adding beta support for 32bit devices

This commit is contained in:
tihmstar 2017-03-29 11:32:13 +02:00
parent 9fcf613f8f
commit 422c69cbd9
3 changed files with 87 additions and 49 deletions

View file

@ -59,6 +59,10 @@
#define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL #define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL
futurerestore::futurerestore(){ futurerestore::futurerestore(){
futurerestore(false);
}
futurerestore::futurerestore(bool is32bit) : _is32bit(is32bit) {
_client = idevicerestore_client_new(); _client = idevicerestore_client_new();
if (_client == NULL) throw std::string("could not create idevicerestore client\n"); if (_client == NULL) throw std::string("could not create idevicerestore client\n");
@ -145,9 +149,13 @@ plist_t futurerestore::nonceMatchesApTickets(){
vector<const char*>nonces; vector<const char*>nonces;
for (int i=0; i< _im4ms.size(); i++){ if (!_is32bit){
if (memcmp(realnonce, (unsigned const char*)getNonceFromIM4M(_im4ms[i],NULL), realNonceSize) == 0) return _aptickets[i]; 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; 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); 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 // 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))) if (!(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, noerase)))
reterror(-5,"ERROR: Unable to find any build identities for IPSW\n"); 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"); reterror(-5,"ERROR: Unable to find any build identities for SEP\n");
//this is the buildidentity used for restore //this is the buildidentity used for restore
plist_t manifest = plist_dict_get_item(build_identity, "Manifest"); plist_t manifest = plist_dict_get_item(build_identity, "Manifest");
printf("checking APTicket to be valid for this restore...\n"); if (skipAPTicketChecks && _is32bit) {
const char * im4m = nonceMatchesIM4Ms(); info("[WARNING] skipping ECID check. If deviceecid doesn't match ticketecid, the restore will fail!\n");
}else {
uint64_t deviceEcid = getDeviceEcid(); printf("checking APTicket to be valid for this restore...\n");
uint64_t im4mEcid = getEcidFromIM4M(im4m); const char * im4m = nonceMatchesIM4Ms();
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'); uint64_t deviceEcid = getDeviceEcid();
else{ uint64_t im4mEcid = getEcidFromIM4M(im4m);
printf("IM4M is not valid for any restore within the Buildmanifest\n"); if (!im4mEcid)
printf("This APTicket can't be used for restoring this firmware\n"); reterror(-46, "Failed to read ECID from APTicket\n");
}
reterror(-44, "APTicket can't be used for this restore\n"); if (im4mEcid != deviceEcid) {
}else{ error("ECID inside APTicket does not match device ECID\n");
if (verifyIM4MSignature(im4m)){ printf("APTicket is valid for %16llx but device is %16llx\n",im4mEcid,deviceEcid);
printf("IM4M signature is not valid!\n"); 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"); 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"); warning("WARNING: we don't have a basebandbuildmanifest, not flashing baseband!\n");
} }
plist_t sep_manifest = plist_dict_get_item(sep_build_identity, "Manifest"); if (!_is32bit) {
plist_t sep_sep = plist_copy(plist_dict_get_item(sep_manifest, "SEP")); plist_t sep_manifest = plist_dict_get_item(sep_build_identity, "Manifest");
plist_dict_set_item(manifest, "SEP", sep_sep); 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"); reterror(-15, "failed to reconnect to device in recovery (iBEC) mode\n");
//do magic //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_ap_nonce(client, &client->nonce, &client->nonce_size);
get_ecid(client, &client->ecid); get_ecid(client, &client->ecid);
if (client->mode->index == MODE_RECOVERY) { 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"); 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"); reterror(-55, "SEP not loaded, refusing to continue");

View file

@ -35,6 +35,7 @@ public:
class futurerestore { class futurerestore {
struct idevicerestore_client_t* _client; struct idevicerestore_client_t* _client;
bool _didInit = false; bool _didInit = false;
bool _is32bit = false;
vector<plist_t> _aptickets; vector<plist_t> _aptickets;
vector<char *>_im4ms; vector<char *>_im4ms;
int _foundnonce = -1; int _foundnonce = -1;
@ -50,7 +51,9 @@ class futurerestore {
const char *_basebandPath; const char *_basebandPath;
public: public:
bool skipAPTicketChecks = false; //ignored on 64bit devices
futurerestore(); futurerestore();
futurerestore(bool is32bit);
bool init(); bool init();
int getDeviceMode(bool reRequest); int getDeviceMode(bool reRequest);
uint64_t getDeviceEcid(); uint64_t getDeviceEcid();

View file

@ -31,7 +31,9 @@ static struct option longopts[] = {
{ "debug", no_argument, NULL, 'd' }, { "debug", no_argument, NULL, 'd' },
{ "latest-sep", no_argument, NULL, '0' }, { "latest-sep", no_argument, NULL, '0' },
{ "latest-baseband", no_argument, NULL, '1' }, { "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 } { NULL, 0, NULL, 0 }
}; };
@ -40,6 +42,8 @@ static struct option longopts[] = {
#define FLAG_LATEST_SEP 1 << 2 #define FLAG_LATEST_SEP 1 << 2
#define FLAG_LATEST_BASEBAND 1 << 3 #define FLAG_LATEST_BASEBAND 1 << 3
#define FLAG_NO_BASEBAND 1 << 4 #define FLAG_NO_BASEBAND 1 << 4
#define FLAG_IS_32_BIT 1 << 5
#define FLAG_SKIP_TICKET_CHECKS 1 << 6
void cmd_help(){ void cmd_help(){
printf("Usage: futurerestore [OPTIONS] IPSW\n"); 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(" -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-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(" --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(" --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(" \t\tWARNING: only use this for device without baseband (eg iPod or some wifi only iPads)\n");
printf("\n"); printf("\n");
@ -121,6 +126,13 @@ int main(int argc, const char * argv[]) {
case '2': // long option: "no-baseband"; case '2': // long option: "no-baseband";
flags |= FLAG_NO_BASEBAND; flags |= FLAG_NO_BASEBAND;
break; 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 case 'd': // long option: "debug"; can be called as short option
idevicerestore_debug = 1; idevicerestore_debug = 1;
break; break;
@ -146,7 +158,8 @@ int main(int argc, const char * argv[]) {
return -5; 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"); if (!client.init()) reterror(-3,"can't init, no device found\n");
printf("futurerestore init done\n"); printf("futurerestore init done\n");
@ -156,7 +169,7 @@ int main(int argc, const char * argv[]) {
if (!((apticketPaths.size() && ipsw) if (!((apticketPaths.size() && ipsw)
&& ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND))) && ((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){ if (!(flags & FLAG_WAIT) || ipsw){
error("missing argument\n"); error("missing argument\n");
cmd_help(); cmd_help();
@ -174,13 +187,13 @@ int main(int argc, const char * argv[]) {
if (flags & FLAG_LATEST_SEP){ if (flags & FLAG_LATEST_SEP){
info("user specified to use latest signed sep\n"); info("user specified to use latest signed sep\n");
client.loadLatestSep(); client.loadLatestSep();
}else{ }else if (!(flags & FLAG_IS_32_BIT)){
client.loadSep(sepPath); client.loadSep(sepPath);
client.setSepManifestPath(sepManifestPath); client.setSepManifestPath(sepManifestPath);
} }
versVals.basebandMode = kBasebandModeWithoutBaseband; 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"); reterror(-3,"sep firmware isn't signed\n");
} }