int copyAcrossVolumes(Volume* volume1, Volume* volume2, char* path1, char* path2) { void* buffer; size_t bufferSize; AbstractFile* tmpFile; int ret; buffer = malloc(1); bufferSize = 0; tmpFile = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize); if(!silence) { printf("retrieving... "); fflush(stdout); } get_hfs(volume1, path1, tmpFile); tmpFile->seek(tmpFile, 0); if(!silence) { printf("writing (%ld)... ", (long) tmpFile->getLength(tmpFile)); fflush(stdout); } ret = add_hfs(volume2, tmpFile, path2); if(!silence) { printf("done\n"); } free(buffer); return ret; }
void doPatchInPlace(Volume* volume, const char* filePath, const char* patchPath) { void* buffer; void* buffer2; size_t bufferSize; size_t bufferSize2; AbstractFile* bufferFile; AbstractFile* patchFile; AbstractFile* out; buffer = malloc(1); bufferSize = 0; bufferFile = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize); XLOG(0, "retrieving..."); fflush(stdout); get_hfs(volume, filePath, bufferFile); bufferFile->close(bufferFile); XLOG(0, "patching..."); fflush(stdout); patchFile = createAbstractFileFromFile(fopen(patchPath, "rb")); buffer2 = malloc(1); bufferSize2 = 0; out = duplicateAbstractFile(createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize), createAbstractFileFromMemoryFile((void**)&buffer2, &bufferSize2)); // reopen the inner package bufferFile = openAbstractFile(createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize)); if(!patchFile || !bufferFile || !out) { XLOG(0, "file error\n"); exit(0); } if(patch(bufferFile, out, patchFile) != 0) { XLOG(0, "patch failed\n"); exit(0); } XLOG(0, "writing... "); fflush(stdout); add_hfs(volume, createAbstractFileFromMemoryFile((void**)&buffer2, &bufferSize2), filePath); free(buffer2); free(buffer); XLOG(0, "success\n"); fflush(stdout); }
void fixupBootNeuterArgs(Volume* volume, char unlockBaseband, char selfDestruct, char use39, char use46) { const char bootNeuterPlist[] = "/System/Library/LaunchDaemons/com.devteam.bootneuter.auto.plist"; AbstractFile* plistFile; char* plist; Dictionary* info; size_t bufferSize; ArrayValue* arguments; XLOG(0, "fixing up BootNeuter arguments...\n"); plist = malloc(1); bufferSize = 0; plistFile = createAbstractFileFromMemoryFile((void**)&plist, &bufferSize); get_hfs(volume, bootNeuterPlist, plistFile); plistFile->close(plistFile); info = createRoot(plist); free(plist); arguments = (ArrayValue*) getValueByKey(info, "ProgramArguments"); addStringToArray(arguments, "-autoMode"); addStringToArray(arguments, "YES"); addStringToArray(arguments, "-RegisterForSystemEvents"); addStringToArray(arguments, "YES"); if(unlockBaseband) { addStringToArray(arguments, "-unlockBaseband"); addStringToArray(arguments, "YES"); } if(selfDestruct) { addStringToArray(arguments, "-selfDestruct"); addStringToArray(arguments, "YES"); } if(use39) { addStringToArray(arguments, "-bootLoader"); addStringToArray(arguments, "3.9"); } else if(use46) { addStringToArray(arguments, "-bootLoader"); addStringToArray(arguments, "4.6"); } plist = getXmlFromRoot(info); releaseDictionary(info); plistFile = createAbstractFileFromMemory((void**)&plist, sizeof(char) * strlen(plist)); add_hfs(volume, plistFile, bootNeuterPlist); free(plist); }
int copyAcrossVolumes(Volume* volume1, Volume* volume2, char* path1, char* path2) { void* buffer; size_t bufferSize; AbstractFile* tmpFile; int ret; buffer = malloc(1); bufferSize = 0; tmpFile = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize); get_hfs(volume1, path1, tmpFile); tmpFile->seek(tmpFile, 0); ret = add_hfs(volume2, tmpFile, path2); free(buffer); return ret; }
static AbstractFile* openRoot(void** buffer, size_t* rootSize) { static char tmpFileBuffer[512]; if((*buffer) != NULL) { return createAbstractFileFromMemoryFile(buffer, rootSize); } else { if(tmpFile == NULL) { #ifdef WIN32 char tmpFilePath[512]; GetTempPath(512, tmpFilePath); GetTempFileName(tmpFilePath, "root", 0, tmpFileBuffer); CloseHandle(CreateFile(tmpFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL)); #else strcpy(tmpFileBuffer, "/tmp/rootXXXXXX"); close(mkstemp(tmpFileBuffer)); FILE* tFile = fopen(tmpFileBuffer, "wb"); fclose(tFile); #endif tmpFile = tmpFileBuffer; } return createAbstractFileFromFile(fopen(tmpFile, "r+b")); } }
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* replaceBootImage(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, AbstractFile* png, size_t *fileSize) { AbstractFile* imageFile; unsigned char header[8]; InfoIBootIM* info; png_uint_32 i; png_bytepp row_pointers; uint8_t* imageBuffer; void* buffer; png->read(png, header, 8); if(png_sig_cmp(header, 0, 8) != 0) { XLOG(0, "error: not a valid png file\n"); return NULL; } png->seek(png, 0); png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn); if (!png_ptr) { return NULL; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return NULL; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { XLOG(0, "error reading png\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(buffer); return NULL; } png_set_read_fn(png_ptr, png, pngRead); png_read_info(png_ptr, info_ptr); if(png_get_bit_depth(png_ptr, info_ptr) > 8) { XLOG(0, "warning: bit depth per channel is greater than 8 (%d). Attempting to strip, but image quality will be degraded.\n", png_get_bit_depth(png_ptr, info_ptr)); } if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY || png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB) { XLOG(0, "notice: attempting to add dummy transparency channel\n"); } if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) { XLOG(0, "notice: attempting to expand palette into full rgb\n"); } png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_bgr(png_ptr); png_set_add_alpha(png_ptr, 0x0, PNG_FILLER_AFTER); png_set_invert_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); if(png_get_image_width(png_ptr, info_ptr) > 320 || png_get_image_height(png_ptr, info_ptr) > 480) { XLOG(0, "error: dimensions out of range, must be within 320x480, not %lux%lu\n", png_get_image_width(png_ptr, info_ptr), png_get_image_height(png_ptr, info_ptr)); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } if(png_get_bit_depth(png_ptr, info_ptr) != 8) { XLOG(0, "error: bit depth per channel must be 8 not %d!\n", png_get_bit_depth(png_ptr, info_ptr)); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } if(png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_GRAY_ALPHA && png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB_ALPHA) { XLOG(0, "error: incorrect color type, must be greyscale with alpha, or rgb with alpha\n"); if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY || png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB) { XLOG(0, "It appears you're missing an alpha channel. Add transparency to your image\n"); } if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) { XLOG(0, "This PNG is saved with the palette color type rather than ARGB.\n"); } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * png_get_image_height(png_ptr, info_ptr)); imageBuffer = malloc(png_get_image_height(png_ptr, info_ptr) * png_get_rowbytes(png_ptr, info_ptr)); for(i = 0; i < png_get_image_height(png_ptr, info_ptr); i++) { row_pointers[i] = imageBuffer + (png_get_rowbytes(png_ptr, info_ptr) * i); } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, end_info); buffer = malloc(1); *fileSize = 0; if(key != NULL) { imageFile = duplicateAbstractFile2(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize), key, iv, NULL); } else { imageFile = duplicateAbstractFile(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize)); } info = (InfoIBootIM*) (imageFile->data); info->header.width = (uint16_t) png_get_image_width(png_ptr, info_ptr); info->header.height = (uint16_t) png_get_image_height(png_ptr, info_ptr); if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA) { info->header.format = IBOOTIM_GREY; } else { info->header.format = IBOOTIM_ARGB; } imageFile->write(imageFile, imageBuffer, png_get_image_height(png_ptr, info_ptr) * png_get_rowbytes(png_ptr, info_ptr)); imageFile->close(imageFile); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png->close(png); free(row_pointers); free(imageBuffer); return buffer; }