amfi.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. //
  2. // amfi.m
  3. // Meridian
  4. //
  5. // Created by Ben Sparkes on 19/12/2017.
  6. // Copyright © 2017 Ben Sparkes. All rights reserved.
  7. //
  8. #import "patchfinder64.h"
  9. #import "kernel.h"
  10. #import "amfi.h"
  11. #import "helpers.h"
  12. #import "ViewController.h"
  13. #import <Foundation/Foundation.h>
  14. #import <CommonCrypto/CommonDigest.h>
  15. #import <mach-o/loader.h>
  16. #import <mach-o/dyld_images.h>
  17. #import <mach-o/fat.h>
  18. #import <mach-o/swap.h>
  19. #import <sys/stat.h>
  20. #import <sys/event.h>
  21. #import <dlfcn.h>
  22. #import <pthread.h>
  23. #import <sys/spawn.h>
  24. uint64_t trust_cache;
  25. uint64_t amficache;
  26. int init_amfi() {
  27. trust_cache = find_trustcache();
  28. amficache = find_amficache();
  29. NSLog(@"[amfi] trust_cache = 0x%llx \n", trust_cache);
  30. NSLog(@"[amfi] amficache = 0x%llx \n", amficache);
  31. if (trust_cache == 0 ||
  32. amficache == 0) {
  33. return -1;
  34. }
  35. return 0;
  36. }
  37. // creds to stek29(?)
  38. int inject_trust(const char *path) {
  39. if (file_exists(path) != 0) {
  40. NSLog(@"[amfi] you wanka, %s doesn't exist!", path);
  41. return -1;
  42. }
  43. typedef char hash_t[20];
  44. struct trust_chain {
  45. uint64_t next;
  46. unsigned char uuid[16];
  47. unsigned int count;
  48. hash_t hash[1];
  49. };
  50. struct trust_chain fake_chain;
  51. fake_chain.next = rk64(trust_cache);
  52. *(uint64_t *)&fake_chain.uuid[0] = 0xabadbabeabadbabe;
  53. *(uint64_t *)&fake_chain.uuid[8] = 0xabadbabeabadbabe;
  54. fake_chain.count = 1;
  55. uint8_t *codeDir = get_code_directory(path, 0);
  56. if (codeDir == NULL) {
  57. NSLog(@"[amfi] was given null code dir for %s!", path);
  58. return -2;
  59. }
  60. uint8_t *hash = get_sha1(codeDir);
  61. memmove(fake_chain.hash[0], hash, 20);
  62. free(hash);
  63. uint64_t kernel_trust = 0;
  64. mach_vm_allocate(tfp0, &kernel_trust, sizeof(fake_chain), VM_FLAGS_ANYWHERE);
  65. kwrite(kernel_trust, &fake_chain, sizeof(fake_chain));
  66. wk64(trust_cache, kernel_trust);
  67. NSLog(@"[amfi] signed %s \n", path);
  68. return 0;
  69. }
  70. uint8_t *get_code_directory(const char* file_path, uint64_t file_off) {
  71. FILE* fd = fopen(file_path, "r");
  72. if (fd == NULL) {
  73. NSLog(@"[amfi] couldn't open file %s", file_path);
  74. fclose(fd);
  75. return NULL;
  76. }
  77. fseek(fd, 0L, SEEK_END);
  78. uint64_t file_len = ftell(fd);
  79. fseek(fd, 0L, SEEK_SET);
  80. if (file_off > file_len){
  81. NSLog(@"[amfi] file offset greater than length");
  82. fclose(fd);
  83. return NULL;
  84. }
  85. uint32_t magic;
  86. fread(&magic, sizeof(magic), 1, fd);
  87. fseek(fd, 0, SEEK_SET);
  88. int is_swap = (magic == MH_CIGAM || magic == MH_CIGAM_64 || magic == FAT_CIGAM);
  89. uint64_t off = file_off;
  90. int ncmds = 0;
  91. if (magic == MH_MAGIC_64) {
  92. struct mach_header_64 mh64;
  93. fread(&mh64, sizeof(mh64), 1, fd);
  94. off += sizeof(mh64);
  95. ncmds = mh64.ncmds;
  96. } else if (magic == MH_MAGIC) {
  97. struct mach_header mh;
  98. fread(&mh, sizeof(mh), 1, fd);
  99. off += sizeof(mh);
  100. ncmds = mh.ncmds;
  101. } else if (magic == FAT_CIGAM || magic == FAT_CIGAM_64) {
  102. struct fat_header header;
  103. fread(&header, sizeof(header), 1, fd);
  104. if (is_swap) swap_fat_header(&header, 0);
  105. int arch_offset = sizeof(header);
  106. for (int i = 0; i < header.nfat_arch; i++) {
  107. struct fat_arch arch;
  108. fseek(fd, arch_offset, 0);
  109. fread(&arch, sizeof(struct fat_arch), 1, fd);
  110. if (is_swap) swap_fat_arch(&arch, 1, 0);
  111. if (arch.cputype != CPU_TYPE_ARM64) continue;
  112. fseek(fd, arch.offset, 0);
  113. uint32_t magic;
  114. fread(&magic, sizeof(magic), 1, fd);
  115. if (magic == MH_MAGIC) {
  116. struct mach_header mh;
  117. fread(&mh, sizeof(mh), 1, fd);
  118. off += arch.offset + sizeof(mh);
  119. ncmds = mh.ncmds;
  120. } else if (magic == MH_MAGIC_64) {
  121. struct mach_header_64 mh64;
  122. fread(&mh64, sizeof(mh64), 1, fd);
  123. off += arch.offset + sizeof(mh64);
  124. ncmds = mh64.ncmds;
  125. }
  126. arch_offset += sizeof(arch);
  127. }
  128. } else {
  129. NSLog(@"[amfi] your magic is not valid in these lands! %ux", magic);
  130. fclose(fd);
  131. return NULL;
  132. }
  133. if (off > file_len) {
  134. NSLog(@"[amfi] unexpected end of file");
  135. fclose(fd);
  136. return NULL;
  137. }
  138. fseek(fd, off, SEEK_SET);
  139. for (int i = 0; i < ncmds; i++) {
  140. if (off + sizeof(struct load_command) > file_len) {
  141. NSLog(@"[amfi] unexpected end of file");
  142. fclose(fd);
  143. return NULL;
  144. }
  145. const struct load_command cmd;
  146. fseek(fd, off, SEEK_SET);
  147. fread((void*)&cmd, sizeof(struct load_command), 1, fd);
  148. if (cmd.cmd == LC_CODE_SIGNATURE) {
  149. uint32_t off_cs;
  150. fread(&off_cs, sizeof(uint32_t), 1, fd);
  151. uint32_t size_cs;
  152. fread(&size_cs, sizeof(uint32_t), 1, fd);
  153. if (off_cs + file_off + size_cs > file_len) {
  154. NSLog(@"[amfi] unexpected end of file");
  155. fclose(fd);
  156. return NULL;
  157. }
  158. uint8_t *cd = malloc(size_cs);
  159. fseek(fd, off_cs + file_off, SEEK_SET);
  160. fread(cd, size_cs, 1, fd);
  161. return cd;
  162. } else {
  163. off += cmd.cmdsize;
  164. if (off > file_len) {
  165. NSLog(@"[amfi] unexpected end of file");
  166. fclose(fd);
  167. return NULL;
  168. }
  169. }
  170. }
  171. NSLog(@"[amfi] couldn't find the code sig for %s", file_path);
  172. fclose(fd);
  173. return NULL;
  174. }
  175. // creds to nullpixel
  176. uint8_t *get_sha1(uint8_t* code_dir) {
  177. uint8_t *out = malloc(CC_SHA1_DIGEST_LENGTH);
  178. uint32_t* code_dir_int = (uint32_t*)code_dir;
  179. uint32_t realsize = 0;
  180. for (int j = 0; j < 10; j++) {
  181. if (swap_uint32(code_dir_int[j]) == 0xfade0c02) {
  182. realsize = swap_uint32(code_dir_int[j+1]);
  183. code_dir += 4*j;
  184. }
  185. }
  186. CC_SHA1(code_dir, realsize, out);
  187. return out;
  188. }
  189. uint32_t swap_uint32(uint32_t val) {
  190. val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
  191. return (val << 16) | (val >> 16);
  192. }