static VALUE decode(VALUE self, VALUE str) { u_int8_t *dst = NULL; u_int32_t len = decompress_lzss(&dst, RSTRING_PTR(str), RSTRING_LEN(str)); VALUE ret = rb_str_new(dst, len); free(dst); return ret; }
AbstractFile* createAbstractFileFromComp(AbstractFile* file) { InfoComp* info; AbstractFile* toReturn; uint8_t *compressed; if(!file) { return NULL; } info = (InfoComp*) malloc(sizeof(InfoComp)); info->file = file; file->seek(file, 0); file->read(file, &(info->header), sizeof(info->header)); flipCompHeader(&(info->header)); if(info->header.signature != COMP_SIGNATURE) { free(info); return NULL; } if(info->header.compression_type != LZSS_SIGNATURE) { free(info); return NULL; } info->buffer = malloc(info->header.length_uncompressed); compressed = malloc(info->header.length_compressed); file->read(file, compressed, info->header.length_compressed); uint32_t real_uncompressed = decompress_lzss(info->buffer, compressed, info->header.length_compressed); real_uncompressed = info->header.length_uncompressed; if(real_uncompressed != info->header.length_uncompressed) { XLOG(5, "mismatch: %d %d %d %x %x\n", info->header.length_compressed, real_uncompressed, info->header.length_uncompressed, compressed[info->header.length_compressed - 2], compressed[info->header.length_compressed - 1]); free(compressed); free(info); return NULL; } XLOG(5, "match: %d %d %d %x %x\n", info->header.length_compressed, real_uncompressed, info->header.length_uncompressed, compressed[info->header.length_compressed - 2], compressed[info->header.length_compressed - 1]); free(compressed); info->dirty = FALSE; info->offset = 0; toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); toReturn->data = info; toReturn->read = readComp; toReturn->write = writeComp; toReturn->seek = seekComp; toReturn->tell = tellComp; toReturn->getLength = getLengthComp; toReturn->close = closeComp; toReturn->type = AbstractFileTypeLZSS; return toReturn; }
long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize) { long ret; compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary; u_int32_t uncompressed_size, size; void *buffer; #if 0 printf("kernel header:\n"); printf("signature: 0x%x\n", kernel_header->signature); printf("compress_type: 0x%x\n", kernel_header->compress_type); printf("adler32: 0x%x\n", kernel_header->adler32); printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size); printf("compressed_size: 0x%x\n", kernel_header->compressed_size); getc(); #endif if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) { if (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) { error("kernel compression is bad\n"); return -1; } #if NOTDEF if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name)) return -1; if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path)) return -1; #endif uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size); binary = buffer = malloc(uncompressed_size); size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size)); if (uncompressed_size != size) { error("size mismatch from lzss: %x\n", size); return -1; } if (OSSwapBigToHostInt32(kernel_header->adler32) != Alder32(binary, uncompressed_size)) { printf("adler mismatch\n"); return -1; } } ThinFatFile(&binary, 0); ret = DecodeMachO(binary, rentry, raddr, rsize); return ret; }
int decompress_kernel(void* compressedKernel, void* decompressedKernel) { compressed_kernel_header *kernel_header = (compressed_kernel_header*)compressedKernel; u_int32_t uncompressed_size, size; printf("decompress_kernel: compressed kernel at %p\n", compressedKernel); if(kernel_header->signature != __builtin_bswap32('comp')) { printf("decompress_kernel: bad file magic\n"); return -1; } if (kernel_header->signature == __builtin_bswap32('comp')) { if (kernel_header->compress_type != __builtin_bswap32('lzss')) { printf("decompress_kernel: kernel compression is bad\n"); return -1; } } assert(decompressedKernel != NULL); uncompressed_size = __builtin_bswap32(kernel_header->uncompressed_size); size = decompress_lzss((u_int8_t *)decompressedKernel, &kernel_header->data[0], __builtin_bswap32(kernel_header->compressed_size)); if (uncompressed_size != size) { printf("decompress_kernel: size mismatch from lzss: %x\n", size); return -1; } if (__builtin_bswap32(kernel_header->adler32) != Adler32(decompressedKernel, uncompressed_size)) { printf("decompress_kernel: adler mismatch\n"); return -1; } printf("decompress_kernel: kernelcache decompressed to %p\n", decompressedKernel); gKernelSize = size; gKernelImage = (void*)decompressedKernel; return 0; }
int main(int argc, char **argv) { int rv; const char *what; const char *filename; const char *outname; TheImg4 *img4; unsigned type; unsigned written; unsigned char ivkey[16 + 32]; unsigned char *iv = NULL, *key = NULL; unsigned char *output = NULL; unsigned outlen = 0; int outdup = 0; DERItem item; unsigned char *data; size_t size; if (argc < 4) { fprintf(stderr, "usage: %s {-image|-extra|-keybag|-ticket} input output [ivkey]\n", argv[0]); return 1; } what = argv[1]; filename = argv[2]; outname = argv[3]; if (argc > 4) { rv = str2hex(sizeof(ivkey), ivkey, argv[4]); if (rv == sizeof(ivkey)) { iv = ivkey; key = ivkey + 16; } } data = read_file(filename, 0, &size); if (data == NULL) { fprintf(stderr, "[e] cannot read '%s'\n", filename); return -1; } img4 = parse(data, size); if (!img4) { fprintf(stderr, "[e] cannot parse '%s'\n", filename); free(data); return -1; } rv = Img4DecodeGetPayloadType(img4, &type); if (rv) { fprintf(stderr, "[e] cannot identify '%s'\n", filename); goto err; } printf("%c%c%c%c\n", FOURCC(type)); if (!strncmp(what, "-i", 2) || !strncmp(what, "-e", 2)) { int decompress; rv = Img4DecodeGetPayload(img4, &item); if (rv) { fprintf(stderr, "[e] cannot extract payload from '%s'\n", filename); goto err; } output = item.data; outlen = item.length; if (iv && key) { if (outlen & 15) { unsigned usize = (outlen + 15) & ~15; unsigned char *tmp = calloc(1, usize); if (!tmp) { fprintf(stderr, "[e] out of memory %u\n", usize); goto err; } memcpy(tmp, output, outlen); OUTSET(tmp); } rv = Img4DecodeGetPayloadKeybag(img4, &item); if (rv || item.length == 0) { fprintf(stderr, "[w] image '%s' has no keybag\n", filename); } #ifdef USE_CORECRYPTO cccbc_one_shot(ccaes_cbc_decrypt_mode(), 32, key, iv, (outlen + 15) / 16, output, output); #else AES_KEY decryptKey; AES_set_decrypt_key(key, 256, &decryptKey); AES_cbc_encrypt(output, output, (outlen + 15) & ~15, &decryptKey, iv, AES_DECRYPT); #endif } #ifdef iOS10 if (img4->payload.compression.data && img4->payload.compression.length) { DERItem tmp[2]; uint32_t deco = 0; uint64_t usize = 0; if (DERParseSequenceContent(&img4->payload.compression, 2, DERImg4PayloadItemSpecs10c, tmp, 0) || DERParseInteger(&tmp[0], &deco) || DERParseInteger64(&tmp[1], &usize)) { fprintf(stderr, "[e] cannot get decompression info\n"); goto err; } if (deco == 1 && what[1] == 'i') { size_t asize = lzfse_decode_scratch_size(); unsigned char *dec, *aux = malloc(asize); if (!aux) { fprintf(stderr, "[e] out of memory %zu\n", asize); goto err; } dec = malloc(usize + 1); if (!dec) { fprintf(stderr, "[e] out of memory %llu\n", usize + 1); free(aux); goto err; } outlen = lzfse_decode_buffer(dec, usize + 1, output, outlen, aux); free(aux); if (outlen != usize) { fprintf(stderr, "[e] decompression error\n"); free(dec); goto err; } OUTSET(dec); } } #endif decompress = (DWORD_BE(output, 0) == 'comp' && DWORD_BE(output, 4) == 'lzss'); if (decompress && what[1] == 'i') { uint32_t csize = DWORD_BE(output, 16); uint32_t usize = DWORD_BE(output, 12); uint32_t adler = DWORD_BE(output, 8); unsigned char *dec = malloc(usize); if (outlen > 0x180 + csize) { fprintf(stderr, "[i] extra 0x%x bytes after compressed chunk\n", outlen - 0x180 - csize); } if (!dec) { fprintf(stderr, "[e] out of memory %u\n", usize); goto err; } outlen = decompress_lzss(dec, output + 0x180, csize); if (adler != lzadler32(dec, outlen)) { fprintf(stderr, "[w] adler32 mismatch\n"); } OUTSET(dec); } else if (decompress) { uint32_t csize = DWORD_BE(output, 16); uint32_t usize = outlen - 0x180 - csize; if (outlen > 0x180 + csize) { unsigned char *dec = malloc(usize); if (!dec) { fprintf(stderr, "[e] out of memory %u\n", usize); goto err; } memcpy(dec, output + 0x180 + csize, usize); outlen = usize; OUTSET(dec); } else { OUTSET(NULL); } } else if (what[1] == 'e') { OUTSET(NULL); } if (!output) { fprintf(stderr, "[e] nothing to do\n"); goto err; } } if (!strncmp(what, "-k", 2)) { rv = Img4DecodeGetPayloadKeybag(img4, &item); if (rv == 0 && item.length) { output = item.data; outlen = item.length; } else { fprintf(stderr, "[e] image '%s' has no keybag\n", filename); goto err; } } if (!strncmp(what, "-t", 2)) { bool exists = false; rv = Img4DecodeManifestExists(img4, &exists); if (rv == 0 && exists) { output = img4->manifestRaw.data; outlen = img4->manifestRaw.length; } else { fprintf(stderr, "[e] image '%s' has no ticket\n", filename); goto err; } } written = write_file(outname, output, outlen); if (written != outlen) { fprintf(stderr, "[e] cannot write '%s'\n", outname); goto err; } rv = 0; out: if (outdup) { free(output); } free(img4); free(data); return rv; err: rv = -1; goto out; }
long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize) { long ret = 0; compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary; u_int32_t uncompressed_size = 0, size = 0, adler32 = 0; void *buffer = NULL; unsigned long len = 0; /*#if 0 printf("kernel header:\n"); printf("signature: 0x%x\n", kernel_header->signature); printf("compress_type: 0x%x\n", kernel_header->compress_type); printf("adler32: 0x%x\n", kernel_header->adler32); printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size); printf("compressed_size: 0x%x\n", kernel_header->compressed_size); getchar(); #endif*/ if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) { DBG("Decompressing Kernel: "); if ((kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) && (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzvn'))) { error("ERROR: kernel compression is bad!\n"); return -1; } #if NOTDEF if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name)) { return -1; } if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path)) { return -1; } #endif uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size); binary = buffer = malloc(uncompressed_size); // MinusZwei size = 0; switch (kernel_header->compress_type) { case OSSwapBigToHostConstInt32('lzvn'): size = decompress_lzvn( binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size)); break; case OSSwapBigToHostConstInt32('lzss'): size = decompress_lzss( (u_int8_t *)binary, uncompressed_size, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size)); break; default: break; } // MinusZwei if (uncompressed_size != size) { if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzvn')) { error("ERROR: size mismatch from lzvn (found: %x, expected: %x).\n", size, uncompressed_size); } if ( kernel_header->compress_type == OSSwapBigToHostConstInt32('lzss')) { error("ERROR: size mismatch from lzss (found: %x, expected: %x).\n", size, uncompressed_size); } return -1; } adler32 = Adler32(binary, uncompressed_size); if (OSSwapBigToHostInt32(kernel_header->adler32) != adler32) { error("ERROR: adler mismatch (found: %x, expected: %x).\n", adler32, OSSwapBigToHostInt32(kernel_header->adler32)); return -1; } DBG("OK.\n"); } ret = ThinFatFile(&binary, &len); if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64) { archCpuType=CPU_TYPE_I386; ret = ThinFatFile(&binary, &len); } // Bungo: no range checking, sorry size = 0; while (memcmp((uint8_t *)binary + size, (uint8_t *)gDarwinBuildVerStr, 21)) { size++; } gDarwinBuildVerStr = (char *)binary + size; // Notify modules that the kernel has been decompressed, thinned and is about to be decoded execute_hook("DecodeKernel", (void*)binary, NULL, NULL, NULL); ret = DecodeMachO(binary, rentry, raddr, rsize); if (ret < 0 && archCpuType == CPU_TYPE_X86_64) { archCpuType = CPU_TYPE_I386; ret = DecodeMachO(binary, rentry, raddr, rsize); } return ret; }
long DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize) { long ret; compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary; u_int32_t uncompressed_size, size; void *buffer; unsigned long len; #if 0 printf("kernel header:\n"); printf("signature: 0x%x\n", kernel_header->signature); printf("compress_type: 0x%x\n", kernel_header->compress_type); printf("adler32: 0x%x\n", kernel_header->adler32); printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size); printf("compressed_size: 0x%x\n", kernel_header->compressed_size); getchar(); #endif if (kernel_header->signature == OSSwapBigToHostConstInt32('comp')) { if (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss')) { error("kernel compression is bad\n"); return -1; } #if NOTDEF if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name)) return -1; if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path)) return -1; #endif uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size); binary = buffer = malloc(uncompressed_size); size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0], OSSwapBigToHostInt32(kernel_header->compressed_size)); if (uncompressed_size != size) { error("size mismatch from lzss: %x\n", size); return -1; } if (OSSwapBigToHostInt32(kernel_header->adler32) != Adler32(binary, uncompressed_size)) { printf("adler mismatch\n"); return -1; } } ret = ThinFatFile(&binary, &len); if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64) { archCpuType=CPU_TYPE_I386; ret = ThinFatFile(&binary, &len); } // Notify modules that the kernel has been decompressed, thinned and is about to be decoded execute_hook("DecodeKernel", (void*)binary, NULL, NULL, NULL); ret = DecodeMachO(binary, rentry, raddr, rsize); if (ret<0 && archCpuType==CPU_TYPE_X86_64) { archCpuType=CPU_TYPE_I386; ret = DecodeMachO(binary, rentry, raddr, rsize); } return ret; }
AbstractFile* createAbstractFileFromIBootIM(AbstractFile* file) { InfoIBootIM* info; AbstractFile* toReturn; uint8_t *compressed; if(!file) { return NULL; } info = (InfoIBootIM*) malloc(sizeof(InfoIBootIM)); info->file = file; file->seek(file, 0); file->read(file, &(info->header), sizeof(info->header)); flipIBootIMHeader(&(info->header)); if(strcmp(info->header.signature, IBOOTIM_SIGNATURE) != 0) { free(info); XLOG(1, "createAbstractFileFromIBootIM: signature does not match\n"); return NULL; } info->compLength = file->getLength(file) - sizeof(info->header); if(info->header.compression_type != IBOOTIM_LZSS_TYPE) { //free(info); XLOG(1, "createAbstractFileFromIBootIM: (warning) unsupported compression type: %x\n", info->header.compression_type); //return NULL; } int depth = 0; if(info->header.format == IBOOTIM_ARGB) { info->length = 4 * info->header.width * info->header.height; depth = 4; } else if(info->header.format == IBOOTIM_GREY) { info->length = 2 * info->header.width * info->header.height; depth = 2; } else { XLOG(1, "createAbstractFileFromIBootIM: unsupported color type: %x\n", info->header.format); free(info); return NULL; } info->buffer = malloc(info->length); compressed = malloc(info->compLength); file->read(file, compressed, info->compLength); int length = decompress_lzss(info->buffer, compressed, info->compLength); if(length > info->length) { XLOG(1, "createAbstractFileFromIBootIM: decompression error\n"); free(compressed); free(info); return NULL; } else if(length < info->length) { XLOG(1, "createAbstractFileFromIBootIM: (warning) uncompressed data shorter than expected: %d\n", length); info->length = length; } free(compressed); info->dirty = FALSE; info->offset = 0; toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); toReturn->data = info; toReturn->read = readIBootIM; toReturn->write = writeIBootIM; toReturn->seek = seekIBootIM; toReturn->tell = tellIBootIM; toReturn->getLength = getLengthIBootIM; toReturn->close = closeIBootIM; toReturn->type = AbstractFileTypeIBootIM; return toReturn; }