rendered paste body/* $Id$ *//* * "THE BEER-WARE LICENSE" (Revision 42): * <fgsch@lodoss.net> wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. *//* * The 8900 decrypter comes from * http://code.google.com/p/iphone-elite/wiki/8900decryptercode: * * This code was extended and modified by PmgR from the original * 8900decrypter.c file by aljen. * * lzss routine comes from: * * 4/6/1989 Haruhiko Okumura * Use, distribute, and modify this program freely. * Please send me your improved versions. * PC-VAN SCIENCE * NIFTY-Serve PAF01022 * CompuServe 74050,1022 * * Based on info from http://wikee.iphwn.org/s5l8900:8900_format * and http://iphonedevwiki.scribblewiki.com/Img2. */#include <openssl/aes.h>#include <fcntl.h>#include <png.h>#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>typedef struct { uint8_t magic[4]; uint8_t version[3]; uint8_t format; uint32_t unknown1; uint32_t sizeOfData; uint32_t footerSignatureOffset; uint32_t footerCertOffset; uint32_t footerCertLen; u_char salt[0x20]; uint16_t unknown2; uint16_t epoch; u_char headerSignature[0x10]; u_char padding[0x7B0];} Apple8900Header;typedef struct { uint8_t magic[8]; uint32_t unknown; uint8_t compression[4]; uint8_t color_type[4]; uint16_t width; uint16_t height; uint8_t padding[0x28];} AppleiBootImgHeader;#define N 4096#define F 18#define THRESHOLD 2intdecompress_lzss(uint8_t *dst, uint8_t *src, uint32_t srclen){ uint8_t text_buf[N + F - 1]; uint8_t *dststart = dst; uint8_t *srcend = src + srclen; int i, j, k, r, c; unsigned int flags; dst = dststart; srcend = src + srclen; for (i = 0; i < N - F; i++) text_buf[i] = ' '; r = N - F; flags = 0; for (;;) { if (((flags >>= 1) & 0x100) == 0) { if (src < srcend) c = *src++; else break; flags = c | 0xFF00; } if (flags & 1) { if (src < srcend) c = *src++; else break; *dst++ = c; text_buf[r++] = c; r &= (N - 1); } else { if (src < srcend) i = *src++; else break; if (src < srcend) j = *src++; else break; i |= ((j & 0xF0) << 4); j = (j & 0x0F) + THRESHOLD; for (k = 0; k <= j; k++) { c = text_buf[(i + k) & (N - 1)]; *dst++ = c; text_buf[r++] = c; r &= (N - 1); } } } return (dst - dststart);}intwrite_png(const char *outfile, uint8_t *data, int color_type, uint32_t width, uint32_t height){ FILE *fp; png_structp pp; png_infop ip; int i, error; pp = NULL; ip = NULL; error = 1; if (!(fp = fopen(outfile, "w"))) goto out; if (!(pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL))) goto out; if (!(ip = png_create_info_struct(pp))) goto out; png_init_io(pp, fp); png_set_IHDR(pp, ip, width, height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_bgr(pp); png_set_invert_alpha(pp); png_write_info(pp, ip); for (i = 0; i < height; i++) png_write_row(pp, (png_bytep)&data[i * width * 4]); png_write_end(pp, ip); error = 0; out: if (pp) { if (ip) png_destroy_write_struct(&pp, &ip); else png_destroy_write_struct(&pp, NULL); } if (fp) fclose(fp); if (error) (void)unlink(outfile); return (error);}intextract(const char *infile, const char *outfile){ Apple8900Header *hdr; AppleiBootImgHeader *ihdr; AES_KEY aes_decrypt_key; uint8_t ramdiskKey[] = "188458A6D15034DFE386F23B61D43774"; uint8_t iv[AES_BLOCK_SIZE]; uint8_t *in, *out; uint8_t aes_key[16]; int color_type, encrypted; int error, fd; int i; in = out = NULL; error = 1; if ((fd = open(infile, O_RDONLY)) < 0) return (1); if (!(hdr = malloc(sizeof(*hdr)))) goto out; if (read(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) goto out; if (memcmp(&hdr->magic, "8900", 4) || memcmp(&hdr->version, "1.0", 3)) goto out; if (hdr->format == 3) encrypted = 1; else if (hdr->format == 4) encrypted = 0; else goto out; if (lseek(fd, sizeof(*hdr), SEEK_SET) < 0) goto out; if (!(in = malloc(1024 * 1000))) goto out; if (!(out = malloc(hdr->sizeOfData))) goto out; for (i = 0; i < sizeof(aes_key); i++) sscanf(&ramdiskKey[i * 2], "%02hhx", &aes_key[i]); AES_set_decrypt_key(aes_key, 128, &aes_decrypt_key); memset(iv, 0, AES_BLOCK_SIZE); for (i = 0; i < hdr->sizeOfData; i += AES_BLOCK_SIZE) { if (read(fd, in, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) goto out; if (encrypted) { AES_cbc_encrypt(in, &out[i], AES_BLOCK_SIZE, &aes_decrypt_key, iv, AES_DECRYPT); } else memcpy(&out[i], in, AES_BLOCK_SIZE); } ihdr = (AppleiBootImgHeader *)(out + 0x400); if (memcmp(&ihdr->magic, "iBootIm\0", 8) || memcmp(&ihdr->compression, "sszl", 4)) goto out; if (!memcmp(&ihdr->color_type, "bgra", 4)) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else if (!memcmp(&ihdr->color_type, "yerg", 4)) color_type = PNG_COLOR_TYPE_GRAY; else goto out; (void)decompress_lzss(in, ((uint8_t *)ihdr) + sizeof(*ihdr), hdr->sizeOfData - 0x400 - sizeof(*ihdr)); error = write_png(outfile, in, color_type, ihdr->width, ihdr->height); out: if (in) free(in); if (out) free(out); if (hdr) free(hdr); if (fd) close(fd); return (error);}voidusage(void){ fprintf(stderr, "usage: apfel2png infile.img2 outfile.png\n"); exit(1);}intmain(int argc, char **argv){ if (argc < 3) usage(); exit(extract(argv[1], argv[2]));}