Permalink
Browse files

dripwn now extracts 3G multitouch firmware as well

* base64 functionality moved from dmg to common
* base64 <data> handling capability added to plist functions
* dripwn modified to use built-in plist library
  • Loading branch information...
1 parent ef34a4d commit b1dcb38657f80d662ab44abd686693b97cf4ee79 @planetbeing committed May 13, 2010
@@ -1,2 +1,2 @@
-add_library(common abstractfile.c)
+add_library(common abstractfile.c base64.c)
File renamed without changes.
View
@@ -16,7 +16,7 @@ link_directories(${ZLIB_LIBRARIES})
link_directories(${PROJECT_BINARY_DIR}/common ${PROJECT_BINARY_DIR}/hfs)
-add_library(dmg base64.c checksum.c dmgfile.c dmglib.c filevault.c io.c partition.c resources.c udif.c)
+add_library(dmg checksum.c dmgfile.c dmglib.c filevault.c io.c partition.c resources.c udif.c)
IF(OPENSSL_FOUND)
add_definitions(-DHAVE_CRYPT)
@@ -2,7 +2,7 @@ link_directories(${PROJECT_BINARY_DIR}/common ${PROJECT_BINARY_DIR}/hfs ${PROJEC
add_executable(dripwn dripwn.c)
-target_link_libraries (dripwn dmg hfs common minizip)
+target_link_libraries (dripwn xpwn)
include_directories(${PROJECT_SOURCE_DIR}/minizip)
link_directories(${PROJECT_BINARY_DIR}/minizip)
View
@@ -5,6 +5,7 @@
#include <string.h>
#include <dmg/dmgfile.h>
#include <dmg/filevault.h>
+#include <xpwn/plist.h>
#define DEFAULT_BUFFER_SIZE (1 * 1024 * 1024)
char endianness;
@@ -25,7 +26,9 @@ char *createTempFile() {
return strdup(tmpFileBuffer);
}
-char *loadZip(const char* ipsw, const char* toExtract) {
+// This gets any file over 100 MB from the IPSW and writes it to a temporary file and returns the name of the temporary file.
+// It is meant to get the rootfs image and is a bit hacky but is unlikely to break.
+char *loadZipLarge(const char* ipsw) {
char *fileName;
void* buffer;
unzFile zip;
@@ -39,7 +42,7 @@ char *loadZip(const char* ipsw, const char* toExtract) {
ASSERT(unzGetCurrentFileInfo(zip, &pfile_info, NULL, 0, NULL, 0, NULL, 0) == UNZ_OK, "cannot get current file info from ipsw");
fileName = (char*) malloc(pfile_info.size_filename + 1);
ASSERT(unzGetCurrentFileInfo(zip, NULL, fileName, pfile_info.size_filename + 1, NULL, 0, NULL, 0) == UNZ_OK, "cannot get current file name from ipsw");
- if(strcmp(toExtract, fileName) == 0) {
+ if(pfile_info.uncompressed_size > (100UL * 1024UL * 1024UL)) {
ASSERT(unzOpenCurrentFile(zip) == UNZ_OK, "cannot open compressed file in IPSW");
uLong fileSize = pfile_info.uncompressed_size;
@@ -99,76 +102,6 @@ char *extractPlist(Volume* volume) {
return outFileName;
}
-int is_base64(const char c) {
- if ( (c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '+' ||
- c == '/' ||
- c == '=') return 1;
- return 0;
-}
-
-void cleanup_base64(char *inp, const unsigned int size) {
- unsigned int i;
- char *tinp1,*tinp2;
- tinp1 = inp;
- tinp2 = inp;
- for (i = 0; i < size; i++) {
- if (is_base64(*tinp2)) {
- *tinp1++ = *tinp2++;
- }
- else {
- *tinp1 = *tinp2++;
- }
- }
- *(tinp1) = 0;
-}
-
-unsigned char decode_base64_char(const char c) {
- if (c >= 'A' && c <= 'Z') return c - 'A';
- if (c >= 'a' && c <= 'z') return c - 'a' + 26;
- if (c >= '0' && c <= '9') return c - '0' + 52;
- if (c == '+') return 62;
- if (c == '=') return 0;
- return 63;
-}
-
-void decode_base64(const char *inp, unsigned int isize,
- char *out, unsigned int *osize) {
- unsigned int i;
- char *tinp = (char*)inp;
- char *tout;
- *osize = isize / 4 * 3;
- tout = tinp;
- for(i = 0; i < isize >> 2; i++) {
- *tout++ = (decode_base64_char(*tinp++) << 2) | (decode_base64_char(*tinp) >> 4);
- *tout++ = (decode_base64_char(*tinp++) << 4) | (decode_base64_char(*tinp) >> 2);
- *tout++ = (decode_base64_char(*tinp++) << 6) | decode_base64_char(*tinp++);
- }
- if (*(tinp-1) == '=') (*osize)--;
- if (*(tinp-2) == '=') (*osize)--;
-}
-
-
-char * find_string(char * string, char * sub_string)
-{
- size_t sub_s_len;
-
- sub_s_len = strlen(sub_string);
-
- while (*string)
- {
- if (strncmp(string, sub_string, sub_s_len) == 0)
- {
- return string;
- }
- string++;
- }
-
- return NULL;
-}
-
int main(int argc, const char *argv[]) {
io_func* io;
Volume* volume;
@@ -185,11 +118,11 @@ int main(int argc, const char *argv[]) {
size_t final_fw_len;
FILE * output;
- if(argc < 4) {
- printf("usage: %s <ipsw> <key> <root-fs-name>\n", argv[0]);
+ if(argc < 3) {
+ printf("usage: %s <ipsw> <key>\n", argv[0]);
return 0;
}
- char *filename = loadZip(argv[1], argv[3]);
+ char *filename = loadZipLarge(argv[1]);
TestByteOrder();
image = createAbstractFileFromFile(fopen(filename, "rb"));
@@ -216,78 +149,51 @@ int main(int argc, const char *argv[]) {
fseek(iphone_mtprops, 0, SEEK_END);
file_len = ftell(iphone_mtprops);
- buffer = (char *)malloc(sizeof(char) * file_len);
+ buffer = (char *)malloc(sizeof(char) * (file_len + 1));
fseek(iphone_mtprops, 0, SEEK_SET);
fread(buffer, file_len, 1, iphone_mtprops);
fclose(iphone_mtprops);
- p = find_string(buffer, "<key>A-Speed Firmware</key>");
- assert(p != NULL);
+ buffer[file_len] = '\0';
- while (*p)
- {
- if (*p == '\n')
- break;
- p++;
- }
- while (*p)
- {
- if (*p == '>')
- break;
- p++;
- }
+ Dictionary* info = createRoot(buffer);
+ assert(info != NULL);
+ free(buffer);
- p++;
+ Dictionary* zephyr1FW = (Dictionary*) getValueByKey(info, "Z1F50,1");
+ if(zephyr1FW)
+ {
+ DataValue* aspeedData = (DataValue*) getValueByKey(zephyr1FW, "A-Speed Firmware");
+ assert(aspeedData != NULL);
- a_speed_firmware = p;
+ DataValue* fwData = (DataValue*) getValueByKey(zephyr1FW, "Firmware");
+ assert(fwData != NULL);
- while (*p)
- {
- if (*p == '<')
- break;
- p++;
- }
- a_speed_fw_len = p - a_speed_firmware;
+ output = fopen("zephyr_aspeed.bin", "wb");
+ assert(output != NULL);
+ fwrite(aspeedData->value, aspeedData->len, 1, output);
+ fclose(output);
- p = find_string(p, "<key>Firmware</key>");
- assert(p != NULL);
+ output = fopen("zephyr_main.bin", "wb");
+ assert(output != NULL);
+ fwrite(fwData->value, fwData->len, 1, output);
+ fclose(output);
+ }
- while (*p)
- {
- if (*p == '\n')
- break;
- p++;
- }
- while (*p)
- {
- if (*p == '>')
- break;
- p++;
- }
- p++;
- firmware = p;
- while (*p)
- {
- if (*p == '<')
- break;
- p++;
- }
- fw_len = p - firmware;
- cleanup_base64(firmware, fw_len);
- decode_base64(firmware, fw_len, firmware, (unsigned int *)&final_fw_len);
- output = fopen("zephyr_main.bin", "a+");
- fwrite(firmware, final_fw_len, 1, output);
- fclose(output);
- cleanup_base64(a_speed_firmware, a_speed_fw_len);
- decode_base64(a_speed_firmware, a_speed_fw_len, a_speed_firmware, (unsigned int *)&final_a_speed_fw_len);
- output = fopen("zephyr_aspeed.bin", "a+");
- fwrite(a_speed_firmware, final_a_speed_fw_len, 1, output);
- fclose(output);
- free(buffer);
+ Dictionary* zephyr2FW = (Dictionary*) getValueByKey(info, "Z2F52,1");
+ if(zephyr2FW)
+ {
+ DataValue* fwData = (DataValue*) getValueByKey(zephyr2FW, "Constructed Firmware");
+ assert(fwData != NULL);
+ output = fopen("zephyr2.bin", "wb");
+ assert(output != NULL);
+ fwrite(fwData->value, fwData->len, 1, output);
+ fclose(output);
+ }
ASSERT(remove(plistName) == 0, "Error deleting iPhone.mtprops");
printf("Zephyr files extracted succesfully.\n");
return 0;
-}
+}
View
@@ -99,4 +99,10 @@ typedef struct io_func_struct {
closeFunc close;
} io_func;
+struct AbstractFile;
+
+unsigned char* decodeBase64(char* toDecode, size_t* dataLength);
+void writeBase64(struct AbstractFile* file, unsigned char* data, size_t dataLength, int tabLength, int width);
+char* convertBase64(unsigned char* data, size_t dataLength, int tabLength, int width);
+
#endif
View
@@ -276,10 +276,6 @@ extern "C" {
#endif
void outResources(AbstractFile* file, AbstractFile* out);
- unsigned char* decodeBase64(char* toDecode, size_t* dataLength);
- void writeBase64(AbstractFile* file, unsigned char* data, size_t dataLength, int tabLength, int width);
- char* convertBase64(unsigned char* data, size_t dataLength, int tabLength, int width);
-
uint32_t CRC32Checksum(uint32_t* crc, const unsigned char *buf, size_t len);
uint32_t MKBlockChecksum(uint32_t* ckSum, const unsigned char* data, size_t len);
@@ -6,7 +6,8 @@ enum DictTypes {
ArrayType,
StringType,
IntegerType,
- BoolType
+ BoolType,
+ DataType
};
typedef struct DictValue {
@@ -21,6 +22,12 @@ typedef struct StringValue {
char* value;
} StringValue;
+typedef struct DataValue {
+ DictValue dValue;
+ int len;
+ char* value;
+} DataValue;
+
typedef struct IntegerValue {
DictValue dValue;
int value;
View
@@ -150,6 +150,12 @@ void createArray(ArrayValue* myself, char* xml) {
curValue = (DictValue*) realloc(curValue, sizeof(StringValue));
((StringValue*)curValue)->value = (char*) malloc(sizeof(char) * (strlen(valueTag->xml) + 1));
strcpy(((StringValue*)curValue)->value, valueTag->xml);
+ } else if(strcmp(valueTag->name, "data") == 0) {
+ size_t len;
+ curValue->type = StringType;
+ curValue = (DictValue*) realloc(curValue, sizeof(DataValue));
+ ((DataValue*)curValue)->value = decodeBase64(valueTag->xml, &len);
+ ((DataValue*)curValue)->len = len;
} else if(strcmp(valueTag->name, "integer") == 0) {
curValue->type = IntegerType;
curValue = (DictValue*) realloc(curValue, sizeof(IntegerValue));
@@ -198,6 +204,14 @@ void removeKey(Dictionary* dict, char* key) {
break;
case StringType:
free(((StringValue*)(toRelease))->value);
+ free(toRelease->key);
+ free(toRelease);
+ break;
+ case DataType:
+ free(((DataValue*)(toRelease))->value);
+ free(toRelease->key);
+ free(toRelease);
+ break;
case IntegerType:
case BoolType:
free(toRelease->key);
@@ -253,6 +267,12 @@ void createDictionary(Dictionary* myself, char* xml) {
curValue = (DictValue*) realloc(curValue, sizeof(StringValue));
((StringValue*)curValue)->value = (char*) malloc(sizeof(char) * (strlen(valueTag->xml) + 1));
strcpy(((StringValue*)curValue)->value, valueTag->xml);
+ } else if(strcmp(valueTag->name, "data") == 0) {
+ size_t len;
+ curValue->type = StringType;
+ curValue = (DictValue*) realloc(curValue, sizeof(DataValue));
+ ((DataValue*)curValue)->value = decodeBase64(valueTag->xml, &len);
+ ((DataValue*)curValue)->len = len;
} else if(strcmp(valueTag->name, "integer") == 0) {
curValue->type = IntegerType;
curValue = (DictValue*) realloc(curValue, sizeof(IntegerValue));
@@ -318,6 +338,18 @@ char* getXmlFromArrayValue(ArrayValue* myself, int tabsCount) {
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
+ } else if(curValue->type == DataType) {
+ char* base64 = convertBase64(((DataValue*)curValue)->value, ((DataValue*)curValue)->len, 0, -1);
+ sprintf(buffer, "%s\t<data>", tabs);
+ toReturnSize += sizeof(char) * (strlen(buffer) + strlen(base64) + 1);
+ toReturn = realloc(toReturn, toReturnSize);
+ toReturn = strcat(toReturn, buffer);
+ toReturn = strcat(toReturn, base64);
+ sprintf(buffer, "</data>\n", tabs);
+ toReturnSize += sizeof(char) * (strlen(buffer) + 1);
+ toReturn = realloc(toReturn, toReturnSize);
+ toReturn = strcat(toReturn, buffer);
+ free(base64);
} else if(curValue->type == IntegerType) {
sprintf(buffer, "%s\t<integer>%d</integer>\n", tabs, ((IntegerValue*)curValue)->value);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
@@ -387,6 +419,18 @@ char* getXmlFromDictionary(Dictionary* myself, int tabsCount) {
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
+ } else if(curValue->type == DataType) {
+ char* base64 = convertBase64(((DataValue*)curValue)->value, ((DataValue*)curValue)->len, 0, -1);
+ sprintf(buffer, "%s\t<data>", tabs);
+ toReturnSize += sizeof(char) * (strlen(buffer) + strlen(base64) + 1);
+ toReturn = realloc(toReturn, toReturnSize);
+ toReturn = strcat(toReturn, buffer);
+ toReturn = strcat(toReturn, base64);
+ sprintf(buffer, "</data>\n", tabs);
+ toReturnSize += sizeof(char) * (strlen(buffer) + 1);
+ toReturn = realloc(toReturn, toReturnSize);
+ toReturn = strcat(toReturn, buffer);
+ free(base64);
} else if(curValue->type == IntegerType) {
sprintf(buffer, "%s\t<integer>%d</integer>\n", tabs, ((IntegerValue*)curValue)->value);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);

2 comments on commit b1dcb38

@posixninja

you know other then the dripwn stuff, all those other changes were already in my branch =P

@posixninja

which means now I get to play "merge the massive collision" cries

Please sign in to comment.