mirror of
https://github.com/tihmstar/futurerestore.git
synced 2024-12-22 17:35:29 +00:00
adding beta support for 32bit devices
This commit is contained in:
parent
9fcf613f8f
commit
422c69cbd9
|
@ -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(){
|
|||
|
||||
vector<const char*>nonces;
|
||||
|
||||
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");
|
||||
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
class futurerestore {
|
||||
struct idevicerestore_client_t* _client;
|
||||
bool _didInit = false;
|
||||
bool _is32bit = false;
|
||||
vector<plist_t> _aptickets;
|
||||
vector<char *>_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();
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue