diff options
Diffstat (limited to 'src')
-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 |