// // amfi_utils.c // electra // // Created by Jamie on 27/01/2018. // Copyright © 2018 Electra Team. All rights reserved. // #include "amfi_utils.h" #include "kutils.h" #include "kmem.h" #include "patchfinder64.h" #include #include #include uint32_t swap_uint32_electra( uint32_t val ) { val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF ); return (val << 16) | (val >> 16); } void getSHA256inplace(const uint8_t* code_dir, uint8_t *out) { if (code_dir == NULL) { printf("NULL passed to getSHA256inplace!\n"); return; } uint32_t* code_dir_int = (uint32_t*)code_dir; uint32_t realsize = 0; for (int j = 0; j < 10; j++) { if (swap_uint32_electra(code_dir_int[j]) == 0xfade0c02) { realsize = swap_uint32_electra(code_dir_int[j+1]); code_dir += 4*j; } } CC_SHA256(code_dir, realsize, out); } uint8_t *getSHA256(const uint8_t* code_dir) { uint8_t *out = malloc(CC_SHA256_DIGEST_LENGTH); getSHA256inplace(code_dir, out); return out; } uint8_t *getCodeDirectory(const char* name) { // Assuming it is a macho FILE* fd = fopen(name, "r"); uint32_t magic; fread(&magic, sizeof(magic), 1, fd); fseek(fd, 0, SEEK_SET); long off; int ncmds; if (magic == MH_MAGIC_64) { struct mach_header_64 mh64; fread(&mh64, sizeof(mh64), 1, fd); off = sizeof(mh64); ncmds = mh64.ncmds; } else if (magic == MH_MAGIC) { struct mach_header mh; fread(&mh, sizeof(mh), 1, fd); off = sizeof(mh); ncmds = mh.ncmds; } else { printf("%s is not a macho! (or has foreign endianness?) (magic: %x)\n", name, magic); 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, SEEK_SET); fread(cd, size_cs, 1, fd); return cd; } else { off += cmd.cmdsize; } } return NULL; } void inject_trusts(int pathc, const char *paths[]) { static uint64_t tc = 0; if (tc == 0) tc = find_trustcache_electra(); struct trust_chain fake_chain; fake_chain.next = rk64_electra(tc); *(uint64_t *)&fake_chain.uuid[0] = 0xabadbabeabadbabe; *(uint64_t *)&fake_chain.uuid[8] = 0xabadbabeabadbabe; int cnt = 0; uint8_t hash[CC_SHA256_DIGEST_LENGTH]; hash_t *allhash = malloc(sizeof(hash_t) * pathc); for (int i = 0; i != pathc; ++i) { uint8_t *cd = getCodeDirectory(paths[i]); if (cd != NULL) { getSHA256inplace(cd, hash); memmove(allhash[cnt], hash, sizeof(hash_t)); ++cnt; } } fake_chain.count = cnt; size_t length = (sizeof(fake_chain) + cnt * sizeof(hash_t) + 0xFFFF) & ~0xFFFF; uint64_t kernel_trust = kalloc(length); kwrite_electra(kernel_trust, &fake_chain, sizeof(fake_chain)); kwrite_electra(kernel_trust + sizeof(fake_chain), allhash, cnt * sizeof(hash_t)); wk64_electra(tc, kernel_trust); }