amfid_payload.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <mach-o/loader.h>
  5. #include <mach/error.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <dlfcn.h>
  9. #import <Foundation/Foundation.h>
  10. #include <CommonCrypto/CommonDigest.h>
  11. #include "fishhook.h"
  12. #include "cs_blobs.h"
  13. static unsigned int
  14. hash_rank(const CodeDirectory *cd)
  15. {
  16. uint32_t type = cd->hashType;
  17. unsigned int n;
  18. for (n = 0; n < sizeof(hashPriorities) / sizeof(hashPriorities[0]); ++n)
  19. if (hashPriorities[n] == type)
  20. return n + 1;
  21. return 0; /* not supported */
  22. }
  23. // 0 on success
  24. int get_hash(const CodeDirectory* directory, uint8_t dst[CS_CDHASH_LEN]) {
  25. uint32_t realsize = ntohl(directory->length);
  26. if (ntohl(directory->magic) != CSMAGIC_CODEDIRECTORY) {
  27. NSLog(@"[get_hash] wtf, not CSMAGIC_CODEDIRECTORY?!");
  28. return 1;
  29. }
  30. uint8_t out[CS_HASH_MAX_SIZE];
  31. uint8_t hash_type = directory->hashType;
  32. switch (hash_type) {
  33. case CS_HASHTYPE_SHA1:
  34. CC_SHA1(directory, realsize, out);
  35. break;
  36. case CS_HASHTYPE_SHA256:
  37. case CS_HASHTYPE_SHA256_TRUNCATED:
  38. CC_SHA256(directory, realsize, out);
  39. break;
  40. case CS_HASHTYPE_SHA384:
  41. CC_SHA384(directory, realsize, out);
  42. break;
  43. default:
  44. NSLog(@"[get_hash] Unknown hash type: 0x%x", hash_type);
  45. return 2;
  46. }
  47. memcpy(dst, out, CS_CDHASH_LEN);
  48. return 0;
  49. }
  50. // see cs_validate_csblob in xnu bsd/kern/ubc_subr.c
  51. // 0 on success
  52. int parse_superblob(uint8_t *code_dir, uint8_t dst[CS_CDHASH_LEN]) {
  53. int ret = 1;
  54. const CS_SuperBlob *sb = (const CS_SuperBlob *)code_dir;
  55. uint8_t highest_cd_hash_rank = 0;
  56. for (int n = 0; n < ntohl(sb->count); n++){
  57. const CS_BlobIndex *blobIndex = &sb->index[n];
  58. uint32_t type = ntohl(blobIndex->type);
  59. uint32_t offset = ntohl(blobIndex->offset);
  60. if (ntohl(sb->length) < offset) {
  61. NSLog(@"offset of blob #%d overflows superblob length", n);
  62. return 1;
  63. }
  64. const CodeDirectory *subBlob = (const CodeDirectory *)(code_dir + offset);
  65. // size_t subLength = ntohl(subBlob->length);
  66. if (type == CSSLOT_CODEDIRECTORY || (type >= CSSLOT_ALTERNATE_CODEDIRECTORIES && type < CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT)) {
  67. uint8_t rank = hash_rank(subBlob);
  68. if (rank > highest_cd_hash_rank) {
  69. ret = get_hash(subBlob, dst);
  70. highest_cd_hash_rank = rank;
  71. }
  72. }
  73. }
  74. return ret;
  75. }
  76. uint8_t *get_code_directory(const char* name, uint64_t file_off) {
  77. // XXX use mmap
  78. FILE* fd = fopen(name, "r");
  79. uint8_t *rv = NULL;
  80. if (fd == NULL) {
  81. NSLog(@"Couldn't open file");
  82. return NULL;
  83. }
  84. fseek(fd, 0L, SEEK_END);
  85. uint64_t file_len = ftell(fd);
  86. fseek(fd, 0L, SEEK_SET);
  87. if (file_off > file_len){
  88. NSLog(@"Error: File offset greater than length.");
  89. goto out;
  90. }
  91. uint64_t off = file_off;
  92. fseek(fd, off, SEEK_SET);
  93. struct mach_header_64 mh;
  94. fread(&mh, sizeof(struct mach_header_64), 1, fd);
  95. if (mh.magic != MH_MAGIC_64){
  96. NSLog(@"Error: Invalid magic");
  97. goto out;
  98. }
  99. off += sizeof(struct mach_header_64);
  100. if (off > file_len){
  101. NSLog(@"Error: Unexpected end of file");
  102. goto out;
  103. }
  104. for (int i = 0; i < mh.ncmds; i++) {
  105. if (off + sizeof(struct load_command) > file_len){
  106. NSLog(@"Error: Unexpected end of file");
  107. goto out;
  108. }
  109. const struct load_command cmd;
  110. fseek(fd, off, SEEK_SET);
  111. fread((void*)&cmd, sizeof(struct load_command), 1, fd);
  112. if (cmd.cmd == 0x1d) {
  113. uint32_t off_cs;
  114. fread(&off_cs, sizeof(uint32_t), 1, fd);
  115. uint32_t size_cs;
  116. fread(&size_cs, sizeof(uint32_t), 1, fd);
  117. if (off_cs+file_off+size_cs > file_len){
  118. NSLog(@"Error: Unexpected end of file");
  119. goto out;
  120. }
  121. rv = malloc(size_cs);
  122. if (rv != NULL) {
  123. fseek(fd, off_cs+file_off, SEEK_SET);
  124. fread(rv, size_cs, 1, fd);
  125. }
  126. goto out;
  127. } else {
  128. off += cmd.cmdsize;
  129. if (off > file_len){
  130. NSLog(@"Error: Unexpected end of file");
  131. goto out;
  132. }
  133. }
  134. }
  135. NSLog(@"Didnt find the code signature");
  136. out:;
  137. fclose(fd);
  138. return rv;
  139. }
  140. int (*old_MISValidateSignatureAndCopyInfo)(NSString* file, NSDictionary* options, NSMutableDictionary** info);
  141. int (*old_MISValidateSignatureAndCopyInfo_broken)(NSString* file, NSDictionary* options, NSMutableDictionary** info);
  142. int fake_MISValidateSignatureAndCopyInfo(NSString* file, NSDictionary* options, NSMutableDictionary** info) {
  143. // NSString *file = (__bridge NSString *)fileStr;
  144. // NSDictionary *options = (__bridge NSDictionary*)opts;
  145. NSLog(@"We got called! %@ with %@ (info: %@)", file, options, *info);
  146. int origret = old_MISValidateSignatureAndCopyInfo(file, options, info);
  147. NSLog(@"We got called! AFTER ACTUAL %@ with %@ (info: %@)", file, options, *info);
  148. if (![*info objectForKey:@"CdHash"]) {
  149. NSNumber* file_offset = [options objectForKey:@"UniversalFileOffset"];
  150. uint64_t file_off = [file_offset unsignedLongLongValue];
  151. uint8_t* code_directory = get_code_directory([file UTF8String], file_off);
  152. if (!code_directory) {
  153. NSLog(@"Can't get code_directory");
  154. return origret;
  155. }
  156. uint8_t cd_hash[CS_CDHASH_LEN];
  157. if (parse_superblob(code_directory, cd_hash)) {
  158. NSLog(@"Ours failed");
  159. return origret;
  160. }
  161. *info = [[NSMutableDictionary alloc] init];
  162. [*info setValue:[[NSData alloc] initWithBytes:cd_hash length:sizeof(cd_hash)] forKey:@"CdHash"];
  163. NSLog(@"ours: %@", *info);
  164. }
  165. return 0;
  166. }
  167. void rebind_mis(void) {
  168. void *libmis = dlopen("/usr/lib/libmis.dylib", RTLD_NOW); //Force binding now
  169. old_MISValidateSignatureAndCopyInfo = dlsym(libmis, "MISValidateSignatureAndCopyInfo");
  170. struct rebinding rebindings[] = {
  171. {"MISValidateSignatureAndCopyInfo", (void *)fake_MISValidateSignatureAndCopyInfo, (void **)&old_MISValidateSignatureAndCopyInfo_broken},
  172. };
  173. rebind_symbols(rebindings, 1);
  174. }
  175. __attribute__ ((constructor))
  176. static void ctor(void) {
  177. rebind_mis();
  178. }