mirror of
https://github.com/tihmstar/futurerestore.git
synced 2025-07-05 15:30:33 +00:00
odysseus64bit
This commit is contained in:
parent
6a3c8c2c9d
commit
d5b65775be
|
@ -44,13 +44,13 @@ AC_CONFIG_SRCDIR([futurerestore])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LIBIPATCHER_REQUIRES_STR="libipatcher >= 57"
|
LIBIPATCHER_REQUIRES_STR="libipatcher >= 61"
|
||||||
LIBPLIST_REQUIRES_STR="libplist >= 2.0.0"
|
LIBPLIST_REQUIRES_STR="libplist >= 2.0.0"
|
||||||
LIBZIP_REQUIRES_STR="libzip >= 0.10"
|
LIBZIP_REQUIRES_STR="libzip >= 0.10"
|
||||||
LIBIMOBILEDEVICE_REQUIRES_STR="libimobiledevice-1.0 >= 1.2.1"
|
LIBIMOBILEDEVICE_REQUIRES_STR="libimobiledevice-1.0 >= 1.2.1"
|
||||||
LIBFRAGMENTZIP_REQUIRES_STR="libfragmentzip >= 47"
|
LIBFRAGMENTZIP_REQUIRES_STR="libfragmentzip >= 47"
|
||||||
LIBIRECOVERY_REQUIRES_STR="libirecovery >= 0.2.0"
|
LIBIRECOVERY_REQUIRES_STR="libirecovery >= 0.2.0"
|
||||||
IMG4TOOL_REQUIRES_STR="libimg4tool >= 159"
|
IMG4TOOL_REQUIRES_STR="libimg4tool >= 162"
|
||||||
LIBGENERAL_REQUIRES_STR="libgeneral >= 26"
|
LIBGENERAL_REQUIRES_STR="libgeneral >= 26"
|
||||||
|
|
||||||
PKG_CHECK_MODULES(libplist, libplist >= 2.0.0)
|
PKG_CHECK_MODULES(libplist, libplist >= 2.0.0)
|
||||||
|
|
|
@ -449,6 +449,8 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
|
||||||
#else
|
#else
|
||||||
if (_client->image4supported) {
|
if (_client->image4supported) {
|
||||||
retassure(libipatcher::has64bitSupport(), "libipatcher was compiled without 64bit support");
|
retassure(libipatcher::has64bitSupport(), "libipatcher was compiled without 64bit support");
|
||||||
|
std::string generator = getGeneratorFromSHSH2(_client->tss);
|
||||||
|
retassure(img4tool::isGeneratorValidForIM4M({_im4ms[0].first,_im4ms[0].second}, generator), "generator returned from device is not valid from apticket");
|
||||||
}
|
}
|
||||||
|
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
|
@ -459,7 +461,6 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
|
||||||
|
|
||||||
irecv_get_mode(_client->dfu->client, &mode);
|
irecv_get_mode(_client->dfu->client, &mode);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
iBSSKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBSS");
|
iBSSKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBSS");
|
||||||
iBECKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBEC");
|
iBECKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBEC");
|
||||||
|
@ -467,7 +468,6 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
|
||||||
reterror("getting keys failed with error: %d (%s). Are keys publicly available?",e.code(),e.what());
|
reterror("getting keys failed with error: %d (%s). Are keys publicly available?",e.code(),e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto iBSS = getIPSWComponent(_client, build_identity, "iBSS");
|
auto iBSS = getIPSWComponent(_client, build_identity, "iBSS");
|
||||||
iBSS = move(libipatcher::patchiBSS((char*)iBSS.first, iBSS.second, iBSSKeys));
|
iBSS = move(libipatcher::patchiBSS((char*)iBSS.first, iBSS.second, iBSSKeys));
|
||||||
|
|
||||||
|
@ -492,31 +492,53 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
|
||||||
retassure(modeIsRecovery, "device not in recovery mode\n");
|
retassure(modeIsRecovery, "device not in recovery mode\n");
|
||||||
}else{
|
}else{
|
||||||
info("Sending %s (%lu bytes)...\n", "iBSS", iBSS.second);
|
info("Sending %s (%lu bytes)...\n", "iBSS", iBSS.second);
|
||||||
// FIXME: Did I do this right????
|
mutex_lock(&_client->device_event_mutex);
|
||||||
irecv_error_t err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBSS.first, (unsigned long)iBSS.second, 1);
|
irecv_error_t err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBSS.first, (unsigned long)iBSS.second, 1);
|
||||||
retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
||||||
|
|
||||||
|
/* reconnect */
|
||||||
|
dfu_client_free(_client);
|
||||||
|
|
||||||
|
debug("Waiting for device to disconnect...\n");
|
||||||
|
cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000);
|
||||||
|
retassure((_client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again");
|
||||||
|
mutex_unlock(&_client->device_event_mutex);
|
||||||
|
|
||||||
|
debug("Waiting for device to reconnect...\n");
|
||||||
|
mutex_lock(&_client->device_event_mutex);
|
||||||
|
cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000);
|
||||||
|
retassure((_client->mode == &idevicerestore_modes[MODE_DFU] || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again");
|
||||||
|
mutex_unlock(&_client->device_event_mutex);
|
||||||
|
|
||||||
|
dfu_client_new(_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_client->build_major > 8) {
|
if (_client->build_major > 8) {
|
||||||
/* reconnect */
|
retassure(!irecv_usb_set_configuration(_client->dfu->client, 1),"ERROR: set configuration failed\n");
|
||||||
dfu_client_free(_client);
|
|
||||||
sleep(3);
|
|
||||||
dfu_client_new(_client);
|
|
||||||
|
|
||||||
retassure(!irecv_usb_set_configuration(_client->dfu->client, 1),"ERROR: set configuration failed\n");
|
|
||||||
|
|
||||||
/* send iBEC */
|
/* send iBEC */
|
||||||
info("Sending %s (%lu bytes)...\n", "iBEC", iBEC.second);
|
info("Sending %s (%lu bytes)...\n", "iBEC", iBEC.second);
|
||||||
// FIXME: Did I do this right????
|
mutex_lock(&_client->device_event_mutex);
|
||||||
irecv_error_t err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBEC.first, (unsigned long)iBEC.second, 1);
|
irecv_error_t err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBEC.first, (unsigned long)iBEC.second, 1);
|
||||||
retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBEC", irecv_strerror(err));
|
||||||
if (modeIsRecovery)
|
printf("waiting for device to reconnect...\n");
|
||||||
|
if (modeIsRecovery){
|
||||||
irecv_send_command(_client->dfu->client, "go");
|
irecv_send_command(_client->dfu->client, "go");
|
||||||
|
recovery_client_free(_client);
|
||||||
|
}else{
|
||||||
|
dfu_client_free(_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("Waiting for device to disconnect...\n");
|
||||||
|
cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000);
|
||||||
|
retassure((_client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
|
||||||
|
mutex_unlock(&_client->device_event_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
dfu_client_free(_client);
|
debug("Waiting for device to reconnect...\n");
|
||||||
|
mutex_lock(&_client->device_event_mutex);
|
||||||
sleep(7);
|
cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000);
|
||||||
|
retassure((_client->mode == &idevicerestore_modes[MODE_RECOVERY] || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not reconnect. Possibly invalid iBEC. Reset device and try again");
|
||||||
|
mutex_unlock(&_client->device_event_mutex);
|
||||||
|
|
||||||
// Reconnect to device, but this time make sure we're not still in DFU mode
|
// Reconnect to device, but this time make sure we're not still in DFU mode
|
||||||
if (recovery_client_new(_client) < 0) {
|
if (recovery_client_new(_client) < 0) {
|
||||||
|
@ -527,16 +549,68 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
|
||||||
reterror("ERROR: Unable to connect to recovery device\n");
|
reterror("ERROR: Unable to connect to recovery device\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning THIS FAILS on iPhone5s 10.3.3 for some reason :/
|
if (_client->image4supported) {
|
||||||
// irecv_get_mode(_client->recovery->client, &mode);
|
char *deviceGen = NULL;
|
||||||
// if (mode == IRECV_K_DFU_MODE) {
|
cleanup([&]{
|
||||||
// if (_client->recovery->client) {
|
safeFree(deviceGen);
|
||||||
// irecv_close(_client->recovery->client);
|
});
|
||||||
// _client->recovery->client = NULL;
|
//IMG4 requires to have a generator set for the device to successfully boot after restore.
|
||||||
// }
|
//set generator now and make sure the nonce is the one we are trying to restore
|
||||||
// reterror("ERROR: Unable to connect to recovery device\n");
|
|
||||||
// }
|
assure(!irecv_send_command(_client->recovery->client, "bgcolor 255 0 0"));
|
||||||
#endif
|
sleep(2); //yes i like displaying colored screens to the user and making him wait for no reason :P
|
||||||
|
|
||||||
|
auto nonceelem = img4tool::getValFromIM4M({_im4ms[0].first,_im4ms[0].second}, 'BNCH');
|
||||||
|
|
||||||
|
printf("APNonce pre-hax:\n");
|
||||||
|
get_ap_nonce(_client, &_client->nonce, &_client->nonce_size);
|
||||||
|
std::string generator = getGeneratorFromSHSH2(_client->tss);
|
||||||
|
|
||||||
|
if (memcmp(_client->nonce, nonceelem.payload(), _client->nonce_size) != 0) {
|
||||||
|
printf("APNonce from device doesn't match IM4M nonce, applying hax...\n");
|
||||||
|
|
||||||
|
assure(_client->tss);
|
||||||
|
printf("Writing generator=%s to nvram!\n",generator.c_str());
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
/* send iBEC */
|
||||||
|
info("Sending %s (%lu bytes)...\n", "iBEC", iBEC.second);
|
||||||
|
mutex_lock(&_client->device_event_mutex);
|
||||||
|
irecv_error_t err = irecv_send_buffer(_client->recovery->client, (unsigned char*)(char*)iBEC.first, (unsigned long)iBEC.second, 1);
|
||||||
|
retassure(err == IRECV_E_SUCCESS,"ERROR: Unable to send %s component: %s\n", "iBEC", irecv_strerror(err));
|
||||||
|
printf("waiting for device to reconnect...\n");
|
||||||
|
retassure(!irecv_send_command(_client->recovery->client, "go"),"failed to re-launch iBEC after nonce hax");
|
||||||
|
recovery_client_free(_client);
|
||||||
|
|
||||||
|
debug("Waiting for device to disconnect...\n");
|
||||||
|
cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000);
|
||||||
|
retassure((_client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not disconnect after sending hax-iBEC in pwn-iBEC mode");
|
||||||
|
mutex_unlock(&_client->device_event_mutex);
|
||||||
|
|
||||||
|
debug("Waiting for device to reconnect...\n");
|
||||||
|
mutex_lock(&_client->device_event_mutex);
|
||||||
|
cond_wait_timeout(&_client->device_event_cond, &_client->device_event_mutex, 10000);
|
||||||
|
retassure((_client->mode == &idevicerestore_modes[MODE_RECOVERY] || (mutex_unlock(&_client->device_event_mutex),0)), "Device did not reconnect after sending hax-iBEC in pwn-iBEC mode");
|
||||||
|
mutex_unlock(&_client->device_event_mutex);
|
||||||
|
|
||||||
|
retassure(!recovery_client_new(_client), "failed to reconnect to recovery after nonce hax");
|
||||||
|
|
||||||
|
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 noncehax. Aborting!");
|
||||||
|
}else{
|
||||||
|
printf("APNonce from device already matches IM4M nonce, no need for extra hax...\n");
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
|
||||||
|
sleep(2); //yes i like displaying colored screens to the user and making him wait for no reason :P
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //HAVE_LIBIPATCHER
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_custom_component(struct idevicerestore_client_t* client, plist_t build_identity, const char* component, unsigned char** data, unsigned int *size){
|
void get_custom_component(struct idevicerestore_client_t* client, plist_t build_identity, const char* component, unsigned char** data, unsigned int *size){
|
||||||
|
@ -596,7 +670,6 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
// verify if ipsw file exists
|
// verify if ipsw file exists
|
||||||
retassure(!access(client->ipsw, F_OK),"ERROR: Firmware file %s does not exist.\n", client->ipsw);
|
retassure(!access(client->ipsw, F_OK),"ERROR: Firmware file %s does not exist.\n", client->ipsw);
|
||||||
|
|
||||||
|
|
||||||
info("Extracting BuildManifest from IPSW\n");
|
info("Extracting BuildManifest from IPSW\n");
|
||||||
{
|
{
|
||||||
int unused;
|
int unused;
|
||||||
|
@ -614,6 +687,7 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
client->image4supported = is_image4_supported(client);
|
client->image4supported = is_image4_supported(client);
|
||||||
info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false");
|
info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false");
|
||||||
|
|
||||||
|
|
||||||
if (_enterPwnRecoveryRequested) //we are in pwnDFU, so we don't need to check nonces
|
if (_enterPwnRecoveryRequested) //we are in pwnDFU, so we don't need to check nonces
|
||||||
client->tss = _aptickets.at(0);
|
client->tss = _aptickets.at(0);
|
||||||
else if (!(client->tss = nonceMatchesApTickets()))
|
else if (!(client->tss = nonceMatchesApTickets()))
|
||||||
|
@ -622,6 +696,11 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
plist_dict_remove_item(client->tss, "BBTicket");
|
plist_dict_remove_item(client->tss, "BBTicket");
|
||||||
plist_dict_remove_item(client->tss, "BasebandFirmware");
|
plist_dict_remove_item(client->tss, "BasebandFirmware");
|
||||||
|
|
||||||
|
if (_enterPwnRecoveryRequested && _client->image4supported) {
|
||||||
|
retassure(plist_dict_get_item(_client->tss, "generator"), "shsh file does not contain generator. But a generator is required for 64bit pwndfu restore");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, _isUpdateInstall),"ERROR: Unable to find any build identities for IPSW\n");
|
retassure(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, _isUpdateInstall),"ERROR: Unable to find any build identities for IPSW\n");
|
||||||
|
|
||||||
if (_client->image4supported) {
|
if (_client->image4supported) {
|
||||||
|
@ -679,7 +758,7 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ticketIdentity) {
|
if (!ticketIdentity) {
|
||||||
printf("Failed to get exact match for build identity, using fallback to ignore certain values");
|
printf("Failed to get exact match for build identity, using fallback to ignore certain values\n");
|
||||||
ticketIdentity = img4tool::getBuildIdentityForIm4m({im4m.first,im4m.second}, buildmanifest, {"RestoreRamDisk","RestoreTrustCache"});
|
ticketIdentity = img4tool::getBuildIdentityForIm4m({im4m.first,im4m.second}, buildmanifest, {"RestoreRamDisk","RestoreTrustCache"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,7 +947,7 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_rerestoreiOS9) {
|
if (_rerestoreiOS9) {
|
||||||
|
mutex_lock(&_client->device_event_mutex);
|
||||||
if (dfu_send_component(client, build_identity, "iBSS") < 0) {
|
if (dfu_send_component(client, build_identity, "iBSS") < 0) {
|
||||||
irecv_close(client->dfu->client);
|
irecv_close(client->dfu->client);
|
||||||
client->dfu->client = NULL;
|
client->dfu->client = NULL;
|
||||||
|
@ -881,8 +960,10 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
debug("Waiting for device to disconnect...\n");
|
debug("Waiting for device to disconnect...\n");
|
||||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||||
retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again");
|
retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again");
|
||||||
|
mutex_unlock(&client->device_event_mutex);
|
||||||
|
|
||||||
debug("Waiting for device to reconnect...\n");
|
debug("Waiting for device to reconnect...\n");
|
||||||
|
mutex_lock(&_client->device_event_mutex);
|
||||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||||
retassure((client->mode == &idevicerestore_modes[MODE_DFU] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again");
|
retassure((client->mode == &idevicerestore_modes[MODE_DFU] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBSS. Reset device and try again");
|
||||||
mutex_unlock(&client->device_event_mutex);
|
mutex_unlock(&client->device_event_mutex);
|
||||||
|
@ -899,12 +980,15 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
dfu_client_free(client);
|
dfu_client_free(client);
|
||||||
|
|
||||||
debug("Waiting for device to disconnect...\n");
|
debug("Waiting for device to disconnect...\n");
|
||||||
|
mutex_lock(&_client->device_event_mutex);
|
||||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||||
retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
|
retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
|
||||||
|
mutex_unlock(&client->device_event_mutex);
|
||||||
|
|
||||||
debug("Waiting for device to reconnect...\n");
|
debug("Waiting for device to reconnect...\n");
|
||||||
|
mutex_lock(&_client->device_event_mutex);
|
||||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||||
retassure((client->mode == &idevicerestore_modes[MODE_RECOVERY] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
|
retassure((client->mode == &idevicerestore_modes[MODE_RECOVERY] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not reconnect. Possibly invalid iBEC. Reset device and try again");
|
||||||
mutex_unlock(&client->device_event_mutex);
|
mutex_unlock(&client->device_event_mutex);
|
||||||
|
|
||||||
|
|
||||||
|
@ -921,9 +1005,9 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (_enterPwnRecoveryRequested){ //if pwnrecovery send all components decrypted, unless we're dealing with iOS 10
|
if (_enterPwnRecoveryRequested){
|
||||||
if (!_client->image4supported) {
|
if (!_client->image4supported) {
|
||||||
if (strncmp(client->version, "10.", 3))
|
if (strncmp(client->version, "10.", 3))//if pwnrecovery send all components decrypted, unless we're dealing with iOS 10
|
||||||
client->recovery_custom_component_function = get_custom_component;
|
client->recovery_custom_component_function = get_custom_component;
|
||||||
}
|
}
|
||||||
}else if (!_rerestoreiOS9){
|
}else if (!_rerestoreiOS9){
|
||||||
|
@ -934,10 +1018,13 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
recovery_client_free(client);
|
recovery_client_free(client);
|
||||||
|
|
||||||
debug("Waiting for device to disconnect...\n");
|
debug("Waiting for device to disconnect...\n");
|
||||||
|
mutex_unlock(&client->device_event_mutex);
|
||||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||||
retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
|
retassure((client->mode == &idevicerestore_modes[MODE_UNKNOWN] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
|
||||||
|
mutex_unlock(&client->device_event_mutex);
|
||||||
|
|
||||||
debug("Waiting for device to reconnect...\n");
|
debug("Waiting for device to reconnect...\n");
|
||||||
|
mutex_unlock(&client->device_event_mutex);
|
||||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 10000);
|
||||||
retassure((client->mode == &idevicerestore_modes[MODE_RECOVERY] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
|
retassure((client->mode == &idevicerestore_modes[MODE_RECOVERY] || (mutex_unlock(&client->device_event_mutex),0)), "Device did not disconnect. Possibly invalid iBEC. Reset device and try again");
|
||||||
mutex_unlock(&client->device_event_mutex);
|
mutex_unlock(&client->device_event_mutex);
|
||||||
|
@ -965,14 +1052,14 @@ void futurerestore::doRestore(const char *ipsw){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_client->image4supported) {
|
if (_client->image4supported) {
|
||||||
|
info("getting sep ticket\n");
|
||||||
retassure(!get_tss_response(client, sep_build_identity, &client->septss), "ERROR: Unable to get SHSH blobs for SEP\n");
|
retassure(!get_tss_response(client, sep_build_identity, &client->septss), "ERROR: Unable to get SHSH blobs for SEP\n");
|
||||||
retassure(_client->sepfwdatasize && _client->sepfwdata, "SEP not loaded, refusing to continue");
|
retassure(_client->sepfwdatasize && _client->sepfwdata, "SEP not loaded, refusing to continue");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mutex_lock(&client->device_event_mutex);
|
mutex_lock(&client->device_event_mutex);
|
||||||
debug("Waiting for device to disconnect...\n");
|
debug("Waiting for device to enter restore mode...\n");
|
||||||
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 180000);
|
cond_wait_timeout(&client->device_event_cond, &client->device_event_mutex, 180000);
|
||||||
retassure((client->mode == &idevicerestore_modes[MODE_RESTORE] || (mutex_unlock(&client->device_event_mutex),0)), "Device failed to enter restore mode");
|
retassure((client->mode == &idevicerestore_modes[MODE_RESTORE] || (mutex_unlock(&client->device_event_mutex),0)), "Device failed to enter restore mode");
|
||||||
mutex_unlock(&client->device_event_mutex);
|
mutex_unlock(&client->device_event_mutex);
|
||||||
|
@ -1378,3 +1465,22 @@ noerror:
|
||||||
return pathStr;
|
return pathStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string futurerestore::getGeneratorFromSHSH2(const plist_t shsh2){
|
||||||
|
plist_t pGenerator = NULL;
|
||||||
|
uint64_t gen = 0;
|
||||||
|
char *genstr = NULL;
|
||||||
|
cleanup([&]{
|
||||||
|
safeFree(genstr);
|
||||||
|
});
|
||||||
|
retassure(pGenerator = plist_dict_get_item(shsh2, "generator"), "shsh file does not contain generator");
|
||||||
|
|
||||||
|
retassure(plist_get_node_type(pGenerator) == PLIST_STRING, "generator has unexpected type! We expect string of the format 0x%16llx");
|
||||||
|
|
||||||
|
plist_get_string_val(pGenerator, &genstr);
|
||||||
|
assure(genstr);
|
||||||
|
|
||||||
|
sscanf(genstr, "0x%16llx",&gen);
|
||||||
|
retassure(gen, "failed to parse generator. Make sure it is in format 0x%16llx");
|
||||||
|
|
||||||
|
return {genstr};
|
||||||
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ public:
|
||||||
static plist_t loadPlistFromFile(const char *path);
|
static plist_t loadPlistFromFile(const char *path);
|
||||||
static void saveStringToFile(const char *str, const char *path);
|
static void saveStringToFile(const char *str, const char *path);
|
||||||
static char *getPathOfElementInManifest(const char *element, const char *manifeststr, const char *model, int isUpdateInstall);
|
static char *getPathOfElementInManifest(const char *element, const char *manifeststr, const char *model, int isUpdateInstall);
|
||||||
|
static std::string getGeneratorFromSHSH2(const plist_t shsh2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue