rendered paste body#include<stdio.h>#include<stdlib.h>#include<getopt.h>#include<stdarg.h>#include<errno.h>#include <unistd.h>#include<sys/types.h>#include<sys/stat.h>//Thanks to Solar Designer for the CRC routineschar *LOCKDOWND_PATH="/usr/libexec/lockdownd";typedef struct a_patch_ { unsigned long offset; unsigned char orig_byte; unsigned char new_byte;} a_patch;typedef struct os_fixes_ { char *file_id; char major; char minor; char sub; unsigned long orig_crc; unsigned long new_crc; a_patch *patches;} os_fixes;a_patch lockdownd_120_5a225c[] ={ {0x0000C40F, 0x0A, 0xEA}, {0x0000667B, 0x0A, 0xEA}, {0x00007C1B, 0x1A, 0xEA}, {0x00008860, 0xA0, 0x1C}, {0x00008861, 0x28, 0x29}, {0x00008864, 0x01, 0x00}, {0x000088C4, 0x3C, 0xB8}, {0x0000893C, 0xC4, 0x40}, {0x0000893D, 0x27, 0x28}, {0x00008A30, 0xFC, 0x4C}, {0x00008A31, 0x26, 0x27}, {0x00008A88, 0xB4, 0xF4}, {0x00008B0C, 0x30, 0x70}, {0x00008C2C, 0xD4, 0x50}, {0x00008C2D, 0x34, 0x35}, {0x00008CA8, 0x94, 0xD4}, {0x00008D04, 0x01, 0x00}, {0x00008D1B, 0xDA, 0xEA}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_114_patches[] ={ {0x000083AF, 0x0A, 0xEA}, {0x0000AFA3, 0x0A, 0xEA}, {0x0000C4CF, 0x1A, 0xEA}, {0x0000CDB4, 0x80, 0x04}, {0x0000CDB5, 0x28, 0x29}, {0x0000CDC0, 0x01, 0x00}, {0x0000CE08, 0x2C, 0xB0}, {0x0000CE58, 0xDC, 0x60}, {0x0000CE59, 0x27, 0x28}, {0x0000CF24, 0x3C, 0x94}, {0x0000CF7C, 0xF4, 0x3C}, {0x0000CF7D, 0x26, 0x27}, {0x0000D000, 0x70, 0xB8}, {0x0000D1A8, 0x8C, 0x10}, {0x0000D1A9, 0x24, 0x25}, {0x0000D224, 0x4C, 0x94}, {0x0000D274, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_113_patches[] ={ {0x000083AF, 0x0A, 0xEA}, {0x0000AFA3, 0x0A, 0xEA}, {0x0000C4CF, 0x1A, 0xEA}, {0x0000CDB4, 0x80, 0x04}, {0x0000CDB5, 0x28, 0x29}, {0x0000CDC0, 0x01, 0x00}, {0x0000CE08, 0x2C, 0xB0}, {0x0000CE58, 0xDC, 0x60}, {0x0000CE59, 0x27, 0x28}, {0x0000CF24, 0x3C, 0x94}, {0x0000CF7C, 0xF4, 0x3C}, {0x0000CF7D, 0x26, 0x27}, {0x0000D000, 0x70, 0xB8}, {0x0000D1A8, 0x8C, 0x10}, {0x0000D1A9, 0x24, 0x25}, {0x0000D224, 0x4C, 0x94}, {0x0000D274, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_112_patches[] ={ {0x00004B3B, 0x1A, 0xEA}, {0x000079FC, 0xD7, 0x00}, {0x000079FD, 0xFF, 0x00}, {0x000079FE, 0xFF, 0xA0}, {0x000079FF, 0x1A, 0xE1}, {0x00007E0B, 0x0A, 0xEA}, {0x0000AC73, 0x0A, 0xEA}, {0x0000BC40, 0x01, 0x00}, {0x0000C5CC, 0x01, 0x00}, {0x0000C5D4, 0x88, 0xEC}, {0x0000C614, 0x48, 0xAC}, {0x0000C640, 0x1C, 0x80}, {0x0000C6F0, 0x90, 0xD0}, {0x0000C74C, 0x44, 0x74}, {0x0000C7DC, 0xB4, 0xE4}, {0x0000C8AC, 0xB0, 0x14}, {0x0000C8AD, 0x33, 0x34}, {0x0000C904, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_111_patches[] ={ {0x0000482F, 0x1A, 0xEA}, {0x0000AF5C, 0x01, 0x00}, {0x0000B814, 0x24, 0x54}, {0x0000B818, 0x01, 0x00}, {0x0000B838, 0x00, 0x30}, {0x0000B858, 0xE0, 0x10}, {0x0000B859, 0x14, 0x15}, {0x0000B884, 0xB4, 0xE4}, {0x0000B958, 0x00, 0x10}, {0x0000B970, 0xEC, 0xF8}, {0x0000B9E0, 0x58, 0x88}, {0x0000BA58, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_102_patches[] ={ {0x00009184, 0x01, 0x00}, {0x000094F0, 0x01, 0x00}, {0x000094F4, 0x3C, 0x68}, {0x000095C4, 0x84, 0x98}, {0x00009604, 0x01, 0x00}, {0x00009624, 0x2C, 0x38}, {0x0000962C, 0x28, 0x30}, {0x000096A4, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_101_patches[] ={ {0x00009158, 0x01, 0x00}, {0x000094C4, 0x01, 0x00}, {0x000094C8, 0x3C, 0x68}, {0x00009598, 0x84, 0x98}, {0x000095D8, 0x01, 0x00}, {0x000095F8, 0x2C, 0x38}, {0x00009600, 0x28, 0x30}, {0x00009678, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_100_patches[] ={ {0x00008CF8, 0x01, 0x00}, {0x000090A4, 0x01, 0x00}, {0x000090A8, 0x3C, 0x68}, {0x00009178, 0x84, 0x98}, {0x000091B8, 0x01, 0x00}, {0x000091D8, 0x2C, 0x38}, {0x000091E0, 0x28, 0x30}, {0x00009258, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_100_ipd2ipe[] ={ {0x00008CF8, 0x01, 0x00}, {0x000090A7, 0xE3, 0x03}, {0x000090AB, 0xE5, 0x05}, {0x000090B3, 0xEA, 0x0A}, {0x00009178, 0x84, 0x98}, {0x000091B8, 0x01, 0x00}, {0x000091D8, 0x2C, 0x38}, {0x000091E0, 0x28, 0x30}, {0x00009258, 0x01, 0x00}, {0x00009263, 0xEA, 0x0A}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_101_ipd2ipe[] ={ {0x00009158, 0x01, 0x00}, {0x000094C7, 0xE3, 0x03}, {0x000094CB, 0xE5, 0x05}, {0x000094D3, 0xEA, 0x0A}, {0x00009598, 0x84, 0x98}, {0x000095D8, 0x01, 0x00}, {0x000095F8, 0x2C, 0x38}, {0x00009600, 0x28, 0x30}, {0x00009678, 0x01, 0x00}, {0x00009683, 0xEA, 0x0A}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_102_hack0[] ={ {0x00009184, 0x01, 0x00}, {0x000094F0, 0x01, 0x00}, {0x000094F4, 0x3C, 0x68}, {0x000095C4, 0x84, 0x98}, {0x00009604, 0x01, 0x00}, {0x00009624, 0x2C, 0x38}, {0x0000962C, 0x28, 0x30}, {0x000096A4, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_111_hack0[] ={ {0x0000482F, 0x1A, 0xEA}, {0x0000AF5C, 0x01, 0x00}, {0x0000B810, 0x00, 0x04}, {0x0000B812, 0xA0, 0x00}, {0x0000B813, 0xE1, 0x1A}, {0x0000B838, 0x00, 0x30}, {0x0000B858, 0xE0, 0x10}, {0x0000B859, 0x14, 0x15}, {0x0000B884, 0xB4, 0xE4}, {0x0000B958, 0x00, 0x10}, {0x0000B970, 0xEC, 0xF8}, {0x0000B9E0, 0x58, 0x88}, {0x0000BA58, 0x01, 0x00}, {0x0007A284, 0x32, 0x31}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_111_hack1[] ={ {0x0000482F, 0x1A, 0xEA}, {0x0000AF5C, 0x01, 0x00}, {0x0000B810, 0x00, 0x04}, {0x0000B812, 0xA0, 0x00}, {0x0000B813, 0xE1, 0x1A}, {0x0000B838, 0x00, 0x30}, {0x0000B858, 0xE0, 0x10}, {0x0000B859, 0x14, 0x15}, {0x0000B884, 0xB4, 0xE4}, {0x0000B958, 0x00, 0x10}, {0x0000B970, 0xEC, 0xF8}, {0x0000B9E0, 0x58, 0x88}, {0x0000BA58, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_111_hack2[] ={ {0x0000482F, 0x1A, 0xEA}, {0x0000AF5C, 0x01, 0x00}, {0x0000B814, 0x24, 0x54}, {0x0000B818, 0x01, 0x00}, {0x0000B838, 0x00, 0x30}, {0x0000B858, 0xE0, 0x10}, {0x0000B859, 0x14, 0x15}, {0x0000B884, 0xB4, 0xE4}, {0x0000B958, 0x00, 0x10}, {0x0000B970, 0xEC, 0xF8}, {0x0000B9E0, 0x58, 0x88}, {0x0000BA58, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_112_hack0[] ={ {0x00004B3B, 0x1A, 0xEA}, {0x000079FC, 0xD7, 0x00}, {0x000079FD, 0xFF, 0x00}, {0x000079FE, 0xFF, 0xA0}, {0x000079FF, 0x1A, 0xE1}, {0x00007E0B, 0x0A, 0xEA}, {0x0000AC73, 0x0A, 0xEA}, {0x0000BC40, 0x01, 0x00}, {0x0000C5C1, 0x40, 0x00}, {0x0000C5C2, 0xA0, 0x54}, {0x0000C5C8, 0x00, 0x04}, {0x0000C5CA, 0xA0, 0x00}, {0x0000C5CB, 0xE1, 0x1A}, {0x0000C614, 0x48, 0xAC}, {0x0000C640, 0x1C, 0x80}, {0x0000C6F0, 0x90, 0xD0}, {0x0000C74C, 0x44, 0x74}, {0x0000C7DC, 0xB4, 0xE4}, {0x0000C8AC, 0xB0, 0x14}, {0x0000C8AD, 0x33, 0x34}, {0x0000C904, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};a_patch lockdownd_112_ipe_old[] ={ {0x000079FC, 0xD7, 0x00}, {0x000079FD, 0xFF, 0x00}, {0x000079FE, 0xFF, 0xA0}, {0x000079FF, 0x1A, 0xE1}, {0x00007E0B, 0x0A, 0xEA}, {0x0000AC73, 0x0A, 0xEA}, {0x0000BC40, 0x01, 0x00}, {0x0000C5C8, 0x00, 0x04}, {0x0000C5CA, 0xA0, 0x00}, {0x0000C5CB, 0xE1, 0x1A}, {0x0000C614, 0x48, 0xAC}, {0x0000C640, 0x1C, 0x80}, {0x0000C6F0, 0x90, 0xD0}, {0x0000C74C, 0x44, 0x74}, {0x0000C7DC, 0xB4, 0xE4}, {0x0000C8AC, 0xB0, 0x14}, {0x0000C8AD, 0x33, 0x34}, {0x0000C904, 0x01, 0x00}, {0xFFFFFFFF, 0x00, 0x00}};os_fixes lockdownd_fixes[] ={ { "lockdownd-5a225c", 1,2,0, 0x343402BE, 0x40A55184, lockdownd_120_5a225c }, { "lockdownd", 1,1,4, 0x76177C04, 0xD500E7A2, lockdownd_114_patches }, { "lockdownd", 1,1,3, 0x53CBC7DB, 0xF0DC5C7D, lockdownd_113_patches }, { "lockdownd", 1,1,2, 0x44FCC4E8, 0x11EE32DF, lockdownd_112_patches }, { "lockdownd", 1,1,1, 0x749267AE, 0xF7A0E782, lockdownd_111_patches }, { "lockdownd", 1,0,2, 0x2D908293, 0xB0525bb7, lockdownd_102_patches }, { "lockdownd", 1,0,1, 0xBEEA7BE6, 0x0126C5B6, lockdownd_101_patches }, { "lockdownd", 1,0,0, 0x1F3EF62D, 0x09031ECF, lockdownd_100_patches }, /* To convert other patches to this one */ { "lockdownd-iphonedev", 1,0,0, 0x56A03DDC, 0x09031ECF, lockdownd_100_ipd2ipe }, { "lockdownd-iphonedev", 1,0,1, 0xF8E3714B, 0x0126C5B6, lockdownd_101_ipd2ipe }, { "lockdownd-hack0", 1,0,2, 0x2D908293, 0xB0525BB7, lockdownd_102_hack0 }, { "lockdownd-hack0", 1,1,1, 0x06F3F00F, 0xF7A0E782, lockdownd_111_hack0 }, { "lockdownd-hack1", 1,1,1, 0x7A813EC5, 0xF7A0E782, lockdownd_111_hack1 }, { "lockdownd-hack2", 1,1,1, 0x749267AE, 0xF7A0E782, lockdownd_111_hack1 }, { "lockdownd-hack0", 1,1,2, 0x6BBCCA70, 0x11EE32DF, lockdownd_112_hack0 }, { "lockdownd-outdated-ipe", 1,1,2, 0x4CA880A2, 0x11EE32DF, lockdownd_112_ipe_old }};typedef unsigned long CRC32_t;#define POLY 0xEDB88320#define ALL1 0xFFFFFFFFstatic CRC32_t *table = NULL;unsigned long REPORTING_LEVEL = 0xFFFFFFFF;void CRC32_Init(CRC32_t *value);void CRC32_Update(CRC32_t *value, void *data, unsigned int size);void CRC32_Final(unsigned char *out, CRC32_t value);int file_exists(char *path);unsigned long get_file_crc(char *path);int handle_patching(char *path, os_fixes *records, int num_records);void inform(int level, char *fmt, ...);int generate_patches(char *orig_path, char *new_path);int do_patches(char *path, a_patch *patches);void usage(char *path){ printf("iPatcher 1.1.x 2008-04-03 237325be65eb7b7663a4485529743805161b42da\n"); printf("Usage: %s [options]\n",path); printf("Options:\n"); printf("\t-a\t\tautomatically perform all patches\n"); printf("\t-l [file]\tpatch lockdownd at the path\n"); printf("\t-v [level]\tset verbosity to level\n"); printf("\t-m\t\tgenerate patch data (must use -o and -n)\n"); printf("\t-n [file]\tfile after patching (new file)\n"); printf("\t-o [file]\tfile before patching (original file)\n"); printf("\t-h\t\tprint this help\n");}int main(int argc, char *argv[]){ int ch; int do_something=0; int do_lockdownd = 0; int do_makepatch = 0; char *new_path = NULL; char *orig_path = NULL; char *lockdownd_path = LOCKDOWND_PATH; int ret_check; if ( argc < 2 ) { usage(argv[0]); return(0); } while ((ch = getopt(argc, argv, "ah?v:l:mn:o:")) != -1) { switch (ch) { case 'v': REPORTING_LEVEL = strtoul(optarg, NULL, 0); break; case 'l': do_lockdownd = 1; do_something = 1; lockdownd_path = optarg; break; case 'a': do_lockdownd = 1; do_something = 1; break; case 'm': do_makepatch = 1; do_something = 1; break; case 'n': new_path = optarg; break; case 'o': orig_path = optarg; break; case 'h': case '?': default: usage(argv[0]); return(0); } } if ( do_something == 0 ) { usage(argv[0]); return(0); } argc -= optind; argv += optind; if ( do_makepatch == 1 ) { if ( new_path == NULL || orig_path == NULL ) { inform(1, "[e] must supply an original and new file\n"); return(0); } if ( !file_exists(new_path)) { inform(1, "[e] file %s doesn't exist\n", new_path); return(0); } if ( !file_exists(orig_path)) { inform(1, "[e] file %s doesn't exist\n", orig_path); return(0); } inform(1, "[i] generating patches\n"); ret_check = generate_patches(orig_path, new_path); if ( ret_check == 1 ) { inform(1, "[i] patch generation succeeded\n"); } else { inform(1, "[i] patch generation failed\n"); } return(0); } if ( do_lockdownd ) { inform(1, "[i] Performing the lockdownd patch\n"); if(!file_exists(lockdownd_path)) { inform(2, "[e] no lockdownd at %s\n", lockdownd_path); inform(1, "[i] Lockdownd patch failed\n"); return(0); } ret_check = handle_patching(lockdownd_path, lockdownd_fixes, sizeof(lockdownd_fixes) / sizeof(os_fixes)); if ( ret_check == 1 ) { inform(1, "[i] Lockdownd patch succeeded\n"); } else { inform(1, "[i] Lockdownd patch failed\n"); } } return(0);}int file_exists(char *path){ int retcheck; struct stat finfo; retcheck = stat(path, &finfo); if ( retcheck == -1 ) return(0); return(1); }void inform(int level, char *fmt, ...){ if ( level <= REPORTING_LEVEL) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); if ( errno != 0 && level > 1) perror("last system error"); }}int generate_patches(char *orig_path, char *new_path){ FILE *o_file; FILE *n_file; unsigned char o_byte; unsigned char n_byte; unsigned long offset; unsigned long o_crc; unsigned long n_crc; o_file = fopen(orig_path, "rb"); if ( o_file == NULL ) { inform(2, "[e] generate_patches->fopen(orig) failed on %s\n", orig_path); return(0); } n_file = fopen(new_path, "rb"); if ( n_file == NULL ) { inform(2, "[e] generate_patches->fopen(new) failed on %s\n", new_path); return(0); } printf("a_patch new_patches[] =\n{\n"); while( (!feof(o_file)) && (!feof(n_file)) ) { o_byte = fgetc(o_file); n_byte = fgetc(n_file); if ( o_byte != n_byte ) { offset = ftell(o_file) - 1; if ( offset == -1 ) { inform(2,"[e] generate_patches->ftell failed\n"); return(0); } printf(" {0x%8.8X, 0x%2.2X, 0x%2.2X},\n", (unsigned int)offset, o_byte, n_byte); } } printf(" {0xFFFFFFFF, 0x00, 0x00}\n};\n"); fclose(o_file); fclose(n_file); o_crc = get_file_crc(orig_path); n_crc = get_file_crc(new_path); printf("original crc: 0x%8.8X\n", (unsigned int)o_crc); printf("new crc: 0x%8.8X\n", (unsigned int)n_crc); return(1);}int handle_patching(char *path, os_fixes *records, int num_records){ unsigned long orig_crc; unsigned long new_crc; a_patch *patches; os_fixes *a_fix; int cnt; int ret_val; a_fix = records; for(cnt = 0; cnt < num_records; cnt++) { patches = a_fix->patches; orig_crc = get_file_crc(path); if ( orig_crc == a_fix->new_crc ) { inform(2, "[i] found patched %d.%d.%d %s, no need to patch\n", a_fix->major, a_fix->minor, a_fix->sub,a_fix->file_id); return(1); } if ( orig_crc == a_fix->orig_crc ) { inform(2, "[i] found unpatched %d.%d.%d %s, patching\n", a_fix->major, a_fix->minor, a_fix->sub,a_fix->file_id); break; } a_fix++; } if ( cnt >= num_records ) { inform(2, "[e] could not match file to a known signature\n"); return(0); } ret_val = do_patches(path, patches); if ( ret_val == 0 ) { inform(2, "[e] couldn't perform the patch\n"); return(0); } new_crc = get_file_crc(path); if ( new_crc != a_fix->new_crc ) { inform(2, "[e] documented crc: %8.8X actual crc: %8.8X\n", a_fix->new_crc, new_crc); return(0); } inform(2, "[i] patch succeeded\n"); return(1);}int do_patches(char *path, a_patch *patches){ FILE *patch_file; a_patch *current_patch; unsigned char current_byte; int ret_val; ret_val = chmod(path, 0777); if ( ret_val == -1 ) { inform(2, "[e] couldn't set write permissions on file, continuing\n"); } patch_file = fopen(path, "r+b"); if( patch_file == NULL ) { inform(2,"[e] do_patches->fopen failure on %s\n", path); return(0); } current_patch = patches; while(current_patch->offset != 0xFFFFFFFF) { ret_val = fseek(patch_file, current_patch->offset, SEEK_SET); if(ret_val != 0) { inform(2,"[e] do_patches->fseek failure\n"); fclose(patch_file); return(0); } current_byte = fgetc(patch_file); if(current_byte != current_patch->orig_byte) { inform(2,"[e] do_patches: original byte does not match\n"); fclose(patch_file); return(0); } ret_val = fseek(patch_file, current_patch->offset, SEEK_SET); if(ret_val != 0) { inform(2,"[e] do_patches->fseek failure\n"); fclose(patch_file); return(0); } ret_val = fwrite(¤t_patch->new_byte, 1, 1, patch_file); if (ret_val != 1 ) { inform(2,"[e] do_patches->fputc failure\n"); fclose(patch_file); return(0); } current_patch++; } ret_val = fclose(patch_file); if ( ret_val != 0 ) { inform(2,"[e] do_patches->fclose failed\n"); } ret_val = chmod(path, 0555); if ( ret_val == -1 ) { inform(2, "[e] couldn't set file permissions to original\n"); } return(1);}unsigned long get_file_crc(char *path){ unsigned char inbuff[1024]; FILE *in_file; CRC32_t crc32; unsigned long ret_val; int ret_check; in_file = fopen(path, "rb"); if ( in_file == NULL ) { inform(2, "[e] get_file_crc->fopen failed on %s\n", path); return(0); } CRC32_Init(&crc32); while(!feof(in_file)) { fread(inbuff, sizeof(unsigned char), sizeof(inbuff), in_file); CRC32_Update(&crc32, inbuff, sizeof(inbuff)); } ret_check = fclose(in_file); if ( ret_check != 0 ) { inform(2, "[e] get_file_crc->fclose failed\n"); } CRC32_Final((unsigned char *)&ret_val, crc32); return(ret_val);}void CRC32_Init(CRC32_t *value){ unsigned int index, bit; CRC32_t entry; *value = ALL1; if (table) return;/* mem_alloc() doesn't return on failure. If replacing this with plain * malloc(3), error checking would need to be added. */ table = malloc(sizeof(*table) * 0x100); if ( table == NULL ) { inform(1,"[e] CRC32_Init->malloc failed\n"); exit(-1); } for (index = 0; index < 0x100; index++) { entry = index; for (bit = 0; bit < 8; bit++) if (entry & 1) { entry >>= 1; entry ^= POLY; } else entry >>= 1; table[index] = entry; }}void CRC32_Update(CRC32_t *value, void *data, unsigned int size){ unsigned char *ptr; unsigned int count; CRC32_t result; result = *value; ptr = data; count = size; if (count) do { result = (result >> 8) ^ table[(result ^ *ptr++) & 0xFF]; } while (--count); *value = result;}void CRC32_Final(unsigned char *out, CRC32_t value){ value = ~value; out[0] = value; out[1] = value >> 8; out[2] = value >> 16; out[3] = value >> 24;}