diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/idevicerestore.c | 593 |
1 files changed, 383 insertions, 210 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c index ec449d9..f9fd116 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -222,203 +222,33 @@ int main(int argc, char* argv[]) { if (send_ibec(ipsw, tss_response) < 0) { error("ERROR: Unable to send iBEC\n"); - return -1; - } - - // Reconnect to iBEC - info("Connecting to iBEC\n"); - recovery_error = irecv_open(&recovery); - while (recovery_error != IRECV_E_SUCCESS) { - sleep(1); - info("Retrying connection...\n"); - recovery_error = irecv_open(&recovery); - if (recovery_error == IRECV_E_SUCCESS) { - break; - } - } - - // Sending DeviceTree - info("Extracting DeviceTree from IPSW\n"); - plist_t devicetree_entry = plist_dict_get_item(tss_response, "RestoreDeviceTree"); - if (!devicetree_entry || plist_get_node_type(devicetree_entry) != PLIST_DICT) { - error("ERROR: Unable to find DeviceTree entry in TSS response\n"); plist_free(tss_response); - irecv_close(recovery); return -1; } - - char* devicetree_path = NULL; - plist_t devicetree_path_node = plist_dict_get_item(devicetree_entry, "Path"); - if (!devicetree_path_node || plist_get_node_type(devicetree_path_node) != PLIST_STRING) { - error("ERROR: Unable to find DeviceTree path in entry\n"); - plist_free(tss_response); - plist_free(devicetree_entry); - irecv_close(recovery); - recovery = NULL; - return -1; - } - plist_get_string_val(devicetree_path_node, &devicetree_path); - - char* devicetree_blob = NULL; - uint64_t devicetree_blob_size = 0; - plist_t devicetree_blob_node = plist_dict_get_item(devicetree_entry, "Blob"); - if (!devicetree_blob_node || plist_get_node_type(devicetree_blob_node) != PLIST_DATA) { - error("ERROR: Unable to find DeviceTree blob in entry\n"); - plist_free(tss_response); - plist_free(devicetree_entry); - irecv_close(recovery); - recovery = NULL; - return -1; - } - plist_get_data_val(devicetree_blob_node, &devicetree_blob, &devicetree_blob_size); - plist_free(devicetree_blob_node); - plist_free(devicetree_entry); - - ipsw_file* devicetree = ipsw_extract_file(ipsw, devicetree_path); - if (devicetree == NULL) { - error("ERROR: Unable to extract %s from IPSW\n", devicetree_path); - irecv_close(recovery); - recovery = NULL; - return -1; - } - - img3_file* devicetree_img3 = img3_parse_file(devicetree->data, devicetree->size); - if (devicetree_img3 == NULL) { - error("ERROR: Unable to parse IMG3: %s\n", devicetree_path); - irecv_close(recovery); - ipsw_free_file(devicetree); - recovery = NULL; - return -1; - } - ipsw_free_file(devicetree); - - img3_replace_signature(devicetree_img3, devicetree_blob); - free(devicetree_blob); - - int devicetree_size = 0; - char* devicetree_data = NULL; - img3_get_data(devicetree_img3, &devicetree_data, &devicetree_size); - write_file("devicetree.img3", devicetree_data, devicetree_size); - recovery_error = irecv_send_buffer(recovery, devicetree_data, devicetree_size); - if (recovery_error != IRECV_E_SUCCESS) { - error("ERROR: Unable to send IMG3: %s\n", devicetree_path); - irecv_close(recovery); - img3_free(devicetree_img3); - recovery = NULL; - return -1; - } - img3_free(devicetree_img3); - - recovery_error = irecv_send_command(recovery, "devicetree"); - if (recovery_error != IRECV_E_SUCCESS) { - error("ERROR: Unable to execute DeviceTree\n"); - irecv_close(recovery); - img3_free(devicetree_img3); - recovery = NULL; - return -1; - } - free(devicetree_data); sleep(1); - // Sending RestoreRamdisk - info("Extracting Ramdisk from IPSW\n"); - plist_t ramdisk_entry = plist_dict_get_item(tss_response, "RestoreRamDisk"); - if (!ramdisk_entry || plist_get_node_type(ramdisk_entry) != PLIST_DICT) { - error("ERROR: Unable to find RestoreRamDisk entry in TSS response\n"); + if (send_devicetree(ipsw, tss_response) < 0) { + error("ERROR: Unable to send DeviceTree\n"); plist_free(tss_response); - irecv_close(recovery); return -1; } - char* ramdisk_path = NULL; - plist_t ramdisk_path_node = plist_dict_get_item(ramdisk_entry, "Path"); - if (!ramdisk_path_node || plist_get_node_type(ramdisk_path_node) != PLIST_STRING) { - error("ERROR: Unable to find RestoreRamDisk path in entry\n"); + if (send_ramdisk(ipsw, tss_response) < 0) { + error("ERROR: Unable to send Ramdisk\n"); plist_free(tss_response); - plist_free(ramdisk_entry); - irecv_close(recovery); - recovery = NULL; return -1; } - plist_get_string_val(ramdisk_path_node, &ramdisk_path); - char* ramdisk_blob = NULL; - uint64_t ramdisk_blob_size = 0; - plist_t ramdisk_blob_node = plist_dict_get_item(ramdisk_entry, "Blob"); - if (!ramdisk_blob_node || plist_get_node_type(ramdisk_blob_node) != PLIST_DATA) { - error("ERROR: Unable to find RestoreRamdisk blob in entry\n"); - plist_free(tss_response); - plist_free(ramdisk_entry); - irecv_close(recovery); - recovery = NULL; - return -1; - } - plist_get_data_val(ramdisk_blob_node, &ramdisk_blob, &ramdisk_blob_size); - plist_free(ramdisk_blob_node); - plist_free(ramdisk_entry); - - ipsw_file* ramdisk = ipsw_extract_file(ipsw, ramdisk_path); - if (ramdisk == NULL) { - error("ERROR: Unable to extract %s from IPSW\n", ramdisk_path); - irecv_close(recovery); - recovery = NULL; - return -1; - } - - img3_file* ramdisk_img3 = img3_parse_file(ramdisk->data, ramdisk->size); - if (ramdisk_img3 == NULL) { - error("ERROR: Unable to parse IMG3: %s\n", ramdisk_path); - irecv_close(recovery); - ipsw_free_file(ramdisk); - recovery = NULL; - return -1; - } - ipsw_free_file(ramdisk); - - img3_replace_signature(ramdisk_img3, ramdisk_blob); - free(ramdisk_blob); - - int ramdisk_size = 0; - char* ramdisk_data = NULL; - img3_get_data(ramdisk_img3, &ramdisk_data, &ramdisk_size); - write_file("ramdisk.dmg", ramdisk_data, ramdisk_size); - recovery_error = irecv_send_buffer(recovery, ramdisk_data, ramdisk_size); - if (recovery_error != IRECV_E_SUCCESS) { - error("ERROR: Unable to send IMG3: %s\n", ramdisk_path); - irecv_close(recovery); - img3_free(ramdisk_img3); - recovery = NULL; - return -1; - } - img3_free(ramdisk_img3); - - recovery_error = irecv_send_command(recovery, "ramdisk"); - if (recovery_error != IRECV_E_SUCCESS) { - error("ERROR: Unable to execute DeviceTree\n"); - irecv_close(recovery); - recovery = NULL; - return -1; - } - free(ramdisk_data); - irecv_close(recovery); - recovery = NULL; - - printf("Please unplug your device, then plug it back in, hit any key to continue\n"); + printf("Please unplug your device, then plug it back in\n"); + printf("Hit any key to continue..."); getchar(); - // Reconnect to iBEC - recovery_error = irecv_open(&recovery); - while (recovery_error != IRECV_E_SUCCESS) { - sleep(1); - info("Retrying connection...\n"); - recovery_error = irecv_open(&recovery); - if (recovery_error == IRECV_E_SUCCESS) { - break; - } + if (send_kernelcache(ipsw, tss_response) < 0) { + error("ERROR: Unable to send KernelCache\n"); + plist_free(tss_response); + return -1; } - irecv_close(recovery); - recovery = NULL; plist_free(tss_response); return 0; } @@ -470,25 +300,19 @@ int get_tss_data(plist_t tss, const char* entry, char** ppath, char** pblob) { plist_t path_node = plist_dict_get_item(node, "Path"); if (!path_node || plist_get_node_type(path_node) != PLIST_STRING) { error("ERROR: Unable to find %s path in entry\n", entry); - plist_free(node); return -1; } plist_get_string_val(path_node, &path); - plist_free(path_node); char* blob = NULL; uint64_t blob_size = 0; plist_t blob_node = plist_dict_get_item(node, "Blob"); if (!blob_node || plist_get_node_type(blob_node) != PLIST_DATA) { error("ERROR: Unable to find %s blob in entry\n", entry); - plist_free(node); free(path); return -1; } - plist_get_data_val(blob_node, &blob, &blob_size); - plist_free(blob_node); - plist_free(node); *ppath = path; *pblob = blob; @@ -497,23 +321,29 @@ int get_tss_data(plist_t tss, const char* entry, char** ppath, char** pblob) { int send_ibec(char* ipsw, plist_t tss) { int i = 0; + irecv_error_t error = 0; irecv_client_t client = NULL; - info("Connecting to iBoot...\n"); - irecv_error_t error = irecv_open(&client); + info("Sending iBEC...\n"); for (i = 10; i > 0; i--) { + error = irecv_open(&client); if (error == IRECV_E_SUCCESS) { irecv_send_command(client, "setenv auto-boot true"); irecv_send_command(client, "saveenv"); break; } - sleep(1); + + if (i == 0) { + error("Unable to connect to iBoot\n"); + return -1; + } + + sleep(2); info("Retrying connection...\n"); - error = irecv_open(&client); } char* path = NULL; char* blob = NULL; - info("Extracting iBEC data from TSS response\n"); + info("Extracting data from TSS response\n"); if (get_tss_data(tss, "iBEC", &path, &blob) < 0) { error("ERROR: Unable to get data for TSS entry\n"); irecv_close(client); @@ -571,8 +401,16 @@ int send_ibec(char* ipsw, plist_t tss) { return -1; } - path = strrchr(path, '/'); - write_file(path + 1, data, size); + if (idevicerestore_debug) { + char* out = strrchr(path, '/'); + if (out != NULL) { + out++; + } else { + out = path; + } + write_file(out, data, size); + } + error = irecv_send_buffer(client, data, size); if (error != IRECV_E_SUCCESS) { error("ERROR: Unable to send IMG3: %s\n", path); @@ -605,61 +443,396 @@ int send_ibec(char* ipsw, plist_t tss) { return -1; } - irecv_close(client); - client = NULL; + if (client) { + irecv_close(client); + client = NULL; + } return 0; } int send_devicetree(char* ipsw, plist_t tss) { int i = 0; - info("Sending devicetree\n"); + irecv_error_t error = 0; irecv_client_t client = NULL; - irecv_error_t error = irecv_open(&client); + info("Sending DeviceTree...\n"); for (i = 10; i > 0; i--) { + error = irecv_open(&client); if (error == IRECV_E_SUCCESS) { break; } - sleep(1); + + if (i == 0) { + error("Unable to connect to iBEC\n"); + return -1; + } + + sleep(3); info("Retrying connection...\n"); - error = irecv_open(&client); } - irecv_close(client); + char* path = NULL; + char* blob = NULL; + info("Extracting data from TSS response\n"); + if (get_tss_data(tss, "DeviceTree", &path, &blob) < 0) { + error("ERROR: Unable to get data for TSS entry\n"); + irecv_close(client); + client = NULL; + return -1; + } + + info("Extracting %s from %s\n", path, ipsw); + ipsw_file* devicetree = ipsw_extract_file(ipsw, path); + if (devicetree == NULL) { + error("ERROR: Unable to extract %s from %s\n", path, ipsw); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + + img3_file* img3 = img3_parse_file(devicetree->data, devicetree->size); + if (img3 == NULL) { + error("ERROR: Unable to parse IMG3: %s\n", path); + ipsw_free_file(devicetree); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + if (devicetree) { + ipsw_free_file(devicetree); + devicetree = NULL; + } + + if (img3_replace_signature(img3, blob) < 0) { + error("ERROR: Unable to replace IMG3 signature\n"); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + if (blob) { + free(blob); + blob = NULL; + } + + int size = 0; + char* data = NULL; + if (img3_get_data(img3, &data, &size) < 0) { + error("ERROR: Unable to reconstruct IMG3\n"); + irecv_close(client); + img3_free(img3); + client = NULL; + free(path); + return -1; + } + + if (idevicerestore_debug) { + char* out = strrchr(path, '/'); + if (out != NULL) { + out++; + } else { + out = path; + } + write_file(out, data, size); + } + + error = irecv_send_buffer(client, data, size); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to send IMG3: %s\n", path); + irecv_close(client); + img3_free(img3); + client = NULL; + free(data); + free(path); + return -1; + } + if (img3) { + img3_free(img3); + img3 = NULL; + } + if (data) { + free(data); + data = NULL; + } + if (path) { + free(path); + path = NULL; + } + + error = irecv_send_command(client, "devicetree"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to execute DeviceTree\n"); + irecv_close(client); + client = NULL; + free(data); + return -1; + } + + if (client) { + irecv_close(client); + client = NULL; + } return 0; } int send_ramdisk(char* ipsw, plist_t tss) { int i = 0; - info("Sending ramdisk\n"); + irecv_error_t error = 0; irecv_client_t client = NULL; - irecv_error_t error = irecv_open(&client); + info("Sending Ramdisk...\n"); for (i = 10; i > 0; i--) { + error = irecv_open(&client); if (error == IRECV_E_SUCCESS) { break; } - sleep(1); + + if (i == 0) { + error("Unable to connect to iBEC\n"); + return -1; + } + + sleep(3); info("Retrying connection...\n"); - error = irecv_open(&client); } - irecv_close(client); + char* path = NULL; + char* blob = NULL; + info("Extracting data from TSS response\n"); + if (get_tss_data(tss, "RestoreRamDisk", &path, &blob) < 0) { + error("ERROR: Unable to get data for TSS entry\n"); + irecv_close(client); + client = NULL; + return -1; + } + + info("Extracting %s from %s\n", path, ipsw); + ipsw_file* ramdisk = ipsw_extract_file(ipsw, path); + if (ramdisk == NULL) { + error("ERROR: Unable to extract %s from %s\n", path, ipsw); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + + img3_file* img3 = img3_parse_file(ramdisk->data, ramdisk->size); + if (img3 == NULL) { + error("ERROR: Unable to parse IMG3: %s\n", path); + ipsw_free_file(ramdisk); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + if (ramdisk) { + ipsw_free_file(ramdisk); + ramdisk = NULL; + } + + if (img3_replace_signature(img3, blob) < 0) { + error("ERROR: Unable to replace IMG3 signature\n"); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + if (blob) { + free(blob); + blob = NULL; + } + + int size = 0; + char* data = NULL; + if (img3_get_data(img3, &data, &size) < 0) { + error("ERROR: Unable to reconstruct IMG3\n"); + irecv_close(client); + img3_free(img3); + client = NULL; + free(path); + return -1; + } + + if (idevicerestore_debug) { + char* out = strrchr(path, '/'); + if (out != NULL) { + out++; + } else { + out = path; + } + write_file(out, data, size); + } + + error = irecv_send_buffer(client, data, size); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to send IMG3: %s\n", path); + irecv_close(client); + img3_free(img3); + client = NULL; + free(data); + free(path); + return -1; + } + if (img3) { + img3_free(img3); + img3 = NULL; + } + if (data) { + free(data); + data = NULL; + } + if (path) { + free(path); + path = NULL; + } + + error = irecv_send_command(client, "ramdisk"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to execute Ramdisk\n"); + irecv_close(client); + client = NULL; + free(data); + return -1; + } + + if (client) { + irecv_close(client); + client = NULL; + } return 0; } int send_kernelcache(char* ipsw, plist_t tss) { int i = 0; - info("Sending kernelcache\n"); + irecv_error_t error = 0; irecv_client_t client = NULL; - irecv_error_t error = irecv_open(&client); + info("Sending KernelCache...\n"); for (i = 10; i > 0; i--) { + error = irecv_open(&client); if (error == IRECV_E_SUCCESS) { break; } - sleep(1); + + if (i == 0) { + error("Unable to connect to iBEC\n"); + return -1; + } + + sleep(3); info("Retrying connection...\n"); - error = irecv_open(&client); } - irecv_close(client); + char* path = NULL; + char* blob = NULL; + info("Extracting data from TSS response\n"); + if (get_tss_data(tss, "KernelCache", &path, &blob) < 0) { + error("ERROR: Unable to get data for TSS entry\n"); + irecv_close(client); + client = NULL; + return -1; + } + + info("Extracting %s from %s\n", path, ipsw); + ipsw_file* kernelcache = ipsw_extract_file(ipsw, path); + if (kernelcache == NULL) { + error("ERROR: Unable to extract %s from %s\n", path, ipsw); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + + img3_file* img3 = img3_parse_file(kernelcache->data, kernelcache->size); + if (img3 == NULL) { + error("ERROR: Unable to parse IMG3: %s\n", path); + ipsw_free_file(kernelcache); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + if (kernelcache) { + ipsw_free_file(kernelcache); + kernelcache = NULL; + } + + if (img3_replace_signature(img3, blob) < 0) { + error("ERROR: Unable to replace IMG3 signature\n"); + irecv_close(client); + client = NULL; + free(path); + free(blob); + return -1; + } + if (blob) { + free(blob); + blob = NULL; + } + + int size = 0; + char* data = NULL; + if (img3_get_data(img3, &data, &size) < 0) { + error("ERROR: Unable to reconstruct IMG3\n"); + irecv_close(client); + img3_free(img3); + client = NULL; + free(path); + return -1; + } + + if (idevicerestore_debug) { + char* out = strrchr(path, '/'); + if (out != NULL) { + out++; + } else { + out = path; + } + write_file(out, data, size); + } + + error = irecv_send_buffer(client, data, size); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to send IMG3: %s\n", path); + irecv_close(client); + img3_free(img3); + client = NULL; + free(data); + free(path); + return -1; + } + if (img3) { + img3_free(img3); + img3 = NULL; + } + if (data) { + free(data); + data = NULL; + } + if (path) { + free(path); + path = NULL; + } + + error = irecv_send_command(client, "bootx"); + if (error != IRECV_E_SUCCESS) { + error("ERROR: Unable to execute iBEC\n"); + irecv_close(client); + client = NULL; + free(data); + return -1; + } + + if (client) { + irecv_close(client); + client = NULL; + } return 0; } |