void do24kpwn(Img3Info* info, Img3Element* element, off_t curPos, const uint8_t* overflow, size_t overflow_size, const uint8_t* payload, size_t payload_size) { off_t sizeRequired = (0x24000 + overflow_size) - curPos; off_t dataRequired = sizeRequired - sizeof(AppleImg3Header); element->data = realloc(element->data, dataRequired); memset(((uint8_t*)element->data) + element->header->dataSize, 0, dataRequired - element->header->dataSize); uint32_t overflowOffset = 0x24000 - (curPos + sizeof(AppleImg3Header)); uint32_t payloadOffset = 0x23000 - (curPos + sizeof(AppleImg3Header)); memcpy(((uint8_t*)element->data) + overflowOffset, overflow, overflow_size); memcpy(((uint8_t*)element->data) + payloadOffset, payload, payload_size); uint32_t* i; for(i = (uint32_t*)(((uint8_t*)element->data) + payloadOffset); i < (uint32_t*)(((uint8_t*)element->data) + payloadOffset + payload_size); i++) { uint32_t candidate = *i; FLIPENDIANLE(candidate); if(candidate == 0xDDCCBBAA) { candidate = info->replaceDWord; FLIPENDIANLE(candidate); *i = candidate; break; } } element->header->size = sizeRequired; element->header->dataSize = dataRequired; }
void flipIBootIMHeader(IBootIMHeader* header) { FLIPENDIANLE(header->unknown); FLIPENDIANLE(header->compression_type); FLIPENDIANLE(header->format); FLIPENDIANLE(header->width); FLIPENDIANLE(header->height); }
void flipHFSPlusCmpfEnd(HFSPlusCmpfEnd* data) { FLIPENDIAN(data->unk1); FLIPENDIAN(data->unk2); FLIPENDIAN(data->unk3); FLIPENDIAN(data->magic); FLIPENDIAN(data->flags); FLIPENDIANLE(data->size); FLIPENDIANLE(data->unk4); }
static size_t receiveDataBodySingle(unsigned char* data, size_t size, size_t nmemb, ReceiveDataBodyDataRef bodyData) { size_t byteCount = size * nmemb; ReceiveBodyFileData *pFileData = bodyData->currentFile; // Read LocalFile header if (pFileData->bytesLeftInLocalFile) { if (byteCount < pFileData->bytesLeftInLocalFile) { memcpy(&pFileData->localFileBytes[sizeof(LocalFile) - pFileData->bytesLeftInLocalFile], data, byteCount); pFileData->bytesLeftInLocalFile -= byteCount; return size * nmemb; } memcpy(&pFileData->localFileBytes[sizeof(LocalFile) - pFileData->bytesLeftInLocalFile], data, pFileData->bytesLeftInLocalFile); data += pFileData->bytesLeftInLocalFile; byteCount -= pFileData->bytesLeftInLocalFile; pFileData->bytesLeftInLocalFile = 0; FLIPENDIANLE(pFileData->localFile.signature); FLIPENDIANLE(pFileData->localFile.versionExtract); // FLIPENDIANLE(pFileData->localFile.flags); FLIPENDIANLE(pFileData->localFile.method); FLIPENDIANLE(pFileData->localFile.modTime); FLIPENDIANLE(pFileData->localFile.modDate); // FLIPENDIANLE(pFileData->localFile.crc32); FLIPENDIANLE(pFileData->localFile.compressedSize); FLIPENDIANLE(pFileData->localFile.size); FLIPENDIANLE(pFileData->localFile.lenFileName); FLIPENDIANLE(pFileData->localFile.lenExtra); pFileData->bytesLeftBeforeData = pFileData->localFile.lenFileName + pFileData->localFile.lenExtra; } // Read file name and extra bytes before body if (pFileData->bytesLeftBeforeData) { if (byteCount < pFileData->bytesLeftBeforeData) { pFileData->bytesLeftBeforeData -= byteCount; return size * nmemb; } data += pFileData->bytesLeftBeforeData; byteCount -= pFileData->bytesLeftBeforeData; pFileData->bytesLeftBeforeData = 0; pFileData->startBodyCallback(bodyData); } // Read body if (pFileData->bytesLeftInData) { if (byteCount < pFileData->bytesLeftInData) { if (pFileData->processBodyCallback(data, byteCount, bodyData) != byteCount) return 0; pFileData->bytesLeftInData -= byteCount; return size * nmemb; } if (pFileData->processBodyCallback(data, pFileData->bytesLeftInData, bodyData) != pFileData->bytesLeftInData) return 0; pFileData->finishBodyCallback(bodyData); pFileData->bytesLeftInData = 0; } return size * nmemb; }
AbstractFile *openAbstractFile(AbstractFile * file) { uint32_t signatureBE; uint32_t signatureLE; if (!file) return NULL; file->seek(file, 0); file->read(file, &signatureBE, sizeof(signatureBE)); signatureLE = signatureBE; FLIPENDIAN(signatureBE); FLIPENDIANLE(signatureLE); file->seek(file, 0); if (signatureBE == SIGNATURE_8900) { return openAbstractFile(createAbstractFileFrom8900(file)); } else if (signatureLE == IMG2_SIGNATURE) { return openAbstractFile(createAbstractFileFromImg2(file)); } else if (signatureLE == IMG3_SIGNATURE) { return openAbstractFile(createAbstractFileFromImg3(file)); } else if (signatureBE == COMP_SIGNATURE) { return openAbstractFile(createAbstractFileFromComp(file)); } else { return file; } }
AbstractFile* duplicateAbstractFile(AbstractFile* file, AbstractFile* backing) { uint32_t signatureBE; uint32_t signatureLE; AbstractFile* orig; if (!backing) { /* imagine that: createAbstractFileFromComp() fails, because of decompress_lzss() */ return NULL; } file->seek(file, 0); file->read(file, &signatureBE, sizeof(signatureBE)); signatureLE = signatureBE; FLIPENDIAN(signatureBE); FLIPENDIANLE(signatureLE); file->seek(file, 0); if(signatureLE == IMG2_SIGNATURE) { orig = createAbstractFileFromImg2(file); return duplicateAbstractFile(orig, duplicateImg2File(orig, backing)); } else if(signatureLE == IMG3_SIGNATURE) { orig = createAbstractFileFromImg3(file); return duplicateAbstractFile(orig, duplicateImg3File(orig, backing)); } else if(signatureBE == COMP_SIGNATURE) { orig = createAbstractFileFromComp(file); return duplicateAbstractFile(orig, duplicateCompFile(orig, backing)); } else { file->close(file); return backing; } }
uint64_t getECID(const void *data) { unsigned char temp[8]; memcpy(temp, data, sizeof(temp)); FLIPENDIANLE(temp); return *(uint64_t *)temp; }
AbstractFile *duplicateAbstractFile2(AbstractFile * file, AbstractFile * backing, const unsigned int *key, const unsigned int *iv, AbstractFile * certificate) { uint32_t signatureBE; uint32_t signatureLE; AbstractFile *orig; AbstractFile *newFile; file->seek(file, 0); file->read(file, &signatureBE, sizeof(signatureBE)); signatureLE = signatureBE; FLIPENDIAN(signatureBE); FLIPENDIANLE(signatureLE); file->seek(file, 0); if (signatureBE == SIGNATURE_8900) { orig = createAbstractFileFrom8900(file); newFile = duplicate8900File(orig, backing); if (certificate != NULL) replaceCertificate8900(newFile, certificate); return duplicateAbstractFile(orig, newFile); } else if (signatureLE == IMG2_SIGNATURE) { orig = createAbstractFileFromImg2(file); return duplicateAbstractFile(orig, duplicateImg2File(orig, backing)); } else if (signatureLE == IMG3_SIGNATURE) { AbstractFile2 *newFile; AbstractFile2 *img3; img3 = (AbstractFile2 *) createAbstractFileFromImg3(file); if (key != NULL) img3->setKey(img3, key, iv); newFile = (AbstractFile2 *) duplicateImg3File((AbstractFile *) img3, backing); if (key != NULL) img3->setKey(newFile, key, iv); if (certificate != NULL) replaceCertificateImg3((AbstractFile *) newFile, certificate); return duplicateAbstractFile((AbstractFile *) img3, (AbstractFile *) newFile); } else if (signatureBE == COMP_SIGNATURE) { orig = createAbstractFileFromComp(file); return duplicateAbstractFile(orig, duplicateCompFile(orig, backing)); } else { file->close(file); return backing; } }
void closeImg3(AbstractFile * file) { uint8_t ivec[16]; Img3Info *info = (Img3Info *) file->data; if (info->dirty) { if (info->encrypted) { uint32_t sz = info->data->header->dataSize; if (info->decryptLast) { sz = info->data->header->size; } memcpy(ivec, info->iv, 16); AES_cbc_encrypt(info->data->data, info->data->data, (sz / 16) * 16, &(info->encryptKey), ivec, AES_ENCRYPT); } if (info->exploit24k) { info->replaceDWord = *((uint32_t *) info->data->data); FLIPENDIANLE(info->replaceDWord); *((uint32_t *) info->data->data) = 0x22023001; flipEndianLE(info->data->data, 4); } if (info->exploitN8824k) { info->replaceDWord = *((uint32_t *) info->data->data); FLIPENDIANLE(info->replaceDWord); *((uint32_t *) info->data->data) = 0x84023001; flipEndianLE(info->data->data, 4); } info->file->seek(info->file, 0); info->root->header->dataSize = 0; /* hack to make certain writeImg3Element doesn't preallocate */ info->root->header->size = 0; writeImg3Element(info->file, info->root, info); } info->root->free(info->root); info->file->close(info->file); free(info); free(file); }
void flipApple8900Header(Apple8900Header* header) { FLIPENDIAN(header->magic); FLIPENDIANLE(header->unknown1); FLIPENDIANLE(header->sizeOfData); FLIPENDIANLE(header->footerSignatureOffset); FLIPENDIANLE(header->footerCertOffset); FLIPENDIANLE(header->footerCertLen); FLIPENDIANLE(header->unknown2); FLIPENDIANLE(header->epoch); }
void flipPartitionMultiple(Partition* partition, char multiple, char out, unsigned int BlockSize) { int i; int numPartitions; if(out) { numPartitions = partition->pmMapBlkCnt; } else { numPartitions = partition->pmMapBlkCnt; FLIPENDIAN(numPartitions); } for(i = 0; i < numPartitions; i++) { if(out) { if(partition->pmSig != APPLE_PARTITION_MAP_SIGNATURE) { break; } FLIPENDIAN(partition->pmSig); } else { FLIPENDIAN(partition->pmSig); if(partition->pmSig != APPLE_PARTITION_MAP_SIGNATURE) { break; } } FLIPENDIAN(partition->pmMapBlkCnt); FLIPENDIAN(partition->pmPyPartStart); FLIPENDIAN(partition->pmPartBlkCnt); FLIPENDIAN(partition->pmLgDataStart); FLIPENDIAN(partition->pmDataCnt); FLIPENDIAN(partition->pmPartStatus); FLIPENDIAN(partition->pmLgBootStart); FLIPENDIAN(partition->pmBootSize); FLIPENDIAN(partition->pmBootAddr); FLIPENDIAN(partition->pmBootAddr2); FLIPENDIAN(partition->pmBootEntry); FLIPENDIAN(partition->pmBootEntry2); FLIPENDIAN(partition->pmBootCksum); FLIPENDIANLE(partition->bootCode); if(!multiple) { break; } partition = (Partition*)((uint8_t*)partition + BlockSize); } }
void replaceCertificateAbstractFile(AbstractFile* file, AbstractFile* certificate) { uint32_t signatureBE; uint32_t signatureLE; AbstractFile* f; file->seek(file, 0); file->read(file, &signatureBE, sizeof(signatureBE)); signatureLE = signatureBE; FLIPENDIAN(signatureBE); FLIPENDIANLE(signatureLE); file->seek(file, 0); if(signatureLE == IMG3_SIGNATURE) { f = createAbstractFileFromImg3(file); replaceCertificateImg3(f, certificate); f->close(f); } }
AbstractFile *openAbstractFile3(AbstractFile * file, const unsigned int *key, const unsigned int *iv, int layers) { uint32_t signatureBE; uint32_t signatureLE; AbstractFile *cur; if (!file) return NULL; file->seek(file, 0); file->read(file, &signatureBE, sizeof(signatureBE)); signatureLE = signatureBE; FLIPENDIAN(signatureBE); FLIPENDIANLE(signatureLE); file->seek(file, 0); if (signatureBE == SIGNATURE_8900) { cur = createAbstractFileFrom8900(file); } else if (signatureLE == IMG2_SIGNATURE) { cur = createAbstractFileFromImg2(file); } else if (signatureLE == IMG3_SIGNATURE) { AbstractFile2 *img3 = (AbstractFile2 *) createAbstractFileFromImg3(file); if (key && iv) img3->setKey(img3, key, iv); cur = (AbstractFile *) img3; key = NULL; iv = NULL; } else if (signatureBE == COMP_SIGNATURE) { cur = createAbstractFileFromComp(file); key = NULL; iv = NULL; } else { return file; } if (layers < 0 || layers > 0) return openAbstractFile3(cur, key, iv, layers - 1); else return cur; }
static void doPartialSHA1(unsigned char md[SHA_DIGEST_LENGTH], const unsigned char *toHashData, int toHashLength, DataValue *partialDigest) { const unsigned *q = (const unsigned *)partialDigest->value; unsigned v31 = q[0]; // XXX ASSERT(v31 == ecid->size == 64)? unsigned v32 = q[1]; SHA_CTX hashctx; memset(&hashctx, 0, sizeof(hashctx)); hashctx.h0 = q[2]; hashctx.h1 = q[3]; hashctx.h2 = q[4]; hashctx.h3 = q[5]; hashctx.h4 = q[6]; FLIPENDIAN(hashctx.h0); FLIPENDIAN(hashctx.h1); FLIPENDIAN(hashctx.h2); FLIPENDIAN(hashctx.h3); FLIPENDIAN(hashctx.h4); FLIPENDIANLE(v32); hashctx.Nl = 8 * v32 + 64; // XXX could this 64 be actually v31? SHA1_Update(&hashctx, toHashData, toHashLength); SHA1_Final(md, &hashctx); }
void closeImg2(AbstractFile* file) { InfoImg2* info = (InfoImg2*) (file->data); uint32_t cksum; if(info->dirty) { info->file->seek(info->file, sizeof(info->header)); info->file->write(info->file, info->buffer, info->header.dataLen); info->header.dataLenPadded = info->header.dataLen; flipImg2Header(&(info->header)); cksum = crc32(0, (unsigned char *)&(info->header), 0x64); FLIPENDIANLE(cksum); info->header.header_checksum = cksum; info->file->seek(info->file, 0); info->file->write(info->file, &(info->header), sizeof(info->header)); } free(info->buffer); info->file->close(info->file); free(info); free(file); }
void flipAppleImg3KBAGHeader(AppleImg3KBAGHeader* data) { FLIPENDIANLE(data->key_modifier); FLIPENDIANLE(data->key_bits); }
void flipAppleImg3RootExtra(AppleImg3RootExtra* extra) { FLIPENDIANLE(extra->shshOffset); FLIPENDIANLE(extra->name); }
void flipAppleImg3Header(AppleImg3Header* header) { FLIPENDIANLE(header->magic); FLIPENDIANLE(header->size); FLIPENDIANLE(header->dataSize); }
void flipImg2Header(Img2Header* header) { FLIPENDIANLE(header->signature); FLIPENDIANLE(header->imageType); FLIPENDIANLE(header->unknown1); FLIPENDIANLE(header->security_epoch); FLIPENDIANLE(header->flags1); FLIPENDIANLE(header->dataLen); FLIPENDIANLE(header->dataLenPadded); FLIPENDIANLE(header->unknown3); FLIPENDIANLE(header->flags2); FLIPENDIANLE(header->unknown4); FLIPENDIANLE(header->header_checksum); FLIPENDIANLE(header->checksum2); }
void flipRsrcBlockHead(HFSPlusCmpfRsrcBlockHead* data) { FLIPENDIAN(data->dataSize); FLIPENDIANLE(data->numBlocks); }
ZipInfo* PartialZipInit(const char* url) { ZipInfo* info = (ZipInfo*) malloc(sizeof(ZipInfo)); info->url = strdup(url); info->centralDirectoryRecvd = 0; info->centralDirectoryEndRecvd = 0; info->centralDirectoryDesc = NULL; info->hCurl = curl_easy_init(); curl_easy_setopt(info->hCurl, CURLOPT_URL, info->url); curl_easy_setopt(info->hCurl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(info->hCurl, CURLOPT_NOBODY, 1); curl_easy_setopt(info->hCurl, CURLOPT_WRITEFUNCTION, dummyReceive); curl_easy_setopt(info->hCurl, CURLOPT_SSL_VERIFYPEER, 0); if(strncmp(info->url, "file://", 7) == 0) { char path[1024]; strcpy(path, info->url + 7); char* filePath = (char*) curl_easy_unescape(info->hCurl, path, 0, NULL); FILE* f = fopen(filePath, "rb"); if(!f) { curl_free(filePath); curl_easy_cleanup(info->hCurl); free(info->url); free(info); return NULL; } fseek(f, 0, SEEK_END); info->length = ftell(f); fclose(f); curl_free(filePath); } else { curl_easy_perform(info->hCurl); double dFileLength; curl_easy_getinfo(info->hCurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dFileLength); info->length = dFileLength; } char sRange[100]; uint64_t start; if(info->length > (0xffff + sizeof(EndOfCD))) start = info->length - 0xffff - sizeof(EndOfCD); else start = 0; uint64_t end = info->length - 1; sprintf(sRange, "%" PRIu64 "-%" PRIu64, start, end); curl_easy_setopt(info->hCurl, CURLOPT_WRITEFUNCTION, receiveCentralDirectoryEnd); curl_easy_setopt(info->hCurl, CURLOPT_WRITEDATA, info); curl_easy_setopt(info->hCurl, CURLOPT_RANGE, sRange); curl_easy_setopt(info->hCurl, CURLOPT_HTTPGET, 1); curl_easy_perform(info->hCurl); char* cur; for(cur = info->centralDirectoryEnd; cur < (info->centralDirectoryEnd + (end - start - 1)); cur++) { EndOfCD* candidate = (EndOfCD*) cur; uint32_t signature = candidate->signature; FLIPENDIANLE(signature); if(signature == 0x06054b50) { uint16_t lenComment = candidate->lenComment; FLIPENDIANLE(lenComment); if((cur + lenComment + sizeof(EndOfCD)) == (info->centralDirectoryEnd + info->centralDirectoryEndRecvd)) { FLIPENDIANLE(candidate->diskNo); FLIPENDIANLE(candidate->CDDiskNo); FLIPENDIANLE(candidate->CDDiskEntries); FLIPENDIANLE(candidate->CDEntries); FLIPENDIANLE(candidate->CDSize); FLIPENDIANLE(candidate->CDOffset); FLIPENDIANLE(candidate->lenComment); info->centralDirectoryDesc = candidate; break; } } } if(info->centralDirectoryDesc) { info->centralDirectory = malloc(info->centralDirectoryDesc->CDSize); start = info->centralDirectoryDesc->CDOffset; end = start + info->centralDirectoryDesc->CDSize - 1; sprintf(sRange, "%" PRIu64 "-%" PRIu64, start, end); curl_easy_setopt(info->hCurl, CURLOPT_WRITEFUNCTION, receiveCentralDirectory); curl_easy_setopt(info->hCurl, CURLOPT_WRITEDATA, info); curl_easy_setopt(info->hCurl, CURLOPT_RANGE, sRange); curl_easy_setopt(info->hCurl, CURLOPT_HTTPGET, 1); curl_easy_perform(info->hCurl); flipFiles(info); return info; } else { curl_easy_cleanup(info->hCurl); free(info->url); free(info); return NULL; } }
static void flipFiles(ZipInfo* info) { char* cur = info->centralDirectory; unsigned int i; for(i = 0; i < info->centralDirectoryDesc->CDEntries; i++) { CDFile* candidate = (CDFile*) cur; FLIPENDIANLE(candidate->signature); FLIPENDIANLE(candidate->version); FLIPENDIANLE(candidate->versionExtract); // FLIPENDIANLE(candidate->flags); FLIPENDIANLE(candidate->method); FLIPENDIANLE(candidate->modTime); FLIPENDIANLE(candidate->modDate); // FLIPENDIANLE(candidate->crc32); FLIPENDIANLE(candidate->compressedSize); FLIPENDIANLE(candidate->size); FLIPENDIANLE(candidate->lenFileName); FLIPENDIANLE(candidate->lenExtra); FLIPENDIANLE(candidate->lenComment); FLIPENDIANLE(candidate->diskStart); // FLIPENDIANLE(candidate->internalAttr); // FLIPENDIANLE(candidate->externalAttr); FLIPENDIANLE(candidate->offset); cur += sizeof(CDFile) + candidate->lenFileName + candidate->lenExtra + candidate->lenComment; } }
unsigned char* PartialZipGetFile(ZipInfo* info, CDFile* file) { LocalFile localHeader; LocalFile* pLocalHeader = &localHeader; uint64_t start = file->offset; uint64_t end = file->offset + sizeof(LocalFile) - 1; char sRange[100]; sprintf(sRange, "%" PRIu64 "-%" PRIu64, start, end); void* pFileHeader[] = {pLocalHeader, NULL, NULL, NULL}; curl_easy_setopt(info->hCurl, CURLOPT_URL, info->url); curl_easy_setopt(info->hCurl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(info->hCurl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(info->hCurl, CURLOPT_WRITEFUNCTION, receiveData); curl_easy_setopt(info->hCurl, CURLOPT_WRITEDATA, &pFileHeader); curl_easy_setopt(info->hCurl, CURLOPT_RANGE, sRange); curl_easy_setopt(info->hCurl, CURLOPT_HTTPGET, 1); curl_easy_perform(info->hCurl); FLIPENDIANLE(localHeader.signature); FLIPENDIANLE(localHeader.versionExtract); // FLIPENDIANLE(localHeader.flags); FLIPENDIANLE(localHeader.method); FLIPENDIANLE(localHeader.modTime); FLIPENDIANLE(localHeader.modDate); // FLIPENDIANLE(localHeader.crc32); FLIPENDIANLE(localHeader.compressedSize); FLIPENDIANLE(localHeader.size); FLIPENDIANLE(localHeader.lenFileName); FLIPENDIANLE(localHeader.lenExtra); unsigned char* fileData = (unsigned char*) malloc(file->compressedSize); size_t progress = 0; void* pFileData[] = {fileData, info, file, &progress}; start = file->offset + sizeof(LocalFile) + localHeader.lenFileName + localHeader.lenExtra; end = start + file->compressedSize - 1; sprintf(sRange, "%" PRIu64 "-%" PRIu64, start, end); curl_easy_setopt(info->hCurl, CURLOPT_WRITEFUNCTION, receiveData); curl_easy_setopt(info->hCurl, CURLOPT_WRITEDATA, pFileData); curl_easy_setopt(info->hCurl, CURLOPT_RANGE, sRange); curl_easy_setopt(info->hCurl, CURLOPT_HTTPGET, 1); curl_easy_perform(info->hCurl); if(file->method == 8) { unsigned char* uncData = (unsigned char*) malloc(file->size); z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = NULL; inflateInit2(&strm, -MAX_WBITS); strm.avail_in = file->compressedSize; strm.next_in = fileData; strm.avail_out = file->size; strm.next_out = uncData; inflate(&strm, Z_FINISH); inflateEnd(&strm); free(fileData); fileData = uncData; } return fileData; }
int patchKernel(AbstractFile* file) { // codesign const char patch[] = {0x00, 0x00, 0x00, 0x0A, 0x00, 0x40, 0xA0, 0xE3, 0x04, 0x00, 0xA0, 0xE1, 0x90, 0x80, 0xBD, 0xE8}; const char patch_old[] = {0xFF, 0x50, 0xA0, 0xE3, 0x04, 0x00, 0xA0, 0xE1, 0x0A, 0x10, 0xA0, 0xE1}; // 2.0 vm_map max_prot const char patch3[] = {0x99, 0x91, 0x43, 0x2B, 0x91, 0xCD, 0xE7, 0x04, 0x24, 0x1D, 0xB0}; // 3.0 vm_map max_prot const char patch2[] = {0x2E, 0xD1, 0x35, 0x98, 0x80, 0x07, 0x33, 0xD4, 0x6B, 0x08, 0x1E, 0x1C}; // 3.0 illb img3 patch 1 const char patch4[] = {0x98, 0x47, 0x00, 0x28, 0x00, 0xD0, 0xAE, 0xE0, 0x06, 0x98}; // 3.0 illb img3 patch 2 const char patch5[] = {0x05, 0x1E, 0x00, 0xD0, 0xA8, 0xE0, 0x03, 0x9B}; // 3.0 CS enforcement patch const char patch6[] = {0x9C, 0x22, 0x03, 0x59, 0x99, 0x58}; // 3.0 armv7 vm_map_enter max_prot const char n88patch1[] = {0x93, 0xBB, 0x16, 0xF0, 0x02, 0x0F, 0x40, 0xF0, 0x36, 0x80, 0x63, 0x08}; // 3.0 armv7 cs patch const char n88patch2[] = {0x05, 0x4B, 0x98, 0x47, 0x00, 0xB1, 0x00, 0x24, 0x20, 0x46, 0x90, 0xBD}; // 3.0 armv7 cs_enforcement_disable patch const char n88patch3[] = {0xD3, 0xF8, 0x9C, 0x20, 0xDF, 0xF8}; // 3.0 arm7 img3 prod patch const char n88patch4[] = {0x03, 0x94, 0xFF, 0xF7, 0x29, 0xFF, 0xF8, 0xB1}; // 3.0 arm7 img3 ecid patch const char n88patch5[] = {0x0C, 0xCA, 0xFF, 0xF7, 0x10, 0xFF, 0x00, 0x38}; // 3.0 arm7 img3 signature patch const char n88patch6[] = {0x30, 0xE0, 0x4F, 0xF0, 0xFF, 0x30, 0x2D, 0xE0}; // 3.0 arm7 img3 signature patch const char n88patch_test1[] = {0x67, 0x4B, 0x98, 0x47, 0x00, 0x28}; // 3.0 arm7 img3 signature patch const char n88patch_test2[] = {0x04, 0x98, 0xFF, 0xF7, 0xD9, 0xFD, 0x04, 0x46}; // 3.0 arm7 img3 signature patch const char n88patch_test3[] = {0x01, 0x99, 0xFF, 0xF7, 0xBE, 0xFC, 0x00, 0xB3}; size_t length = file->getLength(file); uint8_t* buffer = (uint8_t*)malloc(length + sizeof(patch)); file->seek(file, 0); file->read(file, buffer, length); memset(buffer + length, 0, sizeof(patch)); int retval = 0; int i; for(i = 0; i < length; i++) { uint8_t* candidate = &buffer[i]; if(memcmp(candidate, patch, sizeof(patch)) == 0) { XLOG(3, "kernel patch1 success\n"); fflush(stdout); candidate[4] = 0x01; file->seek(file, i); file->write(file, candidate, sizeof(patch)); retval = TRUE; continue; } if(memcmp(candidate, patch_old, sizeof(patch_old)) == 0) { XLOG(3, "kernel patch_old success\n"); fflush(stdout); candidate[0] = 0x0; file->seek(file, i); file->write(file, candidate, sizeof(patch_old)); retval = TRUE; continue; } if(memcmp(candidate, patch3, sizeof(patch3)) == 0) { XLOG(3, "kernel patch3 success\n"); fflush(stdout); candidate[0] = 0x2B; candidate[1] = 0x99; candidate[2] = 0x00; candidate[3] = 0x00; file->seek(file, i); file->write(file, candidate, sizeof(patch3)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, patch2, sizeof(patch2)) == 0) { XLOG(3, "kernel patch2 success\n"); fflush(stdout); // NOP out the BMI candidate[6] = 0x00; candidate[7] = 0x28; file->seek(file, i); file->write(file, candidate, sizeof(patch2)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, patch4, sizeof(patch4)) == 0) { XLOG(3, "kernel patch4 success\n"); fflush(stdout); candidate[3] = 0x20; file->seek(file, i); file->write(file, candidate, sizeof(patch4)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, patch5, sizeof(patch5)) == 0) { XLOG(3, "kernel patch5 success\n"); fflush(stdout); candidate[0] = 0x00; candidate[1] = 0x25; file->seek(file, i); file->write(file, candidate, sizeof(patch5)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, n88patch1, sizeof(n88patch1)) == 0) { XLOG(3, "kernel armv7 vm_map_enter patch success\n"); fflush(stdout); candidate[6] = 0x8B; candidate[7] = 0x46; candidate[8] = 0x8B; candidate[9] = 0x46; file->seek(file, i); file->write(file, candidate, sizeof(n88patch1)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, n88patch2, sizeof(n88patch2)) == 0) { XLOG(3, "kernel armv7 cs patch success\n"); fflush(stdout); candidate[6] = 0x1; file->seek(file, i); file->write(file, candidate, sizeof(n88patch2)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, n88patch4, sizeof(n88patch4)) == 0) { XLOG(3, "kernel armv7 img3 prod patch success\n"); fflush(stdout); candidate[2] = 0x00; candidate[3] = 0x20; candidate[4] = 0x00; candidate[5] = 0x20; file->seek(file, i); file->write(file, candidate, sizeof(n88patch4)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, n88patch5, sizeof(n88patch5)) == 0) { XLOG(3, "kernel armv7 img3 ecid patch success\n"); fflush(stdout); candidate[2] = 0x00; candidate[3] = 0x20; candidate[4] = 0x00; candidate[5] = 0x20; file->seek(file, i); file->write(file, candidate, sizeof(n88patch5)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, n88patch6, sizeof(n88patch6)) == 0) { XLOG(3, "kernel armv7 img3 signature patch success\n"); fflush(stdout); candidate[2] = 0x00; candidate[3] = 0x20; candidate[4] = 0x00; candidate[5] = 0x20; file->seek(file, i); file->write(file, candidate, sizeof(n88patch6)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, n88patch_test1, sizeof(n88patch_test1)) == 0) { XLOG(3, "kernel armv7 img3 ParseFirmwareFooter patch success\n"); fflush(stdout); candidate[2] = 0x00; candidate[3] = 0x20; file->seek(file, i); file->write(file, candidate, sizeof(n88patch_test1)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, n88patch_test2, sizeof(n88patch_test2)) == 0) { XLOG(3, "kernel armv7 img3 CheckMetaTags patch success\n"); fflush(stdout); candidate[2] = 0x00; candidate[3] = 0x20; candidate[4] = 0x00; candidate[5] = 0x20; file->seek(file, i); file->write(file, candidate, sizeof(n88patch_test2)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, n88patch_test3, sizeof(n88patch_test3)) == 0) { XLOG(3, "kernel armv7 img3 encrypt SHSH with 89A patch success\n"); fflush(stdout); candidate[2] = 0x01; candidate[3] = 0x20; candidate[4] = 0x01; candidate[5] = 0x20; file->seek(file, i); file->write(file, candidate, sizeof(n88patch_test3)); retval = TRUE; continue; } if(Do30Patches && memcmp(candidate, patch6, sizeof(patch6)) == 0) { if(candidate[7] != 0x4B) continue; uint32_t cs_enforcement_disable = *((uint32_t*)(((intptr_t)(&candidate[6] + 0x4) & ~0x3) + (0x4 * candidate[6]))); FLIPENDIANLE(cs_enforcement_disable); uint32_t offset = cs_enforcement_disable - 0xC0008000; XLOG(3, "kernel cs_enforcement_disable at: 0x%X, 0x%X\n", cs_enforcement_disable, offset); fflush(stdout); uint32_t value = 1; FLIPENDIANLE(value); *((uint32_t*)(buffer + offset)) = value; file->seek(file, offset); file->write(file, &value, sizeof(value)); continue; } if(Do30Patches && memcmp(candidate, n88patch3, sizeof(n88patch3)) == 0) { uint32_t cs_enforcement_disable = *((uint32_t*)(((intptr_t)(&candidate[4] + 0x4) & ~0x3) + (((candidate[7] & 0xF) << 8) + candidate[6]))); FLIPENDIANLE(cs_enforcement_disable); uint32_t offset = cs_enforcement_disable - 0xC0008000; XLOG(3, "kernel cs_enforcement_disable at: 0x%X, 0x%X\n", cs_enforcement_disable, offset); fflush(stdout); uint32_t value = 1; FLIPENDIANLE(value); *((uint32_t*)(buffer + offset)) = value; file->seek(file, offset); file->write(file, &value, sizeof(value)); continue; } } free(buffer); return retval; }
void flipRsrcBlock(HFSPlusCmpfRsrcBlock* data) { FLIPENDIANLE(data->offset); FLIPENDIANLE(data->size); }
void flipHFSPlusDecmpfs(HFSPlusDecmpfs* compressData) { FLIPENDIANLE(compressData->magic); FLIPENDIANLE(compressData->flags); FLIPENDIANLE(compressData->size); }
void close8900(AbstractFile * file) { unsigned char ivec[16]; SHA_CTX sha_ctx; unsigned char md[20]; unsigned char exploit_data[0x54] = { 0 }; /*int align; */ size_t origSize; uint32_t cksum; Info8900 *info = (Info8900 *) (file->data); if (info->dirty) { if (info->header.format == 3) { /* we need to block-align our data, or AES will break */ origSize = info->header.sizeOfData; /* gotta break abstraction here, because Apple is mean */ if (((Img2Header *) info->buffer)->signature == IMG2_SIGNATURE) { ((Img2Header *) info->buffer)->dataLenPadded = ((Img2Header *) info-> buffer)->dataLenPadded % 16 == 0 ? ((Img2Header *) info->buffer)-> dataLenPadded : ((((Img2Header *) info-> buffer)->dataLenPadded / 16) + 1) * 16; info->header.sizeOfData = ((Img2Header *) info-> buffer)->dataLenPadded + sizeof(Img2Header); cksum = crc32(0, (unsigned char *)info->buffer, 0x64); FLIPENDIANLE(cksum); ((Img2Header *) info->buffer)->header_checksum = cksum; } info->header.sizeOfData = (info->header.sizeOfData) % 16 == 0 ? info-> header.sizeOfData : ((info->header.sizeOfData / 16) + 1) * 16; if (info->header.sizeOfData != origSize) { info->buffer = realloc(info->buffer, info->header.sizeOfData); memset((void *)((uint8_t *) info->buffer + origSize), 0, info->header.sizeOfData - origSize); } } info->header.footerSignatureOffset = info->header.sizeOfData; info->header.footerCertOffset = info->header.footerSignatureOffset + 0x80; if (info->header.format == 3) { memset(ivec, 0, 16); AES_cbc_encrypt(info->buffer, info->buffer, info->header.sizeOfData, &(info->encryptKey), ivec, AES_ENCRYPT); } info->file->seek(info->file, sizeof(info->header)); info->file->write(info->file, info->buffer, info->header.sizeOfData); info->file->seek(info->file, sizeof(info->header) + info->header.footerSignatureOffset); info->file->write(info->file, info->footerSignature, 0x80); info->file->seek(info->file, sizeof(info->header) + info->header.footerCertOffset); if (info->exploit) { info->footerCertificate[0x8be] = 0x9F; info->footerCertificate[0xb08] = 0x55; } info->file->write(info->file, info->footerCertificate, info->header.footerCertLen); if (info->exploit) { info->header.footerCertLen = 0xc5e; exploit_data[0x30] = 0x01; exploit_data[0x50] = 0xEC; exploit_data[0x51] = 0x57; exploit_data[0x53] = 0x20; info->file->write(info->file, exploit_data, sizeof(exploit_data)); } flipApple8900Header(&(info->header)); SHA1_Init(&sha_ctx); SHA1_Update(&sha_ctx, &(info->header), 0x40); SHA1_Final(md, &sha_ctx); memset(ivec, 0, 16); AES_cbc_encrypt(md, (unsigned char *)&(info-> header.headerSignature), 0x10, &(info->encryptKey), ivec, AES_ENCRYPT); info->file->seek(info->file, 0); info->file->write(info->file, &(info->header), sizeof(info->header)); } free(info->footerCertificate); free(info->buffer); info->file->close(info->file); free(info); free(file); }
static const char * checkBlob(X509 *x0, DataValue *blob, DataValue *partialDigest, uint64_t *savecid) { int rv; X509 *x1, *x2; uint64_t thisecid; unsigned partial0; int len = blob->len; const unsigned char *ptr = blob->value; AppleImg3Header *cert = NULL; AppleImg3Header *ecid = NULL; AppleImg3Header *shsh = NULL; while (len > 0) { AppleImg3Header *hdr; if (len < sizeof(AppleImg3Header)) { return "truncated"; } hdr = (AppleImg3Header *)ptr; flipAppleImg3Header(hdr); // XXX we need to flip ECID back before hashing switch (hdr->magic) { case IMG3_ECID_MAGIC: ecid = (AppleImg3Header *)ptr; break; case IMG3_SHSH_MAGIC: shsh = (AppleImg3Header *)ptr; break; case IMG3_CERT_MAGIC: cert = (AppleImg3Header *)ptr; break; default: return "unknown"; } len -= hdr->size; ptr += hdr->size; } if (!ecid || !shsh || !cert) { return "incomplete"; } partial0 = *(unsigned *)partialDigest->value; FLIPENDIANLE(partial0); if (partial0 != 0x40 || partial0 != ecid->size) { return "internal"; // XXX see doPartialSHA1() } thisecid = getECID(ecid + 1); if (*savecid == 0) { *savecid = thisecid; } if (*savecid != thisecid) { return "mismatch"; } rv = extract2Certs((unsigned char *)(cert + 1), cert->dataSize, &x1, &x2); if (rv) { return "asn1"; } rv = cryptoMagic(x0, x1, x2, (unsigned char *)ecid, ecid->size, (unsigned char *)(shsh + 1), shsh->dataSize, partialDigest); X509_free(x2); X509_free(x1); return rv ? "crypto" : NULL; }