#include #include #include #include #include "patchfinder64.h" #include "kernel_utils.h" #include "sha1.h" #include "sha256.h" #import //#define LOG(str, args...) do { NSLog(@"[*] " str "\n", ##args); } while(0) #define LOG(str, args...) struct trust_mem { uint64_t next; //struct trust_mem *next; unsigned char uuid[16]; unsigned int count; //unsigned char data[]; } __attribute__((packed)); uint32_t swap_uint32( uint32_t val ) { val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF ); return (val << 16) | (val >> 16); } uint32_t read_magic(FILE* file, off_t offset) { uint32_t magic; fseek(file, offset, SEEK_SET); fread(&magic, sizeof(uint32_t), 1, file); return magic; } void *load_bytes(FILE *file, off_t offset, size_t size) { void *buf = calloc(1, size); fseek(file, offset, SEEK_SET); fread(buf, size, 1, file); return buf; } uint8_t *get_code_directory(const char* name) { FILE* fd = fopen(name, "r"); uint32_t magic; fread(&magic, sizeof(magic), 1, fd); fseek(fd, 0, SEEK_SET); long off, file_off = 0; int ncmds; int foundarm64 = 0; if (magic == MH_MAGIC_64) { // 0xFEEDFACF struct mach_header_64 mh64; fread(&mh64, sizeof(mh64), 1, fd); off = sizeof(mh64); ncmds = mh64.ncmds; } else if (magic == MH_MAGIC) { printf("[-] %s is 32bit. What are you doing here?\n", name); fclose(fd); return NULL; } else if (magic == 0xBEBAFECA) { //FAT binary magic size_t header_size = sizeof(struct fat_header); size_t arch_size = sizeof(struct fat_arch); size_t arch_off = header_size; struct fat_header *fat = (struct fat_header*)load_bytes(fd, 0, header_size); struct fat_arch *arch = (struct fat_arch *)load_bytes(fd, arch_off, arch_size); int n = swap_uint32(fat->nfat_arch); printf("[*] Binary is FAT with %d architectures\n", n); while (n-- > 0) { magic = read_magic(fd, swap_uint32(arch->offset)); if (magic == 0xFEEDFACF) { printf("[*] Found arm64\n"); foundarm64 = 1; struct mach_header_64* mh64 = (struct mach_header_64*)load_bytes(fd, swap_uint32(arch->offset), sizeof(struct mach_header_64)); file_off = swap_uint32(arch->offset); off = swap_uint32(arch->offset) + sizeof(struct mach_header_64); ncmds = mh64->ncmds; break; } arch_off += arch_size; arch = load_bytes(fd, arch_off, arch_size); } if (!foundarm64) { // by the end of the day there's no arm64 found printf("[-] No arm64? RIP\n"); fclose(fd); return NULL; } } else { printf("[-] %s is not a macho! (or has foreign endianness?) (magic: %x)\n", name, magic); fclose(fd); return NULL; } for (int i = 0; i < ncmds; i++) { struct load_command cmd; fseek(fd, off, SEEK_SET); fread(&cmd, sizeof(struct load_command), 1, fd); if (cmd.cmd == LC_CODE_SIGNATURE) { uint32_t off_cs; fread(&off_cs, sizeof(uint32_t), 1, fd); uint32_t size_cs; fread(&size_cs, sizeof(uint32_t), 1, fd); uint8_t *cd = malloc(size_cs); fseek(fd, off_cs + file_off, SEEK_SET); fread(cd, size_cs, 1, fd); fclose(fd); return cd; } else { off += cmd.cmdsize; } } fclose(fd); return NULL; } void get_sha256_hash(const uint8_t* data, uint32_t datasize, uint8_t *out) { SHA256_CTX ctx; sha256_init(&ctx); sha256_update(&ctx, data, datasize); sha256_final(&ctx, out); } void get_sha1_hash(const uint8_t* data, uint32_t datasize, uint8_t *out) { SHA1_CTX ctx; SHA1Init(&ctx); SHA1Update(&ctx, data, datasize); SHA1Final(out, &ctx); } int trust_bin(const char* filepath) { uint64_t trust_chain = Find_trustcache(); if (!trust_chain) { trust_chain = Find_trustcache10_3_2(); } LOG("trust %p\n", (void*)trust_chain); struct trust_mem fake_chain; fake_chain.next = KernelRead_64bits(trust_chain); *(uint64_t *)&fake_chain.uuid[0] = 0xabadbabeabadbabe; *(uint64_t *)&fake_chain.uuid[8] = 0xabadbabeabadbabe; LOG("trust_chain %p\n", (void*)fake_chain.next); uint8_t *cd = get_code_directory(filepath); if (!cd) { return -1; } uint32_t* code_dir_int = (uint32_t*)cd; uint32_t realsize = 0; for (int j = 0; j < 10; j++) { if (swap_uint32(code_dir_int[j]) == 0xfade0c02) { realsize = swap_uint32(code_dir_int[j+1]); cd += 4*j; } } uint8_t *hash; size_t hash_size; // iOS 11 uses sha-256 if (kCFCoreFoundationVersionNumber >= 1443.00) { hash_size = 32; hash = malloc(hash_size); get_sha256_hash(cd, realsize, hash); } else { hash_size = 20; hash = malloc(hash_size); get_sha1_hash(cd, realsize, hash); } fake_chain.count = 1; size_t length = (sizeof(fake_chain) + hash_size + 0xFFFF) & ~0xFFFF; uint64_t kernel_trust = Kernel_alloc(length); LOG("[*] allocated: 0x%zx => 0x%llx\n", length, kernel_trust); KernelWrite(kernel_trust, &fake_chain, sizeof(fake_chain)); KernelWrite(kernel_trust + sizeof(fake_chain), hash, hash_size); KernelWrite_64bits(trust_chain, kernel_trust); return 0; }