void loadZipFile2(const char* ipsw, OutputState** output, const char* file, int useMemory) { char* fileName; void* buffer; unzFile zip; unz_file_info pfile_info; ASSERT(zip = unzOpen(ipsw), "cannot open input ipsw"); ASSERT(unzGoToFirstFile(zip) == UNZ_OK, "cannot seek to first file in input ipsw"); do { 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((file == NULL && fileName[strlen(fileName) - 1] != '/') || (file != NULL && strcmp(fileName, file)) == 0) { printf("loading: %s (%ld)\n", fileName, pfile_info.uncompressed_size); fflush(stdout); ASSERT(unzOpenCurrentFile(zip) == UNZ_OK, "cannot open compressed file in IPSW"); if(useMemory) { buffer = malloc((pfile_info.uncompressed_size > 0) ? pfile_info.uncompressed_size : 1); ASSERT(unzReadCurrentFile(zip, buffer, pfile_info.uncompressed_size) == pfile_info.uncompressed_size, "cannot read file from ipsw"); addToOutput(output, fileName, buffer, pfile_info.uncompressed_size); } else { char* tmpFileName = createTempFile(); FILE* tmpFile = fopen(tmpFileName, "wb"); buffer = malloc(DEFAULT_BUFFER_SIZE); size_t left = pfile_info.uncompressed_size; while(left > 0) { size_t toRead; if(left > DEFAULT_BUFFER_SIZE) toRead = DEFAULT_BUFFER_SIZE; else toRead = left; ASSERT(unzReadCurrentFile(zip, buffer, toRead) == toRead, "cannot read file from ipsw"); fwrite(buffer, toRead, 1, tmpFile); left -= toRead; } fclose(tmpFile); free(buffer); addToOutput2(output, fileName, NULL, pfile_info.uncompressed_size, tmpFileName); } ASSERT(unzCloseCurrentFile(zip) == UNZ_OK, "cannot close compressed file in IPSW"); } free(fileName); } while(unzGoToNextFile(zip) == UNZ_OK); ASSERT(unzClose(zip) == UNZ_OK, "cannot close input ipsw file"); }
int doDecrypt(StringValue* decryptValue, StringValue* fileValue, const char* bundlePath, OutputState** state, unsigned int* key, unsigned int* iv, int useMemory) { size_t bufferSize; void* buffer; AbstractFile* file; AbstractFile* out; AbstractFile* outRaw; char* tmpFileName; if(useMemory) { bufferSize = 0; buffer = malloc(1); outRaw = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize); } else { tmpFileName = createTempFile(); outRaw = createAbstractFileFromFile(fopen(tmpFileName, "wb")); } out = duplicateAbstractFile(getFileFromOutputState(state, fileValue->value), outRaw); file = openAbstractFile3(getFileFromOutputState(state, fileValue->value), key, iv, 0); if(!file || !out) { XLOG(0, "file error\n"); exit(0); } char *buf = malloc(1024 * 1024); off_t inDataSize = file->getLength(file); while (inDataSize > 0) { off_t avail, chunk = 1024 * 1024; if (chunk > inDataSize) { chunk = inDataSize; } if (chunk < 0) { XLOG(0, "decrypt failed\n"); exit(0); } avail = file->read(file, buf, chunk); out->write(out, buf, avail); if (avail < chunk) { break; } inDataSize -= chunk; } out->close(out); file->close(file); free(buf); XLOG(0, "writing... "); fflush(stdout); if (decryptValue) { fileValue = decryptValue; } if(useMemory) { addToOutput(state, fileValue->value, buffer, bufferSize); } else { outRaw = createAbstractFileFromFile(fopen(tmpFileName, "rb")); size_t length = outRaw->getLength(outRaw); outRaw->close(outRaw); addToOutput2(state, fileValue->value, NULL, length, tmpFileName); } XLOG(0, "success\n"); fflush(stdout); return 0; }
int doPatch(StringValue* patchValue, StringValue* fileValue, const char* bundlePath, OutputState** state, unsigned int* key, unsigned int* iv, int useMemory, int isPlain) { char* patchPath; size_t bufferSize; void* buffer; AbstractFile* patchFile; AbstractFile* file; AbstractFile* out; AbstractFile* outRaw; char* tmpFileName; if(useMemory) { bufferSize = 0; buffer = malloc(1); outRaw = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize); } else { tmpFileName = createTempFile(); outRaw = createAbstractFileFromFile(fopen(tmpFileName, "wb")); } patchPath = malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2)); strcpy(patchPath, bundlePath); strcat(patchPath, "/"); strcat(patchPath, patchValue->value); XLOG(0, "%s (%s)... ", fileValue->value, patchPath); fflush(stdout); patchFile = createAbstractFileFromFile(fopen(patchPath, "rb")); if (isPlain) { out = outRaw; file = getFileFromOutputState(state, fileValue->value); } else { if(key != NULL) { XLOG(0, "encrypted input... "); out = duplicateAbstractFile2(getFileFromOutputState(state, fileValue->value), outRaw, key, iv, NULL); } else { out = duplicateAbstractFile(getFileFromOutputState(state, fileValue->value), outRaw); } if(key != NULL) { XLOG(0, "encrypted output... "); file = openAbstractFile2(getFileFromOutputState(state, fileValue->value), key, iv); } else { file = openAbstractFile(getFileFromOutputState(state, fileValue->value)); } } if(!patchFile || !file || !out) { XLOG(0, "file error\n"); exit(0); } if(patch(file, out, patchFile) != 0) { XLOG(0, "patch failed\n"); exit(0); } if(strstr(fileValue->value, "WTF.s5l8900xall.RELEASE")) { XLOG(0, "Exploiting 8900 vulnerability... ;)\n"); AbstractFile* exploited; if(useMemory) { exploited = createAbstractFileFrom8900(createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize)); } else { exploited = createAbstractFileFrom8900(createAbstractFileFromFile(fopen(tmpFileName, "r+b"))); } exploit8900(exploited); exploited->close(exploited); } XLOG(0, "writing... "); fflush(stdout); if(useMemory) { addToOutput(state, fileValue->value, buffer, bufferSize); } else { outRaw = createAbstractFileFromFile(fopen(tmpFileName, "rb")); size_t length = outRaw->getLength(outRaw); outRaw->close(outRaw); addToOutput2(state, fileValue->value, NULL, length, tmpFileName); } XLOG(0, "success\n"); fflush(stdout); free(patchPath); return 0; }
void addToOutput(OutputState** state, const char* fileName, void* buffer, const size_t bufferSize) { addToOutput2(state, fileName, buffer, bufferSize, NULL); }