Improve pwned restores, add set-nonce for pwned

This commit is contained in:
Cryptic 2021-10-05 18:07:13 -07:00
parent db1dff1b1b
commit b37542c91c
No known key found for this signature in database
GPG key ID: 6027B509EFE3A76B
4 changed files with 134 additions and 24 deletions

@ -1 +1 @@
Subproject commit 59ca01ebf4a9ed2e019cf5b28cc01707adc283fb
Subproject commit 988bd03b5acd8692b23969a7e24b290abed75b5a

View file

@ -106,7 +106,7 @@ extern "C"{
}
#pragma mark futurerestore
futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu, bool noIBSS, bool noRestore) : _isUpdateInstall(isUpdateInstall), _isPwnDfu(isPwnDfu), _noIBSS(noIBSS), _noRestore(noRestore){
futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu, bool noIBSS, bool cfwRamdisk, bool cfwKernel, bool setNonce, bool noRestore) : _isUpdateInstall(isUpdateInstall), _isPwnDfu(isPwnDfu), _noIBSS(noIBSS), _cfwRamdisk(cfwRamdisk), _cfwKernel(cfwKernel), _setNonce(setNonce), _noRestore(noRestore){
_client = idevicerestore_client_new();
if (_client == NULL) throw std::string("could not create idevicerestore client\n");
@ -582,7 +582,8 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
info("ApNonce pre-hax:\n");
get_ap_nonce(_client, &_client->nonce, &_client->nonce_size);
std::string generator = getGeneratorFromSHSH2(_client->tss);
std::string generator = (_setNonce && _custom_nonce != NULL) ? _custom_nonce : getGeneratorFromSHSH2(_client->tss);
if(memcmp(_client->nonce, nonceelem.payload(), _client->nonce_size) != 0) {
info("ApNonce from device doesn't match IM4M nonce, applying hax...\n");
@ -616,7 +617,7 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
printf("APnonce post-hax:\n");
get_ap_nonce(_client, &_client->nonce, &_client->nonce_size);
assure(!irecv_send_command(_client->recovery->client, "bgcolor 255 255 0"));
retassure(memcmp(_client->nonce, nonceelem.payload(), _client->nonce_size) == 0, "ApNonce from device doesn't match IM4M nonce after applying ApNonce hax. Aborting!");
retassure(_setNonce || memcmp(_client->nonce, nonceelem.payload(), _client->nonce_size) == 0, "ApNonce from device doesn't match IM4M nonce after applying ApNonce hax. Aborting!");
} else {
getDeviceMode(true);
retassure(((dfu_client_new(_client) == IRECV_E_SUCCESS) || (mutex_unlock(&_client->device_event_mutex),0)), "Failed to connect to device in Recovery Mode!");
@ -643,6 +644,12 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
retassure(!irecv_setenv(_client->recovery->client, "com.apple.System.boot-nonce", generator.c_str()), "failed to write generator to nvram");
retassure(!irecv_saveenv(_client->recovery->client), "failed to save nvram");
if(_setNonce) {
info("Successfully set nonce generator: %s, exiting recovery mode...\n", generator.c_str());
exitRecovery();
exit(0);
}
sleep(2);
}
#endif //HAVE_LIBIPATCHER
@ -1947,6 +1954,40 @@ void futurerestore::loadVeridian(const char *veridianDGMPath, const char *veridi
fclose(fveridianfwm);
}
void futurerestore::loadRamdisk(const char *ramdiskPath){
FILE *framdisk = NULL;
retassure(framdisk = fopen(ramdiskPath, "rb"), "failed to read Ramdisk\n");
fseek(framdisk, 0, SEEK_END);
_client->ramdiskdatasize = ftell(framdisk);
fseek(framdisk, 0, SEEK_SET);
retassure(_client->ramdiskdata = (char*)malloc(_client->ramdiskdatasize), "failed to malloc memory for Ramdisk\n");
size_t freadRet=0;
retassure((freadRet = fread(_client->ramdiskdata, 1, _client->ramdiskdatasize, framdisk)) == _client->ramdiskdatasize,
"failed to load Ramdisk. size=%zu but fread returned %zu\n",_client->ramdiskdatasize,freadRet);
fclose(framdisk);
}
void futurerestore::loadKernel(const char *loadKernel){
FILE *fkernel = NULL;
retassure(fkernel = fopen(loadKernel, "rb"), "failed to read Kernel\n");
fseek(fkernel, 0, SEEK_END);
_client->kerneldatasize = ftell(fkernel);
fseek(fkernel, 0, SEEK_SET);
retassure(_client->kerneldata = (char*)malloc(_client->kerneldatasize), "failed to malloc memory for Kernel\n");
size_t freadRet=0;
retassure((freadRet = fread(_client->kerneldata, 1, _client->kerneldatasize, fkernel)) == _client->kerneldatasize,
"failed to load Kernel. size=%zu but fread returned %zu\n",_client->kerneldatasize,freadRet);
fclose(fkernel);
}
void futurerestore::loadSep(const char *sepPath){
FILE *fsep = NULL;
retassure(fsep = fopen(sepPath, "rb"), "failed to read SEP\n");
@ -1972,6 +2013,21 @@ void futurerestore::setBasebandPath(const char *basebandPath){
fclose(fbb);
}
void futurerestore::setRamdiskPath(const char *ramdiskPath) {
FILE *fbb = NULL;
retassure(fbb = fopen(ramdiskPath, "rb"), "failed to read ramdisk");
_ramdiskPath = ramdiskPath;
fclose(fbb);
}
void futurerestore::setKernelPath(const char *kernelPath) {
FILE *fbb = NULL;
retassure(fbb = fopen(kernelPath, "rb"), "failed to read kernel");
_kernelPath = kernelPath;
fclose(fbb);
}
#pragma mark static methods
inline void futurerestore::saveStringToFile(const char *str, const char *path){
FILE *f = NULL;

View file

@ -58,6 +58,9 @@ class futurerestore {
bool _isUpdateInstall = false;
bool _isPwnDfu = false;
bool _noIBSS = false;
bool _cfwRamdisk = false;
bool _cfwKernel = false;
bool _setNonce = false;
bool _noRestore = false;
char *_firmwareJson = NULL;
@ -77,6 +80,10 @@ class futurerestore {
const char *_basebandPath = NULL;
const char *_sepbuildmanifestPath = NULL;
const char *_basebandbuildmanifestPath = NULL;
const char *_ramdiskPath = NULL;
const char *_kernelPath = NULL;
const char *_custom_nonce = NULL;
bool _enterPwnRecoveryRequested = false;
bool _rerestoreiOS9 = false;
@ -85,7 +92,7 @@ class futurerestore {
void enterPwnRecovery2(plist_t build_identity, std::string bootargs = "");
public:
futurerestore(bool isUpdateInstall = false, bool isPwnDfu = false, bool noIBSS = false, bool noRestore = false);
futurerestore(bool isUpdateInstall = false, bool isPwnDfu = false, bool noIBSS = false, bool cfwRamdisk = false, bool cfwKernel = false, bool setNonce = false, bool noRestore = false);
bool init();
int getDeviceMode(bool reRequest);
uint64_t getDeviceEcid();
@ -119,8 +126,13 @@ public:
void loadSE(const char *sePath);
void loadSavage(const char *savagePath[6]);
void loadVeridian(const char *veridianDGMPath, const char *veridianFWMPath);
void loadRamdisk(const char *ramdiskPath);
void loadKernel(const char *kernelPath);
void loadSep(const char *sepPath);
void setBasebandPath(const char *basebandPath);
void setRamdiskPath(const char *ramdiskPath);
void setKernelPath(const char *kernelPath);
void setNonce(const char *custom_nonce){_custom_nonce = custom_nonce;};
bool isUpdateInstall(){return _isUpdateInstall;};
plist_t sepManifest(){return _sepbuildmanifest;};

View file

@ -49,8 +49,10 @@ static struct option longopts[] = {
{ "no-baseband", no_argument, NULL, '2' },
#ifdef HAVE_LIBIPATCHER
{ "use-pwndfu", no_argument, NULL, '3' },
{ "just-boot", optional_argument, NULL, '4' },
{ "no-ibss", no_argument, NULL, '5' },
{ "no-ibss", no_argument, NULL, '4' },
{ "rdsk", required_argument, NULL, '5' },
{ "rkrn", required_argument, NULL, '6' },
{ "set-nonce", optional_argument, NULL, '7' },
#endif
{ NULL, 0, NULL, 0 }
};
@ -62,8 +64,10 @@ static struct option longopts[] = {
#define FLAG_NO_BASEBAND 1 << 4
#define FLAG_IS_PWN_DFU 1 << 5
#define FLAG_NO_IBSS 1 << 6
#define FLAG_NO_RESTORE_FR 1 << 7
#define FLAG_RESTORE_RAMDISK 1 << 7
#define FLAG_RESTORE_KERNEL 1 << 8
#define FLAG_SET_NONCE 1 << 9
#define FLAG_NO_RESTORE_FR 1 << 10
void cmd_help(){
printf("Usage: futurerestore [OPTIONS] iPSW\n");
printf("Allows restoring to non-matching firmware with custom SEP+baseband\n");
@ -79,8 +83,10 @@ void cmd_help(){
#ifdef HAVE_LIBIPATCHER
printf("\nOptions for downgrading with Odysseus:\n");
printf(" --use-pwndfu\t\tRestoring devices with Odysseus method. Device needs to be in pwned DFU mode already\n");
printf(" --just-boot=\"-v\"\t\tTethered booting the device from pwned DFU mode. You can optionally set boot-args\n");
printf(" --no-ibss\t\t\tRestoring devices with Odysseus method. For checkm8/iPwnder32 specifically, bootrom needs to be patched already with unless iPwnder.\n");
printf(" --rdsk PATH\t\tSet custom restore ramdisk for entering restoremode(requires use-pwndfu)\n");
printf(" --rkrn PATH\t\tSet custom restore kernelcache for entering restoremode(requires use-pwndfu)\n");
printf(" --set-nonce NONCE\t\tSet custom nonce then exit recovery(requires use-pwndfu)\n");
#endif
printf("\nOptions for SEP:\n");
@ -131,7 +137,10 @@ int main_r(int argc, const char * argv[]) {
const char *sepPath = NULL;
const char *sepManifestPath = NULL;
const char *bootargs = NULL;
const char *ramdiskPath = NULL;
const char *kernelPath = NULL;
const char *custom_nonce = NULL;
vector<const char*> apticketPaths;
t_devicevals devVals = {0};
@ -142,7 +151,7 @@ int main_r(int argc, const char * argv[]) {
return -1;
}
while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wudez0123", longopts, &optindex)) > 0) {
while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wudez01234567", longopts, &optindex)) > 0) {
switch (opt) {
case 't': // long option: "apticket"; can be called as short option
apticketPaths.push_back(optarg);
@ -178,13 +187,27 @@ int main_r(int argc, const char * argv[]) {
case '3': // long option: "use-pwndfu";
flags |= FLAG_IS_PWN_DFU;
break;
case '4': // long option: "just-boot";
bootargs = (optarg) ? optarg : "";
break;
case '5': // long option: "no-ibss";
case '4': // long option: "no-ibss";
flags |= FLAG_NO_IBSS;
break;
break;
case '5': // long option: "rdsk";
flags |= FLAG_RESTORE_RAMDISK;
ramdiskPath = optarg;
break;
case '6': // long option: "rkrn";
flags |= FLAG_RESTORE_KERNEL;
kernelPath = optarg;
break;
case '7': // long option: "set-nonce";
flags |= FLAG_SET_NONCE;
custom_nonce = (optarg) ? optarg : NULL;
if(custom_nonce != NULL) {
uint64_t gen;
retassure(strlen(custom_nonce) == 16 || strlen(custom_nonce) == 18,"Incorrect nonce length!\n");
sscanf(custom_nonce, "0x%16llx",&gen);
retassure(gen, "failed to parse generator. Make sure it is in format 0x%16llx");
}
break;
#endif
case 'e': // long option: "exit-recovery"; can be called as short option
exitRecovery = true;
@ -220,14 +243,22 @@ int main_r(int argc, const char * argv[]) {
return -5;
}
futurerestore client(flags & FLAG_UPDATE, flags & FLAG_IS_PWN_DFU, flags & FLAG_NO_IBSS, flags & FLAG_NO_RESTORE_FR);
futurerestore client(flags & FLAG_UPDATE, flags & FLAG_IS_PWN_DFU, flags & FLAG_NO_IBSS, flags & FLAG_RESTORE_RAMDISK, flags & FLAG_RESTORE_KERNEL, flags & FLAG_SET_NONCE, flags & FLAG_NO_RESTORE_FR);
retassure(client.init(),"can't init, no device found\n");
printf("futurerestore init done\n");
retassure(!bootargs || (flags & FLAG_IS_PWN_DFU),"--just-boot requires --use-pwndfu\n");
if(flags & FLAG_NO_IBSS)
retassure((flags & FLAG_IS_PWN_DFU),"--no-ibss requires --use-pwndfu\n");
if(flags & FLAG_RESTORE_RAMDISK)
retassure((flags & FLAG_IS_PWN_DFU),"--rdsk requires --use-pwndfu\n");
if(flags & FLAG_RESTORE_KERNEL)
retassure((flags & FLAG_IS_PWN_DFU),"--rkrn requires --use-pwndfu\n");
if(flags & FLAG_SET_NONCE)
retassure((flags & FLAG_IS_PWN_DFU),"--set-nonce requires --use-pwndfu\n");
if(flags & FLAG_RESTORE_RAMDISK)
retassure((flags & FLAG_RESTORE_KERNEL),"--rdsk requires --rkrn\n");
if (exitRecovery) {
client.exitRecovery();
info("Done\n");
@ -260,7 +291,21 @@ int main_r(int argc, const char * argv[]) {
}else{
devVals.deviceModel = (char*)client.getDeviceModelNoCopy();
devVals.deviceBoard = (char*)client.getDeviceBoardNoCopy();
if(flags & FLAG_SET_NONCE) {
client.setNonce(custom_nonce);
}
if(flags & FLAG_RESTORE_RAMDISK) {
client.setRamdiskPath(ramdiskPath);
client.loadRamdisk(ramdiskPath);
}
if(flags & FLAG_RESTORE_KERNEL) {
client.setKernelPath(kernelPath);
client.loadKernel(kernelPath);
}
if (flags & FLAG_LATEST_SEP){
info("user specified to use latest signed SEP\n");
client.loadLatestSep();
@ -316,10 +361,7 @@ int main_r(int argc, const char * argv[]) {
}
try {
if (bootargs)
client.doJustBoot(ipsw,bootargs);
else
client.doRestore(ipsw);
client.doRestore(ipsw);
printf("Done: restoring succeeded!\n");
} catch (tihmstar::exception &e) {
e.dump();