diff options
| -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 | 
