summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in20
-rw-r--r--src/idevicerestore.c107
-rw-r--r--src/img3.c41
-rw-r--r--src/img3.h67
-rw-r--r--src/ipsw.c6
-rw-r--r--src/ipsw.h2
-rw-r--r--src/tss.c30
-rw-r--r--src/tss.h6
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
diff --git a/src/ipsw.c b/src/ipsw.c
index 05a92c6..f601201 100644
--- a/src/ipsw.c
+++ b/src/ipsw.c
@@ -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;
diff --git a/src/ipsw.h b/src/ipsw.h
index 12a0985..5cbad19 100644
--- a/src/ipsw.h
+++ b/src/ipsw.h
@@ -30,7 +30,7 @@ typedef struct {
typedef struct {
int index;
- const char* name;
+ char* name;
unsigned int size;
unsigned char* data;
} ipsw_file;
diff --git a/src/tss.c b/src/tss.c
index bd098e4..2b2991d 100644
--- a/src/tss.c
+++ b/src/tss.c
@@ -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) {
+
+}
diff --git a/src/tss.h b/src/tss.h
index 7c9ddf8..c1ff4b4 100644
--- a/src/tss.h
+++ b/src/tss.h
@@ -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