int main(int argc, char* argv[]) { init_libxpwn(); if(argc < 4) { print_usage(); return 0; } AbstractFile* png; AbstractFile* img; AbstractFile* dst; void* imageBuffer; size_t imageSize; unsigned int key[16]; unsigned int iv[16]; unsigned int* pKey = NULL; unsigned int* pIV = NULL; if(strcmp(argv[1], "e") == 0) { img = createAbstractFileFromFile(fopen(argv[2], "rb")); if(argc >= 6) { sscanf(argv[4], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &iv[0], &iv[1], &iv[2], &iv[3], &iv[4], &iv[5], &iv[6], &iv[7], &iv[8], &iv[9], &iv[10], &iv[11], &iv[12], &iv[13], &iv[14], &iv[15]); sscanf(argv[5], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &key[0], &key[1], &key[2], &key[3], &key[4], &key[5], &key[6], &key[7], &key[8], &key[9], &key[10], &key[11], &key[12], &key[13], &key[14], &key[15]); pKey = key; pIV = iv; } AbstractFile2* img3 = (AbstractFile2*) createAbstractFileFromImg3(img); img3->setKey(img3, key, iv); AbstractFile * out = createAbstractFileFromFile(fopen(argv[3], "wb")); size_t inDataSize = (size_t) ((AbstractFile *)img3)->getLength((AbstractFile *)img3); char *inData = (char*) malloc(inDataSize); ((AbstractFile *)img3)->read((AbstractFile *)img3, inData, inDataSize); out->write(out, inData, inDataSize); } return 0; }
void cmd_extract(Volume* volume, int argc, const char *argv[]) { HFSPlusCatalogRecord* record; AbstractFile *outFile; if(argc < 3) { printf("Not enough arguments"); return; } outFile = createAbstractFileFromFile(fopen(argv[2], "wb")); if(outFile == NULL) { printf("cannot create file"); } record = getRecordFromPath(argv[1], volume, NULL, NULL); if(record != NULL) { if(record->recordType == kHFSPlusFileRecord) writeToFile((HFSPlusCatalogFile*)record, outFile, volume); else printf("Not a file\n"); } else { printf("No such file or directory\n"); } outFile->close(outFile); free(record); }
int buildInOut(const char* source, const char* dest, AbstractFile** in, AbstractFile** out) { *in = createAbstractFileFromFile(fopen(source, "rb")); if(!(*in)) { printf("cannot open source: %s\n", source); return FALSE; } *out = createAbstractFileFromFile(fopen(dest, "wb")); if(!(*out)) { (*in)->close(*in); printf("cannot open destination: %s\n", dest); return FALSE; } return TRUE; }
BOOL hfslib_untar(HfsContext* ctx, char* tarFile) { AbstractFile *inFile = createAbstractFileFromFile(fopen(tarFile, "rb")); BOOL result = FALSE; if(inFile == NULL) { printf("file to untar not found"); } else { result = hfs_untar(ctx->volume, inFile); } if (inFile != NULL) { inFile->close(inFile); } return result; }
void extractAllInFolder(HFSCatalogNodeID folderID, Volume* volume) { CatalogRecordList* list; CatalogRecordList* theList; char cwd[1024]; char* name; HFSPlusCatalogFolder* folder; HFSPlusCatalogFile* file; AbstractFile* outFile; struct stat status; ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); theList = list = getFolderContents(folderID, volume); while(list != NULL) { name = unicodeToAscii(&list->name); if(strncmp(name, ".HFS+ Private Directory Data", sizeof(".HFS+ Private Directory Data") - 1) == 0 || name[0] == '\0') { free(name); list = list->next; continue; } if(list->record->recordType == kHFSPlusFolderRecord) { folder = (HFSPlusCatalogFolder*)list->record; printf("folder: %s\n", name); if(stat(name, &status) != 0) { ASSERT(mkdir(name, 0755) == 0, "mkdir"); } ASSERT(chdir(name) == 0, "chdir"); extractAllInFolder(folder->folderID, volume); ASSERT(chdir(cwd) == 0, "chdir"); } else if(list->record->recordType == kHFSPlusFileRecord) { printf("file: %s\n", name); file = (HFSPlusCatalogFile*)list->record; outFile = createAbstractFileFromFile(fopen(name, "wb")); if(outFile != NULL) { writeToFile(file, outFile, volume); outFile->close(outFile); } else { printf("WARNING: cannot fopen %s\n", name); } } free(name); list = list->next; } releaseCatalogRecordList(theList); }
AbstractFile* getFileFromOutputState(OutputState** state, const char* fileName) { OutputState* curFile; curFile = *state; while(curFile != NULL) { if(strcmp(curFile->fileName, fileName) == 0) { if(curFile->tmpFileName == NULL) return createAbstractFileFromMemory(&(curFile->buffer), curFile->bufferSize); else return createAbstractFileFromFile(fopen(curFile->tmpFileName, "rb")); } curFile = curFile->next; } return NULL; }
void cmd_add(Volume* volume, int argc, const char *argv[]) { AbstractFile *inFile; if(argc < 3) { printf("Not enough arguments"); return; } inFile = createAbstractFileFromFile(fopen(argv[1], "rb")); if(inFile == NULL) { printf("file to add not found"); } add_hfs(volume, inFile, argv[2]); }
void cmd_untar(Volume* volume, int argc, const char *argv[]) { AbstractFile *inFile; if(argc < 2) { printf("Not enough arguments"); return; } inFile = createAbstractFileFromFile(fopen(argv[1], "rb")); if(inFile == NULL) { printf("file to untar not found"); } hfs_untar(volume, inFile); }
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 cmd_cat(Volume* volume, int argc, const char *argv[]) { HFSPlusCatalogRecord* record; AbstractFile* stdoutFile; record = getRecordFromPath(argv[1], volume, NULL, NULL); stdoutFile = createAbstractFileFromFile(stdout); if(record != NULL) { if(record->recordType == kHFSPlusFileRecord) writeToFile((HFSPlusCatalogFile*)record, stdoutFile, volume); else printf("Not a file\n"); } else { printf("No such file or directory\n"); } free(record); free(stdoutFile); }
AbstractFile* getFileFromOutputStateForReplace(OutputState** state, const char* fileName) { OutputState* curFile; size_t bufSize; curFile = *state; while(curFile != NULL) { if(strcmp(curFile->fileName, fileName) == 0) { if(curFile->tmpFileName == NULL) { bufSize = curFile->bufferSize; curFile->bufferSize = 0; return createAbstractFileFromMemoryFileBuffer(&(curFile->buffer), &curFile->bufferSize, bufSize); } else { return createAbstractFileFromFile(fopen(curFile->tmpFileName, "wb")); } } curFile = curFile->next; } return NULL; }
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 main(int argc, char* argv[]) { printf("---------------------------PLEASE READ THIS---------------------------\n"); printf("Please make certain that all iTunes related processes are not running\n"); printf("at this time (use Task Manager, etc. to end them). Your iPhone/iPod\n"); printf("must be placed into DFU mode AFTER iTunes had been turned off. This\n"); printf(" will allow me to talk to it without iTunes getting in beforehand.\n"); printf("USB Product ID of iPhone ought to be 0x1222\n"); printf("---------------------------PLEASE READ THIS---------------------------\n"); if(argc < 3) { printf("usage: %s <custom.ipsw> <n82ap|m68ap|n45ap>\n", argv[0]); printf("advanced usage: %s -f <file>\n", argv[0]); printf("n82ap = 3G iPhone, m68ap = First-generation iPhone, n45ap = iPod touch\n"); return 0; } if(strcmp(argv[1], "-f") == 0) { download(createAbstractFileFromFile(fopen(argv[2], "rb")), 2048, 1); return 0; } char ibssName[100]; sprintf(ibssName, "Firmware/dfu/iBSS.%s.RELEASE.dfu", argv[2]); OutputState* data = NULL; loadZipFile(argv[1], &data, "Firmware/dfu/WTF.s5l8900xall.RELEASE.dfu"); loadZipFile(argv[1], &data, ibssName); download(getFileFromOutputState(&data, "Firmware/dfu/WTF.s5l8900xall.RELEASE.dfu"), 2048, 1); sleep(5); download(getFileFromOutputState(&data, ibssName), 2048, 1); releaseOutput(&data); return 0; }
char* xpwntool_get_kbag(char* fileName) { char* strbuf = NULL; AbstractFile* inFile; inFile = openAbstractFile2(createAbstractFileFromFile(fopen(fileName, "rb")), NULL, NULL); if (inFile != NULL && inFile->type == AbstractFileTypeImg3) { Img3Info* i3i = (Img3Info*)(inFile->data); if (i3i != NULL) { Img3Element* kbag = i3i->kbag; if (kbag != NULL && kbag->data != NULL && kbag->header != NULL) { size_t buflen = 1 + 2 * kbag->header->dataSize; strbuf = (char*)HeapAlloc(GetProcessHeap(), 0, buflen); char* bytes = (char*)kbag->data; for (size_t i = 0; i < kbag->header->dataSize; ++i) { snprintf(strbuf + 2 * i, 2, "%02X", (unsigned char) bytes[i]); } strbuf[buflen-1] = '\0'; return strbuf; } } inFile->close(inFile); } return strbuf; }
int main(int argc, const char *argv[]) { io_func* io; Volume* volume; AbstractFile* image; int argOff; TestByteOrder(); if(argc < 3) { printf("usage: %s <image-file> (-k <key>) <ls|cat|mv|mkdir|add|rm|chmod|extract|extractall|rmall|addall|grow|untar> <arguments>\n", argv[0]); return 0; } argOff = 2; if(strstr(argv[1], ".dmg")) { image = createAbstractFileFromFile(fopen(argv[1], "rb")); if(argc > 3) { if(strcmp(argv[2], "-k") == 0) { image = createAbstractFileFromFileVault(image, argv[3]); argOff = 4; } } io = openDmgFilePartition(image, -1); } else { io = openFlatFile(argv[1]); } if(io == NULL) { fprintf(stderr, "error: Cannot open image-file.\n"); return 1; } volume = openVolume(io); if(volume == NULL) { fprintf(stderr, "error: Cannot open volume.\n"); CLOSE(io); return 1; } if(argc > argOff) { if(strcmp(argv[argOff], "ls") == 0) { cmd_ls(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "cat") == 0) { cmd_cat(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "mv") == 0) { cmd_mv(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[2], "symlink") == 0) { cmd_symlink(volume, argc - 2, argv + 2); } else if(strcmp(argv[argOff], "mkdir") == 0) { cmd_mkdir(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "add") == 0) { cmd_add(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "rm") == 0) { cmd_rm(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "chmod") == 0) { cmd_chmod(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "extract") == 0) { cmd_extract(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "extractall") == 0) { cmd_extractall(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "rmall") == 0) { cmd_rmall(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "addall") == 0) { cmd_addall(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "grow") == 0) { cmd_grow(volume, argc - argOff, argv + argOff); } else if(strcmp(argv[argOff], "untar") == 0) { cmd_untar(volume, argc - argOff, argv + argOff); } } closeVolume(volume); CLOSE(io); return 0; }
int xpwntool_enc_dec(char* srcName, char* destName, char* templateFileName, char* ivStr, char* keyStr) { char* inData; size_t inDataSize; AbstractFile* templateFile = NULL; unsigned int* key = NULL; unsigned int* iv = NULL; int hasKey = TRUE; int hasIV = TRUE; if (templateFileName != NULL && strlen(templateFileName) != 0) { templateFile = createAbstractFileFromFile(fopen(templateFileName, "rb")); if(!templateFile) { fprintf(stderr, "error: cannot open template\n"); return 1; } } size_t bytes; hexToInts(keyStr, &key, &bytes); if (bytes == 0) { free(key); key = NULL; } else { hexToInts(ivStr, &iv, &bytes); } AbstractFile* inFile; inFile = openAbstractFile2(createAbstractFileFromFile(fopen(srcName, "rb")), key, iv); if(!inFile) { fprintf(stderr, "error: cannot open infile\n"); return 2; } AbstractFile* outFile = createAbstractFileFromFile(fopen(destName, "wb")); if(!outFile) { fprintf(stderr, "error: cannot open outfile\n"); return 3; } AbstractFile* newFile; if(templateFile) { newFile = duplicateAbstractFile2(templateFile, outFile, key, iv, NULL); if(!newFile) { fprintf(stderr, "error: cannot duplicate file from provided template\n"); return 4; } } else { newFile = outFile; } if(newFile->type == AbstractFileTypeImg3) { AbstractFile2* abstractFile2 = (AbstractFile2*) newFile; if (key != NULL) { abstractFile2->setKey(abstractFile2, key, iv); } } inDataSize = (size_t) inFile->getLength(inFile); inData = (char*) malloc(inDataSize); inFile->read(inFile, inData, inDataSize); inFile->close(inFile); newFile->write(newFile, inData, inDataSize); newFile->close(newFile); free(inData); if(key) free(key); if(iv) free(iv); return 0; }
int main(int argc, char* argv[]) { init_libxpwn(&argc, argv); OutputState *outputState; size_t fileLength; AbstractFile *signFile; Dictionary *signDict = NULL; DataValue *ticket; Dictionary *dict; AbstractFile *manifestFile; Dictionary* manifest; struct component_t *array; char *plist; int i, j, n; int rv, error = 0; X509 *x0, *y1, *y2; uint64_t savecid = 0; const unsigned char *p; int verbose = FALSE; int fromzip = FALSE; if (argc < 3) { XLOG(0, "usage %s file.shsh BuildManifest.plist [-v] [-z]\n", argv[0]); return 0; } for (i = 3; i < argc; i++) { if (!strcmp(argv[i], "-v")) { verbose = TRUE; continue; } if (!strcmp(argv[i], "-z")) { fromzip = TRUE; continue; } } // XXX handle gzip/bplist files signFile = createAbstractFileFromFile(fopen(argv[1], "rb")); if (!signFile) { XLOG(0, "FATAL: cannot open %s\n", argv[1]); exit(1); } fileLength = signFile->getLength(signFile); plist = malloc(fileLength); signFile->read(signFile, plist, fileLength); signFile->close(signFile); signDict = createRoot(plist); free(plist); if (!signDict) { XLOG(0, "FATAL: cannot parse %s\n", argv[1]); exit(1); } MaxLoadZipSize = 128 * 1024; if (fromzip) { outputState = loadZip2(argv[2], TRUE); // XXX ASSERT manifestFile = getFileFromOutputState(&outputState, "BuildManifest.plist"); } else { outputState = NULL; manifestFile = createAbstractFileFromFile(fopen(argv[2], "rb")); } if (!manifestFile) { XLOG(0, "FATAL: cannot open %s\n", argv[2]); exit(1); } fileLength = manifestFile->getLength(manifestFile); plist = malloc(fileLength); manifestFile->read(manifestFile, plist, fileLength); manifestFile->close(manifestFile); manifest = createRoot(plist); free(plist); if (!manifest) { XLOG(0, "FATAL: cannot parse %s\n", argv[2]); exit(1); } releaseOutput(&outputState); array = parseManifest(manifest, &n); if (!array) { XLOG(0, "FATAL: cannot parse manifest\n"); exit(1); } OPENSSL_add_all_algorithms_noconf(); p = cerb; x0 = d2i_X509(NULL, &p, cerb_len); if (!x0) { XLOG(0, "FATAL: cannot load root CA\n"); exit(1); } ticket = (DataValue *)getValueByKey(signDict, "APTicket"); if (ticket) { p = ticket->value; rv = asn1_parse2(&p, ticket->len, 0, 0); if (!rv || !apcert.value || !rsasig.value || !theset.value) { XLOG(0, "FATAL: cannot parse ticket\n"); exit(1); } if (clen > 0 && contarray->len == 8) { savecid = getECID(contarray->value); } if (!savecid) { printf("ERROR: bad, bad ECID\n"); error = 1; } rv = extract2Certs(apcert.value, apcert.len, &y1, &y2); if (rv == 0) { rv = cryptoMagic(x0, y1, y2, theset.value, theset.len, (unsigned char *)rsasig.value, rsasig.len, NULL); X509_free(y1); X509_free(y2); } if (rv) { printf("ERROR: APTicket failed crypto\n"); error = 1; } } else { VERBOSE("WARNING: cannot find ticket in %s\n", argv[1]); } dict = (Dictionary *)signDict->values; while (dict) { DataValue *blob = NULL; DataValue *partialDigest = NULL; if (dict->dValue.type == DictionaryType) { blob = (DataValue *)getValueByKey(dict, "Blob"); partialDigest = (DataValue *)getValueByKey(dict, "PartialDigest"); } if (blob && partialDigest) { const char *diag = checkBlob(x0, blob, partialDigest, &savecid); if (diag) { printf("ERROR: Blob for %s is invalid (%s)\n", dict->dValue.key, diag); error = 1; } else { for (i = 0; i < n; i++) { struct component_t *centry = array + i; if (centry->partial && partialDigest->len == centry->partial->len && !memcmp(partialDigest->value, centry->partial->value, partialDigest->len)) { array[i].blob = blob; } } } } dict = (Dictionary *)dict->dValue.next; } if (!ticket && !savecid) { printf("ERROR: bad, bad ECID\n"); error = 1; } for (i = 0; i < n; i++) { struct component_t *centry = array + i; int found = FALSE; for (j = 0; j < clen; j++) { struct tuple_t *tentry = contarray + j; if (tentry->len == centry->digest->len && !memcmp(tentry->value, centry->digest->value, tentry->len)) { found = TRUE; } } if (!found) { if (centry->blob) { VERBOSE("WARNING: no digest for %s (%s), but it has blob\n", centry->key, centry->path); } else if (!centry->required) { VERBOSE("WARNING: no digest for %s (%s), but it is not critical\n", centry->key, centry->path); } else { printf("ERROR: no digest for %s (%s) and no blob found\n", centry->key, centry->path); error = 1; } } else { VERBOSE("INFO: %s (%s) is signed by APTicket%s\n", centry->key, centry->path, centry->blob ? " and blob" : ""); } } free(array); free(contarray); releaseDictionary(manifest); releaseDictionary(signDict); if (error) { printf("%s is BROKEN\n", argv[1]); } else { printf("%s seems usable for ECID 0x%016llX\n", argv[1], savecid); } X509_free(x0); EVP_cleanup(); ERR_remove_state(0); CRYPTO_cleanup_all_ex_data(); return error; }
void writeOutput(OutputState** state, char* ipsw) { OutputState* curFile; OutputState* next; zip_fileinfo info; struct tm* filedate; time_t tm_t; zipFile zip; tm_t = time(NULL); filedate = localtime(&tm_t); info.tmz_date.tm_sec = filedate->tm_sec; info.tmz_date.tm_min = filedate->tm_min; info.tmz_date.tm_hour = filedate->tm_hour; info.tmz_date.tm_mday = filedate->tm_mday; info.tmz_date.tm_mon = filedate->tm_mon ; info.tmz_date.tm_year = filedate->tm_year; info.dosDate = 0; info.internal_fa = 0; info.external_fa = 0; ASSERT(zip = zipOpen(ipsw, APPEND_STATUS_CREATE), "Cannot open output zip file"); next = *state; while(next != NULL) { curFile = next; next = next->next; printf("packing: %s (%ld)\n", curFile->fileName, (long) curFile->bufferSize); fflush(stdout); if(curFile->bufferSize > 0) { ASSERT(zipOpenNewFileInZip(zip, curFile->fileName, &info, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) == 0, "error adding to zip"); if(curFile->tmpFileName == NULL) { ASSERT(zipWriteInFileInZip(zip, curFile->buffer, curFile->bufferSize) == 0, "error writing to zip"); } else { AbstractFile* tmpFile = createAbstractFileFromFile(fopen(curFile->tmpFileName, "rb")); char* buffer = malloc(DEFAULT_BUFFER_SIZE); size_t left = tmpFile->getLength(tmpFile); while(left > 0) { size_t toRead; if(left > DEFAULT_BUFFER_SIZE) toRead = DEFAULT_BUFFER_SIZE; else toRead = left; ASSERT(tmpFile->read(tmpFile, buffer, toRead) == toRead, "error reading data"); ASSERT(zipWriteInFileInZip(zip, buffer, toRead) == 0, "error writing to zip"); left -= toRead; } tmpFile->close(tmpFile); free(buffer); } } else { ASSERT(zipOpenNewFileInZip(zip, curFile->fileName, &info, NULL, 0, NULL, 0, NULL, 0, 0) == 0, "error adding to zip"); } ASSERT(zipCloseFileInZip(zip) == 0, "error closing file in zip"); if(curFile->tmpFileName) { unlink(curFile->tmpFileName); free(curFile->tmpFileName); } free(curFile->fileName); if(curFile->buffer) { free(curFile->buffer); } free(curFile); } zipClose(zip, NULL); }
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; }
Dictionary* parseIPSW2(const char* inputIPSW, const char* bundleRoot, char** bundlePath, OutputState** state, int useMemory) { Dictionary* info; char* infoPath; AbstractFile* plistFile; char* plist; FILE* inputIPSWFile; SHA_CTX sha1_ctx; char* buffer; int read; unsigned char hash[20]; DIR* dir; struct dirent* ent; StringValue* plistSHA1String; unsigned int plistHash[20]; int i; *bundlePath = NULL; inputIPSWFile = fopen(inputIPSW, "rb"); if(!inputIPSWFile) { return NULL; } XLOG(0, "Hashing IPSW...\n"); buffer = malloc(BUFFERSIZE); SHA1_Init(&sha1_ctx); while(!feof(inputIPSWFile)) { read = fread(buffer, 1, BUFFERSIZE, inputIPSWFile); SHA1_Update(&sha1_ctx, buffer, read); } SHA1_Final(hash, &sha1_ctx); free(buffer); fclose(inputIPSWFile); XLOG(0, "Matching IPSW in %s... (%02x%02x%02x%02x...)\n", bundleRoot, (int) hash[0], (int) hash[1], (int) hash[2], (int) hash[3]); dir = opendir(bundleRoot); if(dir == NULL) { XLOG(1, "Bundles directory not found\n"); return NULL; } while((ent = readdir(dir)) != NULL) { if(ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) { continue; } infoPath = (char*) malloc(sizeof(char) * (strlen(bundleRoot) + sizeof(PATH_SEPARATOR) + strlen(ent->d_name) + sizeof(PATH_SEPARATOR "Info.plist"))); sprintf(infoPath, "%s" PATH_SEPARATOR "%s" PATH_SEPARATOR "Info.plist", bundleRoot, ent->d_name); XLOG(0, "checking: %s\n", infoPath); if((plistFile = createAbstractFileFromFile(fopen(infoPath, "rb"))) != NULL) { plist = (char*) malloc(plistFile->getLength(plistFile)); plistFile->read(plistFile, plist, plistFile->getLength(plistFile)); plistFile->close(plistFile); info = createRoot(plist); free(plist); plistSHA1String = (StringValue*)getValueByKey(info, "SHA1"); if(plistSHA1String) { sscanf(plistSHA1String->value, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", &plistHash[0], &plistHash[1], &plistHash[2], &plistHash[3], &plistHash[4], &plistHash[5], &plistHash[6], &plistHash[7], &plistHash[8], &plistHash[9], &plistHash[10], &plistHash[11], &plistHash[12], &plistHash[13], &plistHash[14], &plistHash[15], &plistHash[16], &plistHash[17], &plistHash[18], &plistHash[19]); for(i = 0; i < 20; i++) { if(plistHash[i] != hash[i]) { break; } } if(i == 20) { *bundlePath = (char*) malloc(sizeof(char) * (strlen(bundleRoot) + sizeof(PATH_SEPARATOR) + strlen(ent->d_name))); sprintf(*bundlePath, "%s" PATH_SEPARATOR "%s", bundleRoot, ent->d_name); free(infoPath); break; } } releaseDictionary(info); } free(infoPath); } closedir(dir); if(*bundlePath == NULL) { return NULL; } *state = loadZip2(inputIPSW, useMemory); return info; }
void addAllInFolder(HFSCatalogNodeID folderID, Volume* volume, const char* parentName) { CatalogRecordList* list; CatalogRecordList* theList; char cwd[1024]; char fullName[1024]; char testBuffer[1024]; char* pathComponent; int pathLen; char* name; DIR* dir; DIR* tmp; HFSCatalogNodeID cnid; struct dirent* ent; AbstractFile* file; HFSPlusCatalogFile* outFile; strcpy(fullName, parentName); pathComponent = fullName + strlen(fullName); ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); theList = list = getFolderContents(folderID, volume); ASSERT((dir = opendir(cwd)) != NULL, "opendir"); while((ent = readdir(dir)) != NULL) { if(ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) { continue; } strcpy(pathComponent, ent->d_name); pathLen = strlen(fullName); cnid = 0; list = theList; while(list != NULL) { name = unicodeToAscii(&list->name); if(strcmp(name, ent->d_name) == 0) { cnid = (list->record->recordType == kHFSPlusFolderRecord) ? (((HFSPlusCatalogFolder*)list->record)->folderID) : (((HFSPlusCatalogFile*)list->record)->fileID); free(name); break; } free(name); list = list->next; } if((tmp = opendir(ent->d_name)) != NULL) { closedir(tmp); printf("folder: %s\n", fullName); fflush(stdout); if(cnid == 0) { cnid = newFolder(fullName, volume); } fullName[pathLen] = '/'; fullName[pathLen + 1] = '\0'; ASSERT(chdir(ent->d_name) == 0, "chdir"); addAllInFolder(cnid, volume, fullName); ASSERT(chdir(cwd) == 0, "chdir"); } else { printf("file: %s\n", fullName); fflush(stdout); if(cnid == 0) { cnid = newFile(fullName, volume); } file = createAbstractFileFromFile(fopen(ent->d_name, "rb")); ASSERT(file != NULL, "fopen"); outFile = (HFSPlusCatalogFile*)getRecordByCNID(cnid, volume); writeToHFSFile(outFile, file, volume); file->close(file); free(outFile); if(strncmp(fullName, "/Applications/", sizeof("/Applications/") - 1) == 0) { testBuffer[0] = '\0'; strcpy(testBuffer, "/Applications/"); strcat(testBuffer, ent->d_name); strcat(testBuffer, ".app/"); strcat(testBuffer, ent->d_name); if(strcmp(testBuffer, fullName) == 0) { if(strcmp(ent->d_name, "Installer") == 0 || strcmp(ent->d_name, "BootNeuter") == 0 ) { printf("Giving setuid permissions to %s...\n", fullName); fflush(stdout); chmodFile(fullName, 04755, volume); } else { printf("Giving permissions to %s\n", fullName); fflush(stdout); chmodFile(fullName, 0755, volume); } } } else if(strncmp(fullName, "/bin/", sizeof("/bin/") - 1) == 0 || strncmp(fullName, "/Applications/BootNeuter.app/bin/", sizeof("/Applications/BootNeuter.app/bin/") - 1) == 0 || strncmp(fullName, "/sbin/", sizeof("/sbin/") - 1) == 0 || strncmp(fullName, "/usr/sbin/", sizeof("/usr/sbin/") - 1) == 0 || strncmp(fullName, "/usr/bin/", sizeof("/usr/bin/") - 1) == 0 || strncmp(fullName, "/usr/libexec/", sizeof("/usr/libexec/") - 1) == 0 || strncmp(fullName, "/usr/local/bin/", sizeof("/usr/local/bin/") - 1) == 0 || strncmp(fullName, "/usr/local/sbin/", sizeof("/usr/local/sbin/") - 1) == 0 || strncmp(fullName, "/usr/local/libexec/", sizeof("/usr/local/libexec/") - 1) == 0 ) { chmodFile(fullName, 0755, volume); printf("Giving permissions to %s\n", fullName); fflush(stdout); } } } closedir(dir); releaseCatalogRecordList(theList); }
int main(int argc, char* argv[]) { init_libxpwn(); Dictionary* info; Dictionary* firmwarePatches; Dictionary* patchDict; ArrayValue* patchArray; void* buffer; StringValue* actionValue; StringValue* pathValue; StringValue* fileValue; StringValue* patchValue; char* patchPath; char* rootFSPathInIPSW; io_func* rootFS; Volume* rootVolume; size_t rootSize; size_t preferredRootSize = 0; size_t minimumRootSize = 0; char* ramdiskFSPathInIPSW; unsigned int ramdiskKey[16]; unsigned int ramdiskIV[16]; unsigned int* pRamdiskKey = NULL; unsigned int* pRamdiskIV = NULL; io_func* ramdiskFS; Volume* ramdiskVolume; char* updateRamdiskFSPathInIPSW = NULL; int i; OutputState* outputState; char* bundlePath; char* bundleRoot = "FirmwareBundles/"; int mergePaths; char* outputIPSW; void* imageBuffer; size_t imageSize; AbstractFile* bootloader39 = NULL; AbstractFile* bootloader46 = NULL; AbstractFile* applelogo = NULL; AbstractFile* recoverymode = NULL; char noWipe = FALSE; char unlockBaseband = FALSE; char selfDestruct = FALSE; char use39 = FALSE; char use46 = FALSE; char doBootNeuter = FALSE; char updateBB = FALSE; char useMemory = FALSE; unsigned int key[16]; unsigned int iv[16]; unsigned int* pKey = NULL; unsigned int* pIV = NULL; if(argc < 3) { XLOG(0, "usage %s <input.ipsw> <target.ipsw> [-b <bootimage.png>] [-r <recoveryimage.png>] [-s <system partition size>] [-memory] [-bbupdate] [-nowipe] [-e \"<action to exclude>\"] [[-unlock] [-use39] [-use46] [-cleanup] -3 <bootloader 3.9 file> -4 <bootloader 4.6 file>] <package1.tar> <package2.tar>...\n", argv[0]); return 0; } outputIPSW = argv[2]; int* toRemove = NULL; int numToRemove = 0; for(i = 3; i < argc; i++) { if(argv[i][0] != '-') { break; } if(strcmp(argv[i], "-memory") == 0) { useMemory = TRUE; continue; } if(strcmp(argv[i], "-s") == 0) { int size; sscanf(argv[i + 1], "%d", &size); preferredRootSize = size; i++; continue; } if(strcmp(argv[i], "-nowipe") == 0) { noWipe = TRUE; continue; } if(strcmp(argv[i], "-bbupdate") == 0) { updateBB = TRUE; continue; } if(strcmp(argv[i], "-e") == 0) { numToRemove++; toRemove = realloc(toRemove, numToRemove * sizeof(int)); toRemove[numToRemove - 1] = i + 1; i++; continue; } if(strcmp(argv[i], "-unlock") == 0) { unlockBaseband = TRUE; continue; } if(strcmp(argv[i], "-cleanup") == 0) { selfDestruct = TRUE; continue; } if(strcmp(argv[i], "-use39") == 0) { if(use46) { XLOG(0, "error: select only one of -use39 and -use46\n"); exit(1); } use39 = TRUE; continue; } if(strcmp(argv[i], "-use46") == 0) { if(use39) { XLOG(0, "error: select only one of -use39 and -use46\n"); exit(1); } use46 = TRUE; continue; } if(strcmp(argv[i], "-b") == 0) { applelogo = createAbstractFileFromFile(fopen(argv[i + 1], "rb")); if(!applelogo) { XLOG(0, "cannot open %s\n", argv[i + 1]); exit(1); } i++; continue; } if(strcmp(argv[i], "-r") == 0) { recoverymode = createAbstractFileFromFile(fopen(argv[i + 1], "rb")); if(!recoverymode) { XLOG(0, "cannot open %s\n", argv[i + 1]); exit(1); } i++; continue; } if(strcmp(argv[i], "-3") == 0) { bootloader39 = createAbstractFileFromFile(fopen(argv[i + 1], "rb")); if(!bootloader39) { XLOG(0, "cannot open %s\n", argv[i + 1]); exit(1); } i++; continue; } if(strcmp(argv[i], "-4") == 0) { bootloader46 = createAbstractFileFromFile(fopen(argv[i + 1], "rb")); if(!bootloader46) { XLOG(0, "cannot open %s\n", argv[i + 1]); exit(1); } i++; continue; } } mergePaths = i; if(use39 || use46 || unlockBaseband || selfDestruct || bootloader39 || bootloader46) { if(!(bootloader39) || !(bootloader46)) { XLOG(0, "error: you must specify both bootloader files.\n"); exit(1); } else { doBootNeuter = TRUE; } } info = parseIPSW2(argv[1], bundleRoot, &bundlePath, &outputState, useMemory); if(info == NULL) { XLOG(0, "error: Could not load IPSW\n"); exit(1); } firmwarePatches = (Dictionary*)getValueByKey(info, "FilesystemPatches"); int j; for(j = 0; j < numToRemove; j++) { removeKey(firmwarePatches, argv[toRemove[j]]); } free(toRemove); firmwarePatches = (Dictionary*)getValueByKey(info, "FirmwarePatches"); patchDict = (Dictionary*) firmwarePatches->values; while(patchDict != NULL) { fileValue = (StringValue*) getValueByKey(patchDict, "File"); StringValue* keyValue = (StringValue*) getValueByKey(patchDict, "Key"); StringValue* ivValue = (StringValue*) getValueByKey(patchDict, "IV"); pKey = NULL; pIV = NULL; if(keyValue) { sscanf(keyValue->value, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &key[0], &key[1], &key[2], &key[3], &key[4], &key[5], &key[6], &key[7], &key[8], &key[9], &key[10], &key[11], &key[12], &key[13], &key[14], &key[15]); pKey = key; } if(ivValue) { sscanf(ivValue->value, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &iv[0], &iv[1], &iv[2], &iv[3], &iv[4], &iv[5], &iv[6], &iv[7], &iv[8], &iv[9], &iv[10], &iv[11], &iv[12], &iv[13], &iv[14], &iv[15]); pIV = iv; } if(strcmp(patchDict->dValue.key, "Restore Ramdisk") == 0) { ramdiskFSPathInIPSW = fileValue->value; if(pKey) { memcpy(ramdiskKey, key, sizeof(key)); memcpy(ramdiskIV, iv, sizeof(iv)); pRamdiskKey = ramdiskKey; pRamdiskIV = ramdiskIV; } else { pRamdiskKey = NULL; pRamdiskIV = NULL; } } if(strcmp(patchDict->dValue.key, "Update Ramdisk") == 0) { updateRamdiskFSPathInIPSW = fileValue->value; } patchValue = (StringValue*) getValueByKey(patchDict, "Patch2"); if(patchValue) { if(noWipe) { XLOG(0, "%s: ", patchDict->dValue.key); fflush(stdout); doPatch(patchValue, fileValue, bundlePath, &outputState, pKey, pIV, useMemory); patchDict = (Dictionary*) patchDict->dValue.next; continue; /* skip over the normal Patch */ } } patchValue = (StringValue*) getValueByKey(patchDict, "Patch"); if(patchValue) { XLOG(0, "%s: ", patchDict->dValue.key); fflush(stdout); doPatch(patchValue, fileValue, bundlePath, &outputState, pKey, pIV, useMemory); } if(strcmp(patchDict->dValue.key, "AppleLogo") == 0 && applelogo) { XLOG(0, "replacing %s\n", fileValue->value); fflush(stdout); ASSERT((imageBuffer = replaceBootImage(getFileFromOutputState(&outputState, fileValue->value), pKey, pIV, applelogo, &imageSize)) != NULL, "failed to use new image"); addToOutput(&outputState, fileValue->value, imageBuffer, imageSize); } if(strcmp(patchDict->dValue.key, "RecoveryMode") == 0 && recoverymode) { XLOG(0, "replacing %s\n", fileValue->value); fflush(stdout); ASSERT((imageBuffer = replaceBootImage(getFileFromOutputState(&outputState, fileValue->value), pKey, pIV, recoverymode, &imageSize)) != NULL, "failed to use new image"); addToOutput(&outputState, fileValue->value, imageBuffer, imageSize); } patchDict = (Dictionary*) patchDict->dValue.next; } fileValue = (StringValue*) getValueByKey(info, "RootFilesystem"); rootFSPathInIPSW = fileValue->value; size_t defaultRootSize = ((IntegerValue*) getValueByKey(info, "RootFilesystemSize"))->value; minimumRootSize = defaultRootSize * 1000 * 1000; minimumRootSize -= minimumRootSize % 512; if(preferredRootSize == 0) { preferredRootSize = defaultRootSize; } rootSize = preferredRootSize * 1000 * 1000; rootSize -= rootSize % 512; if(useMemory) { buffer = malloc(rootSize); } else { buffer = NULL; } if(buffer == NULL) { XLOG(2, "using filesystem backed temporary storage\n"); } extractDmg( createAbstractFileFromFileVault(getFileFromOutputState(&outputState, rootFSPathInIPSW), ((StringValue*)getValueByKey(info, "RootFilesystemKey"))->value), openRoot((void**)&buffer, &rootSize), -1); rootFS = IOFuncFromAbstractFile(openRoot((void**)&buffer, &rootSize)); rootVolume = openVolume(rootFS); XLOG(0, "Growing root to minimum: %ld\n", (long) defaultRootSize); fflush(stdout); grow_hfs(rootVolume, minimumRootSize); if(rootSize > minimumRootSize) { XLOG(0, "Growing root: %ld\n", (long) preferredRootSize); fflush(stdout); grow_hfs(rootVolume, rootSize); } firmwarePatches = (Dictionary*)getValueByKey(info, "FilesystemPatches"); patchArray = (ArrayValue*) firmwarePatches->values; while(patchArray != NULL) { for(i = 0; i < patchArray->size; i++) { patchDict = (Dictionary*) patchArray->values[i]; fileValue = (StringValue*) getValueByKey(patchDict, "File"); actionValue = (StringValue*) getValueByKey(patchDict, "Action"); if(strcmp(actionValue->value, "ReplaceKernel") == 0) { pathValue = (StringValue*) getValueByKey(patchDict, "Path"); XLOG(0, "replacing kernel... %s -> %s\n", fileValue->value, pathValue->value); fflush(stdout); add_hfs(rootVolume, getFileFromOutputState(&outputState, fileValue->value), pathValue->value); } if(strcmp(actionValue->value, "Patch") == 0) { patchValue = (StringValue*) getValueByKey(patchDict, "Patch"); patchPath = (char*) malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2)); strcpy(patchPath, bundlePath); strcat(patchPath, "/"); strcat(patchPath, patchValue->value); XLOG(0, "patching %s (%s)... ", fileValue->value, patchPath); doPatchInPlace(rootVolume, fileValue->value, patchPath); free(patchPath); } } patchArray = (ArrayValue*) patchArray->dValue.next; } for(; mergePaths < argc; mergePaths++) { XLOG(0, "merging %s\n", argv[mergePaths]); AbstractFile* tarFile = createAbstractFileFromFile(fopen(argv[mergePaths], "rb")); if(tarFile == NULL) { XLOG(1, "cannot find %s, make sure your slashes are in the right direction\n", argv[mergePaths]); releaseOutput(&outputState); closeRoot(buffer); exit(0); } hfs_untar(rootVolume, tarFile); tarFile->close(tarFile); } if(pRamdiskKey) { ramdiskFS = IOFuncFromAbstractFile(openAbstractFile2(getFileFromOutputStateForOverwrite(&outputState, ramdiskFSPathInIPSW), pRamdiskKey, pRamdiskIV)); } else { XLOG(0, "unencrypted ramdisk\n"); ramdiskFS = IOFuncFromAbstractFile(openAbstractFile(getFileFromOutputStateForOverwrite(&outputState, ramdiskFSPathInIPSW))); } ramdiskVolume = openVolume(ramdiskFS); XLOG(0, "growing ramdisk: %d -> %d\n", ramdiskVolume->volumeHeader->totalBlocks * ramdiskVolume->volumeHeader->blockSize, (ramdiskVolume->volumeHeader->totalBlocks + 4) * ramdiskVolume->volumeHeader->blockSize); grow_hfs(ramdiskVolume, (ramdiskVolume->volumeHeader->totalBlocks + 4) * ramdiskVolume->volumeHeader->blockSize); if(doBootNeuter) { firmwarePatches = (Dictionary*)getValueByKey(info, "BasebandPatches"); if(firmwarePatches != NULL) { patchDict = (Dictionary*) firmwarePatches->values; while(patchDict != NULL) { pathValue = (StringValue*) getValueByKey(patchDict, "Path"); fileValue = (StringValue*) getValueByKey(patchDict, "File"); if(fileValue) { XLOG(0, "copying %s -> %s... ", fileValue->value, pathValue->value); fflush(stdout); if(copyAcrossVolumes(ramdiskVolume, rootVolume, fileValue->value, pathValue->value)) { patchValue = (StringValue*) getValueByKey(patchDict, "Patch"); if(patchValue) { patchPath = malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2)); strcpy(patchPath, bundlePath); strcat(patchPath, "/"); strcat(patchPath, patchValue->value); XLOG(0, "patching %s (%s)... ", pathValue->value, patchPath); fflush(stdout); doPatchInPlace(rootVolume, pathValue->value, patchPath); free(patchPath); } } } if(strcmp(patchDict->dValue.key, "Bootloader 3.9") == 0 && bootloader39 != NULL) { add_hfs(rootVolume, bootloader39, pathValue->value); } if(strcmp(patchDict->dValue.key, "Bootloader 4.6") == 0 && bootloader46 != NULL) { add_hfs(rootVolume, bootloader46, pathValue->value); } patchDict = (Dictionary*) patchDict->dValue.next; } } fixupBootNeuterArgs(rootVolume, unlockBaseband, selfDestruct, use39, use46); } createRestoreOptions(ramdiskVolume, preferredRootSize, updateBB); closeVolume(ramdiskVolume); CLOSE(ramdiskFS); if(updateRamdiskFSPathInIPSW) removeFileFromOutputState(&outputState, updateRamdiskFSPathInIPSW); closeVolume(rootVolume); CLOSE(rootFS); buildDmg(openRoot((void**)&buffer, &rootSize), getFileFromOutputStateForReplace(&outputState, rootFSPathInIPSW)); closeRoot(buffer); writeOutput(&outputState, outputIPSW); releaseDictionary(info); free(bundlePath); return 0; }
int main(int argc, char* argv[]) { init_libxpwn(&argc, argv); if(argc < 4) { print_usage(); return 0; } AbstractFile* png; AbstractFile* img; AbstractFile* dst; void* imageBuffer; size_t imageSize; unsigned int key[32]; unsigned int iv[16]; unsigned int* pKey = NULL; unsigned int* pIV = NULL; if(strcmp(argv[1], "inject") == 0) { if(argc < 5) { print_usage(); return 0; } png = createAbstractFileFromFile(fopen(argv[2], "rb")); img = createAbstractFileFromFile(fopen(argv[4], "rb")); dst = createAbstractFileFromFile(fopen(argv[3], "wb")); if(argc >= 7) { sscanf(argv[5], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &iv[0], &iv[1], &iv[2], &iv[3], &iv[4], &iv[5], &iv[6], &iv[7], &iv[8], &iv[9], &iv[10], &iv[11], &iv[12], &iv[13], &iv[14], &iv[15]); sscanf(argv[6], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &key[0], &key[1], &key[2], &key[3], &key[4], &key[5], &key[6], &key[7], &key[8], &key[9], &key[10], &key[11], &key[12], &key[13], &key[14], &key[15], &key[16], &key[17], &key[18], &key[19], &key[20], &key[21], &key[22], &key[23], &key[24], &key[25], &key[26], &key[27], &key[28], &key[29], &key[30], &key[31]); pKey = key; pIV = iv; } imageBuffer = replaceBootImage(img, pKey, pIV, png, &imageSize); dst->write(dst, imageBuffer, imageSize); dst->close(dst); } else if(strcmp(argv[1], "extract") == 0) { img = createAbstractFileFromFile(fopen(argv[2], "rb")); if(argc >= 6) { sscanf(argv[4], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &iv[0], &iv[1], &iv[2], &iv[3], &iv[4], &iv[5], &iv[6], &iv[7], &iv[8], &iv[9], &iv[10], &iv[11], &iv[12], &iv[13], &iv[14], &iv[15]); sscanf(argv[5], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", &key[0], &key[1], &key[2], &key[3], &key[4], &key[5], &key[6], &key[7], &key[8], &key[9], &key[10], &key[11], &key[12], &key[13], &key[14], &key[15], &key[16], &key[17], &key[18], &key[19], &key[20], &key[21], &key[22], &key[23], &key[24], &key[25], &key[26], &key[27], &key[28], &key[29], &key[30], &key[31]); pKey = key; pIV = iv; } if(convertToPNG(img, pKey, pIV, argv[3]) < 0) { XLOG(1, "error converting img to png"); } } return 0; }
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; }