diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/idevicerestore.c | 37 | ||||
-rw-r--r-- | src/img3.c | 236 | ||||
-rw-r--r-- | src/img3.h | 7 |
3 files changed, 266 insertions, 14 deletions
diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 0a5e7f1..1c8b24a 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -40,6 +40,7 @@ int idevicerestore_debug = 0; void usage(int argc, char* argv[]); +int write_file(const char* filename, char* data, int size); int main(int argc, char* argv[]) { int opt = 0; @@ -302,7 +303,12 @@ int main(int argc, char* argv[]) { ipsw_free_file(ibec); img3_replace_signature(ibec_img3, ibec_blob); - recovery_error = irecv_send_file(recovery, img3_get_data(ibec_img3)); + + int ibec_size = 0; + char* ibec_data = NULL; + img3_get_data(ibec_img3, &ibec_data, &ibec_size); + write_file("ibec.dfu", ibec_data, ibec_size); + recovery_error = irecv_send_buffer(recovery, ibec_data, ibec_size); if(recovery_error != IRECV_E_SUCCESS) { error("ERROR: Unable to send IMG3: %s\n", ibec_path); irecv_close(recovery); @@ -311,6 +317,16 @@ int main(int argc, char* argv[]) { return -1; } + recovery_error = irecv_send_command(recovery, "go"); + if(recovery_error != IRECV_E_SUCCESS) { + error("ERROR: Unable to execute iBEC\n"); + irecv_close(recovery); + img3_free(ibec_img3); + recovery = NULL; + return -1; + } + + free(ibec_data); irecv_close(recovery); plist_free(tss_response); return 0; @@ -329,3 +345,22 @@ void usage(int argc, char* argv[]) { printf("\n"); exit(1); } + +int write_file(const char* filename, char* data, int size) { + debug("Writing data to %s\n", filename); + FILE* file = fopen(filename, "wb"); + if (file == NULL) { + error("read_file: Unable to open file %s\n", filename); + return -1; + } + + int bytes = fwrite(data, 1, size, file); + fclose(file); + + if(bytes != size) { + error("ERROR: Unable to write entire file: %s: %d %d\n", filename, bytes, size); + return -1; + } + + return size; +} @@ -26,7 +26,7 @@ #include "img3.h" #include "idevicerestore.h" -img3_file* img3_parse_file(unsigned char* data, int size) { +img3_file* img3_parse_file(char* data, int size) { int data_offset = 0; img3_header* header = (img3_header*) data; if(header->signature != kImg3Container) { @@ -107,7 +107,6 @@ img3_file* img3_parse_file(unsigned char* data, int size) { case kKbagElement: if(image->kbag1_element == NULL) { image->kbag1_element = img3_parse_element(&data[data_offset]); - image->kbag1_element = img3_parse_element(&data[data_offset]); if(image->kbag1_element == NULL) { error("ERROR: Unable to parse first KBAG element\n"); img3_free(image); @@ -116,7 +115,6 @@ img3_file* img3_parse_file(unsigned char* data, int size) { } else { image->kbag2_element = img3_parse_element(&data[data_offset]); - image->kbag2_element = img3_parse_element(&data[data_offset]); if(image->kbag2_element == NULL) { error("ERROR: Unable to parse second KBAG element\n"); img3_free(image); @@ -167,9 +165,26 @@ img3_file* img3_parse_file(unsigned char* data, int size) { return image; } -img3_element* img3_parse_element(char* element) { - img3_element_header* element_header = (img3_element_header*) element; - return 1; +img3_element* img3_parse_element(char* data) { + img3_element_header* element_header = (img3_element_header*) data; + img3_element* element = (img3_element*) malloc(sizeof(img3_element)); + if(element == NULL) { + error("ERROR: Unable to allocate memory for IMG3 element\n"); + return NULL; + } + memset(element, '\0', sizeof(img3_element)); + + element->data = (char*) malloc(element_header->full_size); + if(element->data == NULL) { + error("ERROR: Unable to allocate memory for IMG3 element data\n"); + free(element); + return NULL; + } + memcpy(element->data, data, element_header->full_size); + element->header = (img3_element_header*) element->data; + element->type = (img3_element_type) element->header->signature; + + return element; } void img3_free(img3_file* image) { @@ -178,14 +193,215 @@ void img3_free(img3_file* image) { free(image->header); } + if(image->type_element != NULL) { + img3_free_element(image->type_element); + image->type_element = NULL; + } + + if(image->data_element != NULL) { + img3_free_element(image->data_element); + image->data_element = NULL; + } + + if(image->vers_element != NULL) { + img3_free_element(image->vers_element); + image->vers_element = NULL; + } + + if(image->sepo_element != NULL) { + img3_free_element(image->sepo_element); + image->sepo_element = NULL; + } + + if(image->bord_element != NULL) { + img3_free_element(image->bord_element); + image->bord_element = NULL; + } + + if(image->kbag1_element != NULL) { + img3_free_element(image->kbag1_element); + image->kbag1_element = NULL; + } + + if(image->kbag2_element != NULL) { + img3_free_element(image->kbag2_element); + image->kbag2_element = NULL; + } + + if(image->ecid_element != NULL) { + img3_free_element(image->ecid_element); + image->ecid_element = NULL; + } + + if(image->shsh_element != NULL) { + img3_free_element(image->shsh_element); + image->shsh_element = NULL; + } + + if(image->cert_element != NULL) { + img3_free_element(image->cert_element); + image->cert_element = NULL; + } + free(image); + image = NULL; } } -void img3_replace_signature(img3_file* image, char* signature) { - return; +void img3_free_element(img3_element* element) { + if(element != NULL) { + if(element->data != NULL) { + free(element->data); + element->data = NULL; + } + free(element); + element = NULL; + } } -char* img3_get_data(img3_file* image) { - return NULL; +int img3_replace_signature(img3_file* image, char* signature) { + int offset = 0; + img3_element* ecid = img3_parse_element(&signature[offset]); + if(ecid == NULL || ecid->type != kEcidElement) { + error("ERROR: Unable to find ECID element in signature\n"); + return -1; + } + offset += ecid->header->full_size; + + img3_element* shsh = img3_parse_element(&signature[offset]); + if(shsh == NULL || shsh->type != kShshElement) { + error("ERROR: Unable to find SHSH element in signature\n"); + return -1; + } + offset += shsh->header->full_size; + + img3_element* cert = img3_parse_element(&signature[offset]); + if(cert == NULL || cert->type != kCertElement) { + error("ERROR: Unable to find CERT element in signature\n"); + return -1; + } + offset += cert->header->full_size; + + if(image->ecid_element != NULL) { + img3_free_element(image->ecid_element); + } + image->ecid_element = ecid; + + if(image->shsh_element != NULL) { + img3_free_element(image->shsh_element); + } + image->shsh_element = shsh; + + if(image->cert_element != NULL) { + img3_free_element(image->cert_element); + } + image->cert_element = cert; + + return 0; +} + +int img3_get_data(img3_file* image, char** pdata, int* psize) { + int offset = 0; + int size = sizeof(img3_header); + + // Add up the size of the image first so we can allocate our memory + if(image->type_element != NULL) { + size += image->type_element->header->full_size; + } + if(image->data_element != NULL) { + size += image->data_element->header->full_size; + } + if(image->vers_element != NULL) { + size += image->vers_element->header->full_size; + } + if(image->sepo_element != NULL) { + size += image->sepo_element->header->full_size; + } + if(image->bord_element != NULL) { + size += image->bord_element->header->full_size; + } + if(image->kbag1_element != NULL) { + size += image->kbag1_element->header->full_size; + } + if(image->kbag2_element != NULL) { + size += image->kbag2_element->header->full_size; + } + if(image->ecid_element != NULL) { + size += image->ecid_element->header->full_size; + } + if(image->shsh_element != NULL) { + size += image->shsh_element->header->full_size; + } + if(image->cert_element != NULL) { + size += image->cert_element->header->full_size; + } + + char* data = (char*) malloc(size); + if(data == NULL) { + error("ERROR: Unable to allocate memory for IMG3 data\n"); + return -1; + } + + // Add data to our new header (except shsh_offset) + img3_header* header = (img3_header*) data; + header->full_size = size; + header->signature = image->header->signature; + header->data_size = size - sizeof(img3_header); + header->image_type = image->header->image_type; + offset += sizeof(img3_header); + + // Copy each section over to the new buffer + if(image->type_element != NULL) { + memcpy(&data[offset], image->type_element->data, image->type_element->header->full_size); + offset += image->type_element->header->full_size; + } + if(image->data_element != NULL) { + memcpy(&data[offset], image->data_element->data, image->data_element->header->full_size); + offset += image->data_element->header->full_size; + } + if(image->vers_element != NULL) { + memcpy(&data[offset], image->vers_element->data, image->vers_element->header->full_size); + offset += image->vers_element->header->full_size; + } + if(image->sepo_element != NULL) { + memcpy(&data[offset], image->sepo_element->data, image->sepo_element->header->full_size); + offset += image->sepo_element->header->full_size; + } + if(image->bord_element != NULL) { + memcpy(&data[offset], image->bord_element->data, image->bord_element->header->full_size); + offset += image->bord_element->header->full_size; + } + if(image->kbag1_element != NULL) { + memcpy(&data[offset], image->kbag1_element->data, image->kbag1_element->header->full_size); + offset += image->kbag1_element->header->full_size; + } + if(image->kbag2_element != NULL) { + memcpy(&data[offset], image->kbag2_element->data, image->kbag2_element->header->full_size); + offset += image->kbag2_element->header->full_size; + } + if(image->ecid_element != NULL) { + memcpy(&data[offset], image->ecid_element->data, image->ecid_element->header->full_size); + offset += image->ecid_element->header->full_size; + } + if(image->shsh_element != NULL) { + memcpy(&data[offset], image->shsh_element->data, image->shsh_element->header->full_size); + header->shsh_offset = offset - sizeof(img3_header); + offset += image->shsh_element->header->full_size; + } + if(image->cert_element != NULL) { + memcpy(&data[offset], image->cert_element->data, image->cert_element->header->full_size); + offset += image->cert_element->header->full_size; + } + + if(offset != size) { + error("ERROR: Incorrectly sized image data\n"); + free(data); + *pdata = 0; + *psize = 0; + return -1; + } + + *pdata = data; + *psize = size; + return 0; } @@ -79,10 +79,11 @@ typedef struct { img3_element* cert_element; } img3_file; -img3_file* img3_parse_file(unsigned char* data, int size); +img3_file* img3_parse_file(char* data, int size); img3_element* img3_parse_element(char* data); -void img3_replace_signature(img3_file* image, char* signature); +int img3_replace_signature(img3_file* image, char* signature); void img3_free(img3_file* image); -char* img3_get_data(img3_file* image); +int img3_get_data(img3_file* image, char** pdata, int* psize); +void img3_free_element(img3_element* element); #endif |