diff --git a/futurerestore/futurerestore.cpp b/futurerestore/futurerestore.cpp index fc953838..925f6b19 100644 --- a/futurerestore/futurerestore.cpp +++ b/futurerestore/futurerestore.cpp @@ -59,6 +59,10 @@ #define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL futurerestore::futurerestore(){ + futurerestore(false); +} + +futurerestore::futurerestore(bool is32bit) : _is32bit(is32bit) { _client = idevicerestore_client_new(); if (_client == NULL) throw std::string("could not create idevicerestore client\n"); @@ -145,9 +149,13 @@ plist_t futurerestore::nonceMatchesApTickets(){ vectornonces; - for (int i=0; i< _im4ms.size(); i++){ - if (memcmp(realnonce, (unsigned const char*)getNonceFromIM4M(_im4ms[i],NULL), realNonceSize) == 0) return _aptickets[i]; - } + if (!_is32bit){ + for (int i=0; i< _im4ms.size(); i++){ + if (memcmp(realnonce, (unsigned const char*)getNonceFromIM4M(_im4ms[i],NULL), realNonceSize) == 0) return _aptickets[i]; + } + }else + reterror(-71, "nonceMatchesApTickets is not supported for 32bit devices!\n"); + return NULL; } @@ -305,7 +313,15 @@ int futurerestore::doRestore(const char *ipsw, bool noerase){ } info("Identified device as %s, %s\n", client->device->hardware_model, client->device->product_type); - if (!(client->tss = nonceMatchesApTickets())) reterror(-20, "Devicenonce does not match APTicket nonce\n"); + if (skipAPTicketChecks && _is32bit) { + info("[WARNING] skipping APNonce check. If devicenonce doesn't match ticketnonce, the restore will fail!\n"); + if (_im4ms.size() != 1) + reterror(-72, "ERROR: user selected to skip APNonce checks but specified more than one APTicket.\n"\ + "Without inspecting APTickets it is not possible to choose the correct one, therfore this feature is disabled.\n" + "Either re-enable APTicket checks, or only pass one APTicket\n"); + client->tss = _aptickets[0]; + }else if (!(client->tss = nonceMatchesApTickets())) + reterror(-20, "Devicenonce does not match APTicket nonce\n"); // verify if ipsw file exists @@ -336,48 +352,52 @@ int futurerestore::doRestore(const char *ipsw, bool noerase){ if (!(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, noerase))) reterror(-5,"ERROR: Unable to find any build identities for IPSW\n"); - if (!(sep_build_identity = getBuildidentityWithBoardconfig(_sepbuildmanifest, client->device->hardware_model, noerase))) + if (!_is32bit && !(sep_build_identity = getBuildidentityWithBoardconfig(_sepbuildmanifest, client->device->hardware_model, noerase))) reterror(-5,"ERROR: Unable to find any build identities for SEP\n"); //this is the buildidentity used for restore plist_t manifest = plist_dict_get_item(build_identity, "Manifest"); - printf("checking APTicket to be valid for this restore...\n"); - const char * im4m = nonceMatchesIM4Ms(); - - uint64_t deviceEcid = getDeviceEcid(); - uint64_t im4mEcid = getEcidFromIM4M(im4m); - if (!im4mEcid) - reterror(-46, "Failed to read ECID from APTicket\n"); - - if (im4mEcid != deviceEcid) { - error("ECID inside APTicket does not match device ECID\n"); - printf("APTicket is valid for %16llx but device is %16llx\n",im4mEcid,deviceEcid); - reterror(-45, "APTicket can't be used for restoring this device\n"); - }else - printf("Verified ECID in APTicket matches device ECID\n"); - - plist_t ticketIdentity = getBuildIdentityForIM4M(im4m, buildmanifest); - //TODO: make this nicer! - //for now a simple pointercompare should be fine, because both plist_t should point into the same buildidentity inside the buildmanifest - if (ticketIdentity != build_identity ){ - error("BuildIdentity selected for restore does not match APTicket\n\n"); - printf("BuildIdentity selected for restore:\n"); - printGeneralBuildIdentityInformation(build_identity); - printf("\nBuildIdentiy valid for the APTicket:\n"); + if (skipAPTicketChecks && _is32bit) { + info("[WARNING] skipping ECID check. If deviceecid doesn't match ticketecid, the restore will fail!\n"); + }else { + printf("checking APTicket to be valid for this restore...\n"); + const char * im4m = nonceMatchesIM4Ms(); - if (ticketIdentity) printGeneralBuildIdentityInformation(ticketIdentity),putchar('\n'); - else{ - printf("IM4M is not valid for any restore within the Buildmanifest\n"); - printf("This APTicket can't be used for restoring this firmware\n"); - } - reterror(-44, "APTicket can't be used for this restore\n"); - }else{ - if (verifyIM4MSignature(im4m)){ - printf("IM4M signature is not valid!\n"); + uint64_t deviceEcid = getDeviceEcid(); + uint64_t im4mEcid = getEcidFromIM4M(im4m); + if (!im4mEcid) + reterror(-46, "Failed to read ECID from APTicket\n"); + + if (im4mEcid != deviceEcid) { + error("ECID inside APTicket does not match device ECID\n"); + printf("APTicket is valid for %16llx but device is %16llx\n",im4mEcid,deviceEcid); + reterror(-45, "APTicket can't be used for restoring this device\n"); + }else + printf("Verified ECID in APTicket matches device ECID\n"); + + plist_t ticketIdentity = getBuildIdentityForIM4M(im4m, buildmanifest); + //TODO: make this nicer! + //for now a simple pointercompare should be fine, because both plist_t should point into the same buildidentity inside the buildmanifest + if (ticketIdentity != build_identity ){ + error("BuildIdentity selected for restore does not match APTicket\n\n"); + printf("BuildIdentity selected for restore:\n"); + printGeneralBuildIdentityInformation(build_identity); + printf("\nBuildIdentiy valid for the APTicket:\n"); + + if (ticketIdentity) printGeneralBuildIdentityInformation(ticketIdentity),putchar('\n'); + else{ + printf("IM4M is not valid for any restore within the Buildmanifest\n"); + printf("This APTicket can't be used for restoring this firmware\n"); + } reterror(-44, "APTicket can't be used for this restore\n"); + }else{ + if (verifyIM4MSignature(im4m)){ + printf("IM4M signature is not valid!\n"); + reterror(-44, "APTicket can't be used for this restore\n"); + } + printf("Verified APTicket to be valid for this restore\n"); } - printf("Verified APTicket to be valid for this restore\n"); } @@ -396,9 +416,11 @@ int futurerestore::doRestore(const char *ipsw, bool noerase){ warning("WARNING: we don't have a basebandbuildmanifest, not flashing baseband!\n"); } - plist_t sep_manifest = plist_dict_get_item(sep_build_identity, "Manifest"); - plist_t sep_sep = plist_copy(plist_dict_get_item(sep_manifest, "SEP")); - plist_dict_set_item(manifest, "SEP", sep_sep); + if (!_is32bit) { + plist_t sep_manifest = plist_dict_get_item(sep_build_identity, "Manifest"); + plist_t sep_sep = plist_copy(plist_dict_get_item(sep_manifest, "SEP")); + plist_dict_set_item(manifest, "SEP", sep_sep); + } @@ -521,7 +543,7 @@ int futurerestore::doRestore(const char *ipsw, bool noerase){ reterror(-15, "failed to reconnect to device in recovery (iBEC) mode\n"); //do magic - get_sep_nonce(client, &client->sepnonce, &client->sepnonce_size); + if (!_is32bit) get_sep_nonce(client, &client->sepnonce, &client->sepnonce_size); get_ap_nonce(client, &client->nonce, &client->nonce_size); get_ecid(client, &client->ecid); if (client->mode->index == MODE_RECOVERY) { @@ -542,13 +564,13 @@ int futurerestore::doRestore(const char *ipsw, bool noerase){ } - if (get_tss_response(client, sep_build_identity, &client->septss) < 0) { + if (!_is32bit && get_tss_response(client, sep_build_identity, &client->septss) < 0) { reterror(-11,"ERROR: Unable to get SHSH blobs for SEP\n"); } - if (!_client->sepfwdatasize || !_client->sepfwdata) + if (!_is32bit && (!_client->sepfwdatasize || !_client->sepfwdata)) reterror(-55, "SEP not loaded, refusing to continue"); diff --git a/futurerestore/futurerestore.hpp b/futurerestore/futurerestore.hpp index 396261e9..bc3074f4 100644 --- a/futurerestore/futurerestore.hpp +++ b/futurerestore/futurerestore.hpp @@ -35,6 +35,7 @@ public: class futurerestore { struct idevicerestore_client_t* _client; bool _didInit = false; + bool _is32bit = false; vector _aptickets; vector_im4ms; int _foundnonce = -1; @@ -50,7 +51,9 @@ class futurerestore { const char *_basebandPath; public: + bool skipAPTicketChecks = false; //ignored on 64bit devices futurerestore(); + futurerestore(bool is32bit); bool init(); int getDeviceMode(bool reRequest); uint64_t getDeviceEcid(); diff --git a/futurerestore/main.cpp b/futurerestore/main.cpp index d0c1ef12..741c11b5 100644 --- a/futurerestore/main.cpp +++ b/futurerestore/main.cpp @@ -31,7 +31,9 @@ static struct option longopts[] = { { "debug", no_argument, NULL, 'd' }, { "latest-sep", no_argument, NULL, '0' }, { "latest-baseband", no_argument, NULL, '1' }, - { "no-baseband", no_argument, NULL, '2' }, + { "no-baseband", no_argument, NULL, '2' }, + { "is-32bit", no_argument, NULL, '3' }, + { "skip-ticket-checks", no_argument, NULL, '4' }, //use this for 32bit devices only, this flag is ignored on 64bit devices { NULL, 0, NULL, 0 } }; @@ -40,6 +42,8 @@ static struct option longopts[] = { #define FLAG_LATEST_SEP 1 << 2 #define FLAG_LATEST_BASEBAND 1 << 3 #define FLAG_NO_BASEBAND 1 << 4 +#define FLAG_IS_32_BIT 1 << 5 +#define FLAG_SKIP_TICKET_CHECKS 1 << 6 void cmd_help(){ printf("Usage: futurerestore [OPTIONS] IPSW\n"); @@ -54,6 +58,7 @@ void cmd_help(){ printf(" -u, --update\t\t\tupdate instead of erase install\n"); printf(" --latest-sep\t\tuse latest signed sep instead of manually specifying one(may cause bad restore)\n"); printf(" --latest-baseband\t\tse latest signed baseband instead of manually specifying one(may cause bad restore)\n"); + printf(" --is-32bit\t\tuse this for restoring 32bit device without SEP\n"); printf(" --no-baseband\t\tskip checks and don't flash baseband.\n"); printf(" \t\tWARNING: only use this for device without baseband (eg iPod or some wifi only iPads)\n"); printf("\n"); @@ -121,6 +126,13 @@ int main(int argc, const char * argv[]) { case '2': // long option: "no-baseband"; flags |= FLAG_NO_BASEBAND; break; + case '3': // long option: "is-32bit"; + flags |= FLAG_IS_32_BIT; + printf("[INFO] setting 32bit device flag\n"); + break; + case '4': // long option: "skip-apnonce-match-check"; + flags |= FLAG_SKIP_TICKET_CHECKS; + break; case 'd': // long option: "debug"; can be called as short option idevicerestore_debug = 1; break; @@ -146,7 +158,8 @@ int main(int argc, const char * argv[]) { return -5; } - futurerestore client; + futurerestore client(flags & FLAG_IS_32_BIT); + client.skipAPTicketChecks = (flags & FLAG_SKIP_TICKET_CHECKS); if (!client.init()) reterror(-3,"can't init, no device found\n"); printf("futurerestore init done\n"); @@ -156,7 +169,7 @@ int main(int argc, const char * argv[]) { if (!((apticketPaths.size() && ipsw) && ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND))) - && ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP)))) { + && ((sepPath && sepManifestPath) || (flags & (FLAG_LATEST_SEP|FLAG_IS_32_BIT))) )) { if (!(flags & FLAG_WAIT) || ipsw){ error("missing argument\n"); cmd_help(); @@ -174,13 +187,13 @@ int main(int argc, const char * argv[]) { if (flags & FLAG_LATEST_SEP){ info("user specified to use latest signed sep\n"); client.loadLatestSep(); - }else{ + }else if (!(flags & FLAG_IS_32_BIT)){ client.loadSep(sepPath); client.setSepManifestPath(sepManifestPath); } versVals.basebandMode = kBasebandModeWithoutBaseband; - if (!(isSepManifestSigned = isManifestSignedForDevice(sepManifestPath, &devVals, &versVals))){ + if (!(flags & FLAG_IS_32_BIT) && !(isSepManifestSigned = isManifestSignedForDevice(sepManifestPath, &devVals, &versVals))){ reterror(-3,"sep firmware isn't signed\n"); }