diff --git a/futurerestore/futurerestore.cpp b/futurerestore/futurerestore.cpp index 4dd4faaa..3315f21f 100644 --- a/futurerestore/futurerestore.cpp +++ b/futurerestore/futurerestore.cpp @@ -55,6 +55,7 @@ futurerestore::futurerestore(){ //tsschecker nocache nocache = 1; + _foundnonce = -1; } bool futurerestore::init(){ @@ -122,7 +123,7 @@ void futurerestore::setAutoboot(bool val){ } } -bool futurerestore::nonceMatchesApTicket(){ +plist_t futurerestore::nonceMatchesApTickets(){ if (!_didInit) reterror(-1, "did not init\n"); if (getDeviceMode(true) != MODE_RECOVERY) reterror(-10, "Device not in recovery mode, can't check apnonce\n"); @@ -130,22 +131,30 @@ bool futurerestore::nonceMatchesApTicket(){ int realNonceSize = 0; recovery_get_ap_nonce(_client, &realnonce, &realNonceSize); - return memcmp(realnonce, (unsigned const char*)getNonceFromIM4M(_im4m,NULL), realNonceSize) == 0; + vectornonces; + + for (int i=0; i< _im4ms.size(); i++){ + if (memcmp(realnonce, (unsigned const char*)getNonceFromIM4M(_im4ms[i],NULL), realNonceSize) == 0) return _aptickets[i]; + } + + return NULL; } -void futurerestore::waitForNonce(const char *nonce, size_t nonceSize){ +void futurerestore::waitForNonce(vectornonces, size_t nonceSize){ if (!_didInit) reterror(-1, "did not init\n"); setAutoboot(false); unsigned char* realnonce; int realNonceSize = 0; - info("waiting for nonce: "); - int i = 0; - for (i = 0; i < nonceSize; i++) { - info("%02x ", ((unsigned char *)nonce)[i]); + for (auto nonce : nonces){ + info("waiting for nonce: "); + int i = 0; + for (i = 0; i < nonceSize; i++) { + info("%02x ", ((unsigned char *)nonce)[i]); + } + info("\n"); } - info("\n"); do { if (realNonceSize){ @@ -163,44 +172,57 @@ void futurerestore::waitForNonce(const char *nonce, size_t nonceSize){ info("%02x ", realnonce[i]); } info("\n"); - } while (memcmp(realnonce, (unsigned const char*)nonce, realNonceSize) != 0); + for (int i=0; inonces; + + for (auto im4m : _im4ms){ + nonces.push_back(getNonceFromIM4M(im4m,&nonceSize)); + } + + waitForNonce(nonces,nonceSize); } -void futurerestore::loadAPTicket(const char *apticketPath){ - if (_apticket) plist_free(_apticket), _apticket = NULL; - FILE *f = fopen(apticketPath,"rb"); - if (!f) reterror(-9, "failed to load apticket at %s\n",apticketPath); - fseek(f, 0, SEEK_END); - - size_t fSize = ftell(f); - fseek(f, 0, SEEK_SET); - char *buf = (char*)malloc(fSize); - fread(buf, fSize, 1, f); - fclose(f); - - if (memcmp(buf, "bplist00", 8) == 0) - plist_from_bin(buf, (uint32_t)fSize, &_apticket); - else - plist_from_xml(buf, (uint32_t)fSize, &_apticket); - - safeFree(_im4m); - - plist_t ticket = plist_dict_get_item(_apticket, "ApImg4Ticket"); - uint64_t im4msize=0; - plist_get_data_val(ticket, &_im4m, &im4msize); -} - -void futurerestore::loadAPTicket(string apticketPath){ - loadAPTicket(apticketPath.c_str()); +void futurerestore::loadAPTickets(const vector &apticketPaths){ + for (auto apticketPath : apticketPaths){ + + FILE *f = fopen(apticketPath,"rb"); + if (!f) reterror(-9, "failed to load apticket at %s\n",apticketPath); + fseek(f, 0, SEEK_END); + + size_t fSize = ftell(f); + fseek(f, 0, SEEK_SET); + char *buf = (char*)malloc(fSize); + memset(buf, 0, fSize); + fread(buf, fSize, 1, f); + fclose(f); + + plist_t apticket = NULL; + char *im4m = NULL; + + if (memcmp(buf, "bplist00", 8) == 0) + plist_from_bin(buf, (uint32_t)fSize, &apticket); + else + plist_from_xml(buf, (uint32_t)fSize, &apticket); + + + plist_t ticket = plist_dict_get_item(apticket, "ApImg4Ticket"); + uint64_t im4msize=0; + plist_get_data_val(ticket, &im4m, &im4msize); + + _im4ms.push_back(im4m); + _aptickets.push_back(apticket); + } } int futurerestore::doRestore(const char *ipsw, bool noerase){ @@ -231,7 +253,7 @@ int futurerestore::doRestore(const char *ipsw, bool noerase){ } info("Identified device as %s, %s\n", client->device->hardware_model, client->device->product_type); - if (!nonceMatchesApTicket()) reterror(-20, "Devicenonce does not match APTicket nonce\n"); + if (!(client->tss = nonceMatchesApTickets())) reterror(-20, "Devicenonce does not match APTicket nonce\n"); // verify if ipsw file exists @@ -256,7 +278,6 @@ int futurerestore::doRestore(const char *ipsw, bool noerase){ client->image4supported = is_image4_supported(client); info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false"); - client->tss = _apticket; plist_dict_remove_item(client->tss, "BBTicket"); plist_dict_remove_item(client->tss, "BasebandFirmware"); @@ -470,12 +491,16 @@ futurerestore::~futurerestore(){ normal_client_free(_client); recovery_client_free(_client); idevicerestore_client_free(_client); - safeFree(_im4m); + for (auto im4m : _im4ms){ + safeFree(im4m); + } safeFree(_firmwareJson); safeFree(_firmwareTokens); safeFree(__latestManifest); safeFree(__latestFirmwareUrl); - safePlistFree(_apticket); + for (auto plist : _aptickets){ + safePlistFree(plist); + } } void futurerestore::loadFirmwareTokens(){ @@ -614,7 +639,7 @@ char *futurerestore::getNonceFromIM4M(const char* im4m, size_t *nonceSize){ ret = (char*)malloc(asn1Len(nonceOctet).dataLen); if (ret){ - memcpy(ret, nonceOctet + asn1Len(nonceOctet).sizeBytes, asn1Len(nonceOctet).dataLen); + memcpy(ret, nonceOctet + asn1Len(nonceOctet).sizeBytes, asn1Len(nonceOctet).dataLen); if (nonceSize) *nonceSize = asn1Len(nonceOctet).dataLen; } diff --git a/futurerestore/futurerestore.hpp b/futurerestore/futurerestore.hpp index 8d20759f..5a3e84ec 100644 --- a/futurerestore/futurerestore.hpp +++ b/futurerestore/futurerestore.hpp @@ -12,6 +12,7 @@ #include "config.h" #include #include +#include #include "idevicerestore.h" #include "jsmn.h" @@ -33,8 +34,9 @@ public: class futurerestore { struct idevicerestore_client_t* _client; bool _didInit = false; - plist_t _apticket = NULL; - char *_im4m = NULL; + vector _aptickets; + vector_im4ms; + int _foundnonce = -1; char *_firmwareJson = NULL; jsmntok_t *_firmwareTokens = NULL;; @@ -55,11 +57,10 @@ public: void putDeviceIntoRecovery(); void setAutoboot(bool val); void waitForNonce(); - void waitForNonce(const char *nonce, size_t nonceSize); - void loadAPTicket(const char *apticketPath); - void loadAPTicket(string apticketPath); + void waitForNonce(vectornonces, size_t nonceSize); + void loadAPTickets(const vector &apticketPaths); - bool nonceMatchesApTicket(); + plist_t nonceMatchesApTickets(); void loadFirmwareTokens(); const char *getConnectedDeviceModel(); diff --git a/futurerestore/main.cpp b/futurerestore/main.cpp index ede05805..8f9d5afb 100644 --- a/futurerestore/main.cpp +++ b/futurerestore/main.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "futurerestore.hpp" #include "all_tsschecker.h" #include "tsschecker.h" @@ -65,12 +66,13 @@ int main(int argc, const char * argv[]) { int isBasebandSigned = 0; const char *ipsw = NULL; - const char *apticketPath = NULL; const char *basebandPath = NULL; const char *basebandManifestPath = NULL; const char *sepPath = NULL; const char *sepManifestPath = NULL; + vector apticketPaths; + t_devicevals devVals; t_iosVersion versVals; memset(&devVals, 0, sizeof(devVals)); @@ -84,7 +86,7 @@ int main(int argc, const char * argv[]) { while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wud01", longopts, &optindex)) > 0) { switch (opt) { case 't': // long option: "apticket"; can be called as short option - apticketPath = optarg; + apticketPaths.push_back(optarg); break; case 'b': // long option: "baseband"; can be called as short option basebandPath = optarg; @@ -128,9 +130,9 @@ int main(int argc, const char * argv[]) { futurerestore client; if (!client.init()) reterror(-3,"can't init, no device found\n"); - if (apticketPath) client.loadAPTicket(apticketPath); + if (apticketPaths.size()) client.loadAPTickets(apticketPaths); - if (!((apticketPath && ipsw) + if (!((apticketPaths.size() && ipsw) && ((basebandPath && basebandManifestPath) || (flags & FLAG_LATEST_BASEBAND)) && ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP)))) { if (!(flags & FLAG_WAIT) || ipsw){