diff options
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/Makefile.in | 20 | ||||
| -rw-r--r-- | src/idevicerestore.c | 107 | ||||
| -rw-r--r-- | src/img3.c | 41 | ||||
| -rw-r--r-- | src/img3.h | 67 | ||||
| -rw-r--r-- | src/ipsw.c | 6 | ||||
| -rw-r--r-- | src/ipsw.h | 2 | ||||
| -rw-r--r-- | src/tss.c | 30 | ||||
| -rw-r--r-- | src/tss.h | 6 | 
9 files changed, 260 insertions, 21 deletions
| diff --git a/src/Makefile.am b/src/Makefile.am index c295eb0..c011729 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,6 +18,6 @@ AM_LDFLAGS =\  bin_PROGRAMS = idevicerestore -idevicerestore_SOURCES = idevicerestore.c ipsw.c tss.c +idevicerestore_SOURCES = idevicerestore.c ipsw.c tss.c img3.c  idevicerestore_CFLAGS = $(AM_CFLAGS)  idevicerestore_LDFLAGS = $(AM_LDFLAGS)
\ No newline at end of file diff --git a/src/Makefile.in b/src/Makefile.in index 713e1a2..b52e20a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -48,7 +48,8 @@ CONFIG_CLEAN_VPATH_FILES =  am__installdirs = "$(DESTDIR)$(bindir)"  PROGRAMS = $(bin_PROGRAMS)  am_idevicerestore_OBJECTS = idevicerestore-idevicerestore.$(OBJEXT) \ -	idevicerestore-ipsw.$(OBJEXT) idevicerestore-tss.$(OBJEXT) +	idevicerestore-ipsw.$(OBJEXT) idevicerestore-tss.$(OBJEXT) \ +	idevicerestore-img3.$(OBJEXT)  idevicerestore_OBJECTS = $(am_idevicerestore_OBJECTS)  idevicerestore_LDADD = $(LDADD)  idevicerestore_LINK = $(CCLD) $(idevicerestore_CFLAGS) $(CFLAGS) \ @@ -187,7 +188,7 @@ AM_LDFLAGS = \  	$(libcurl_LIBS)            \  	$(libirecovery_LIBS) -idevicerestore_SOURCES = idevicerestore.c ipsw.c tss.c +idevicerestore_SOURCES = idevicerestore.c ipsw.c tss.c img3.c  idevicerestore_CFLAGS = $(AM_CFLAGS)  idevicerestore_LDFLAGS = $(AM_LDFLAGS)  all: all-am @@ -272,6 +273,7 @@ distclean-compile:  	-rm -f *.tab.c  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idevicerestore-idevicerestore.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idevicerestore-img3.Po@am__quote@  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idevicerestore-ipsw.Po@am__quote@  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idevicerestore-tss.Po@am__quote@ @@ -331,6 +333,20 @@ idevicerestore-tss.obj: tss.c  @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@  @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(idevicerestore_CFLAGS) $(CFLAGS) -c -o idevicerestore-tss.obj `if test -f 'tss.c'; then $(CYGPATH_W) 'tss.c'; else $(CYGPATH_W) '$(srcdir)/tss.c'; fi` +idevicerestore-img3.o: img3.c +@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(idevicerestore_CFLAGS) $(CFLAGS) -MT idevicerestore-img3.o -MD -MP -MF $(DEPDIR)/idevicerestore-img3.Tpo -c -o idevicerestore-img3.o `test -f 'img3.c' || echo '$(srcdir)/'`img3.c +@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/idevicerestore-img3.Tpo $(DEPDIR)/idevicerestore-img3.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='img3.c' object='idevicerestore-img3.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(idevicerestore_CFLAGS) $(CFLAGS) -c -o idevicerestore-img3.o `test -f 'img3.c' || echo '$(srcdir)/'`img3.c + +idevicerestore-img3.obj: img3.c +@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(idevicerestore_CFLAGS) $(CFLAGS) -MT idevicerestore-img3.obj -MD -MP -MF $(DEPDIR)/idevicerestore-img3.Tpo -c -o idevicerestore-img3.obj `if test -f 'img3.c'; then $(CYGPATH_W) 'img3.c'; else $(CYGPATH_W) '$(srcdir)/img3.c'; fi` +@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/idevicerestore-img3.Tpo $(DEPDIR)/idevicerestore-img3.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='img3.c' object='idevicerestore-img3.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(idevicerestore_CFLAGS) $(CFLAGS) -c -o idevicerestore-img3.obj `if test -f 'img3.c'; then $(CYGPATH_W) 'img3.c'; else $(CYGPATH_W) '$(srcdir)/img3.c'; fi` +  ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)  	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \  	unique=`for i in $$list; do \ diff --git a/src/idevicerestore.c b/src/idevicerestore.c index 121ce22..0719508 100644 --- a/src/idevicerestore.c +++ b/src/idevicerestore.c @@ -29,6 +29,7 @@  #include <libimobiledevice/libimobiledevice.h>  #include "tss.h" +#include "img3.h"  #include "ipsw.h"  #include "idevicerestore.h" @@ -130,6 +131,8 @@ int main(int argc, char* argv[]) {  		plist_get_uint_val(unique_chip_node, &ecid);  		lockdownd_client_free(lockdown);  		idevice_free(device); +		lockdown = NULL; +		device = NULL;  	}  	else if(mode == RECOVERY_MODE) {  		recovery_error = irecv_get_ecid(recovery, &ecid); @@ -139,6 +142,7 @@ int main(int argc, char* argv[]) {  			return -1;  		}  		irecv_close(recovery); +		recovery = NULL;  	}  	if(ecid != 0) { @@ -184,8 +188,109 @@ int main(int argc, char* argv[]) {  		return -1;  	}  	plist_free(tss_request); -  	info("Got TSS response\n"); + +	if(mode == NORMAL_MODE) { +		// Place the device in recovery mode +		info("Entering recovery mode...\n"); +		device_error = idevice_new(&device, uuid); +		if(device_error != IDEVICE_E_SUCCESS) { +			error("ERROR: Unable to find device\n"); +			plist_free(tss_response); +			return -1; +		} + +		lockdown_error = lockdownd_client_new_with_handshake(device, &lockdown, "idevicerestore"); +		if(lockdown_error != LOCKDOWN_E_SUCCESS) { +			error("ERROR: Unable to connect to lockdownd service\n"); +			plist_free(tss_response); +			idevice_free(device); +			return -1; +		} + +		lockdown_error = lockdownd_enter_recovery(lockdown); +		if(lockdown_error != LOCKDOWN_E_SUCCESS) { +			error("ERROR: Unable to place device in recovery mode\n"); +			lockdownd_client_free(lockdown); +			plist_free(tss_response); +			idevice_free(device); +			return -1; +		} + +		lockdownd_client_free(lockdown); +		idevice_free(device); +		lockdown = NULL; +		device = NULL; +	} + +	recovery_error = irecv_open(&recovery, uuid); +	while(recovery_error != IRECV_E_SUCCESS) { +		sleep(1); +		info("Retrying connection...\n"); +		recovery_error = irecv_open(&recovery, uuid); +		if(recovery_error == IRECV_E_SUCCESS) { +			mode = RECOVERY_MODE; +			break; +		} +	} + +	info("Extracting iBEC from IPSW\n"); +	archive = ipsw_open(ipsw); +	if(archive == NULL) { +		error("ERROR: Unable to open IPSW\n"); +		plist_free(tss_response); +		irecv_close(recovery); +		return -1; +	} + +	plist_t ibec_entry = plist_dict_get_item(tss_response, "iBEC"); +	if(!ibec_entry || plist_get_node_type(ibec_entry) != PLIST_DICT) { +		error("ERROR: Unable to find iBEC entry in TSS response\n"); +		plist_free(tss_response); +		irecv_close(recovery); +		ipsw_close(archive); +		return -1; +	} + +	char* ibec_path = NULL; +	plist_t ibec_path_node = plist_dict_get_item(ibec_entry, "Path"); +	if(!ibec_path_node || plist_get_node_type(ibec_path_node) != PLIST_STRING) { +		error("ERROR: Unable to find iBEC path in entry\n"); +		plist_free(tss_response); +		plist_free(ibec_entry); +		irecv_close(recovery); +		ipsw_close(archive); +	} +	plist_get_string_val(ibec_path_node, &ibec_path); +	plist_free(ibec_entry); + +	ipsw_file* ibec = ipsw_extract_file(archive, ibec_path); +	if(ibec == NULL) { +		error("ERROR: Unable to extract %s from IPSW\n", ibec_path); +		irecv_close(recovery); +		ipsw_close(archive); +		return -1; +	} +	ipsw_close(archive); + +	img3_file* ibec_img3 = img3_parse_file(ibec->data, ibec->size); +	if(ibec_img3 == NULL) { +		error("ERROR: Unable to parse IMG3: %s\n", ibec_path); +		irecv_close(recovery); +		ipsw_free_file(ibec); +		return -1; +	} +	ipsw_free_file(ibec); + +	tss_stitch_img3(tss_response, &ibec_img3); +	recovery_error = irecv_send_file(recovery, ibec_img3->data); +	if(recovery_error != IRECV_E_SUCCESS) { +		error("ERROR: Unable to send IMG3: %s\n", ibec_path); +		irecv_close(recovery); +		image3_free(ibec_img3); +	} + +	irecv_close(recovery);  	plist_free(tss_response);  	return 0;  } diff --git a/src/img3.c b/src/img3.c new file mode 100644 index 0000000..8a536e5 --- /dev/null +++ b/src/img3.c @@ -0,0 +1,41 @@ +/* + * img3.c + * Functions for handling with Apple's IMG3 format + * + * Copyright (c) 2010 Joshua Hill. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "img3.h" +#include "idevicerestore.h" + +img3_file* image3_parse_file(unsigned char* data, unsigned int size) { +	img3_header* header = (img3_header*) data; +	if(header->imageType != kImg3Container) { +		error("ERROR: Invalid IMG3 file\n"); +		return NULL; +	} +	return NULL; +} + +void image3_free(img3_file* file) { +	if(file != NULL) { +		free(file); +	} +} diff --git a/src/img3.h b/src/img3.h new file mode 100644 index 0000000..75fcd5c --- /dev/null +++ b/src/img3.h @@ -0,0 +1,67 @@ +/* + * img3.h + * Functions for handling with Apple's IMG3 format + * + * Copyright (c) 2010 Joshua Hill. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + */ + +#ifndef IMG3_H +#define IMG3_H + +typedef enum { +    kNorContainer  = 0x696D6733, // img3 +    kImg3Container = 0x496D6733, // Img3 +    k8900Container = 0x30303938, // 8900 +    kImg2Container = 0x494D4732  // IMG2 +} img3_container; + +typedef enum { +    kDataElement = 0x44415441, // DATA +    kTypeElement = 0x54595045, // TYPE +    kKbagElement = 0x4B424147, // KBAG +    kShshElement = 0x53485348, // SHSH +    kCertElement = 0x43455254, // CERT +    kChipElement = 0x43484950, // CHIP +    kProdElement = 0x50524F44, // PROD +    kSdomElement = 0x53444F4D, // SDOM +    kBordElement = 0x424F5244, // BORD +    kSepoElement = 0x5345504F, // SEPO +    kEcidElement = 0x45434944  // ECID +} img3_element_type; + +typedef struct { +    unsigned int signature; +    unsigned int fullSize; +    unsigned int dataSize; +    unsigned int shshOffset; +    unsigned int imageType; +} img3_header; + +typedef struct { +    unsigned int signature; +    unsigned int fullSize; +    unsigned int dataSize; +} img3_element_header; + +typedef struct { +	unsigned char* data; +} img3_file; + +img3_file* img3_parse_file(unsigned char* data, unsigned int size); +void img3_free(img3_file* file); + +#endif @@ -22,11 +22,9 @@  #include <zip.h>  #include <stdlib.h>  #include <string.h> -#include "ipsw.h" -#define error(...) fprintf(stderr, __VA_ARGS__) -#define info(...) if(verbose >= 1) fprintf(stderr, __VA_ARGS__) -#define debug(...) if(verbose >= 2) fprintf(stderr, __VA_ARGS__) +#include "ipsw.h" +#include "idevicerestore.h"  ipsw_archive* ipsw_open(const char* ipsw) {  	int err = 0; @@ -30,7 +30,7 @@ typedef struct {  typedef struct {  	int index; -	const char* name; +	char* name;  	unsigned int size;  	unsigned char* data;  } ipsw_file; @@ -26,10 +26,16 @@  #include <plist/plist.h>  #include "tss.h" +#include "img3.h"  #include "idevicerestore.h"  #define ECID_STRSIZE 0x20 +typedef struct { +	int length; +	char* content; +} tss_response; +  plist_t tss_create_request(plist_t buildmanifest, uint64_t ecid) {  	// Fetch build information from BuildManifest  	plist_t build_identities_array = plist_dict_get_item(buildmanifest, "BuildIdentities"); @@ -127,13 +133,14 @@ plist_t tss_create_request(plist_t buildmanifest, uint64_t ecid) {  		plist_t tss_entry = plist_copy(manifest_entry);  		plist_dict_insert_item(tss_request, key, tss_entry); +		free(key);  	} -	/* -		int sz = 0; -		char* xml = NULL; -		plist_to_xml(tss_request, &xml, &sz); -		printf("%s", xml); -	*/ + +	int sz = 0; +	char* xml = NULL; +	plist_to_xml(tss_request, &xml, &sz); +	printf("%s", xml); +  	return tss_request;  } @@ -182,6 +189,7 @@ plist_t tss_send_request(plist_t tss_request) {  		curl_easy_perform(handle);  		curl_slist_free_all(header);  		curl_easy_cleanup(handle); +		free(request);  	}  	curl_global_cleanup(); @@ -204,11 +212,17 @@ plist_t tss_send_request(plist_t tss_request) {  	plist_t tss_response = NULL;  	tss_size = response->length - (tss_data - response->content);  	plist_from_xml(tss_data, tss_size, &tss_response); -/* +	free(response->content); +	free(response); +  	int sz = 0;  	char* xml = NULL;  	plist_to_xml(tss_response, &xml, &sz);  	printf("%s", xml); -*/ +  	return tss_response;  } + +void tss_stitch_img3(img3_file* file, plist_t signature) { + +} @@ -24,12 +24,10 @@  #include <plist/plist.h> -typedef struct { -	int length; -	char* content; -} tss_response; +#include "img3.h"  plist_t tss_create_request(plist_t buildmanifest, uint64_t ecid);  plist_t tss_send_request(plist_t tss_request); +void tss_stitch_img3(img3_file* file, plist_t signature);  #endif | 
