All pastes #977711 Raw Edit

fgsch

public c v1 · immutable
#977711 ·published 2008-04-09 00:48 UTC
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]));}