main.m 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Massive creds to @theninjaprawn for his async_wake fork & help getting this patch to work :)
  2. // [2018-3-14] big thanks for stek for letting me use his code on proper blob parsing :) -> https://github.com/stek29/electra/blob/amfid_fix/basebinaries/amfid_payload/
  3. #include <dlfcn.h>
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <sys/types.h>
  7. #include <mach/mach.h>
  8. #include <mach-o/loader.h>
  9. #include <mach-o/fat.h>
  10. #include <mach/error.h>
  11. #include <errno.h>
  12. #include <stdlib.h>
  13. #include <sys/sysctl.h>
  14. #include <dlfcn.h>
  15. #include <sys/mman.h>
  16. #include <spawn.h>
  17. #include <sys/stat.h>
  18. #include <pthread.h>
  19. #include <Foundation/Foundation.h>
  20. #include <CommonCrypto/CommonDigest.h>
  21. #include "helpers/fishhook.h"
  22. #include "kern_utils.h"
  23. #include "helpers/kexecute.h"
  24. #include "helpers/kmem.h"
  25. #include "helpers/patchfinder64.h"
  26. #include "ent_patching.h"
  27. int (*old_MISValidateSignatureAndCopyInfo)(NSString* file, NSDictionary* options, NSMutableDictionary** info);
  28. int (*old_MISValidateSignatureAndCopyInfo_broken)(NSString* file, NSDictionary* options, NSMutableDictionary** info);
  29. int fake_MISValidateSignatureAndCopyInfo(NSString* file, NSDictionary* options, NSMutableDictionary** info) {
  30. const char* file_path = [file UTF8String];
  31. INFO(@"called for file %s", file_path);
  32. // Call the original func
  33. old_MISValidateSignatureAndCopyInfo(file, options, info);
  34. if (info == NULL) {
  35. INFO("info is null - skipping");
  36. return 0;
  37. }
  38. if (*info == NULL) {
  39. *info = [[NSMutableDictionary alloc] init];
  40. if (*info == nil) {
  41. ERROR("out of memory - can't alloc info");
  42. return 0;
  43. }
  44. }
  45. if ([*info objectForKey:@"CdHash"]) {
  46. return 0;
  47. }
  48. NSNumber* file_offset = [options objectForKey:@"UniversalFileOffset"];
  49. uint64_t file_off = [file_offset unsignedLongLongValue];
  50. img_info_t img;
  51. img.name = file.UTF8String;
  52. img.file_off = file_off;
  53. if (open_img(&img)) {
  54. ERROR(@"failed to open file: %@", file);
  55. return 0;
  56. }
  57. uint32_t cs_length;
  58. const uint8_t *cs = find_code_signature(&img, &cs_length);
  59. if (cs == NULL) {
  60. ERROR(@"can't find code signature: %@", file);
  61. close_img(&img);
  62. return 0;
  63. }
  64. const CS_CodeDirectory *chosen_csdir = NULL;
  65. uint32_t cdir_offset = 0;
  66. const CS_GenericBlob *entitlements = NULL; // may be NULL for no entitlements
  67. int ret = find_best_codedir(cs, cs_length, &chosen_csdir, &cdir_offset, &entitlements);
  68. if (ret != 0) {
  69. ERROR(@"failed to find the best code directory");
  70. close_img(&img);
  71. return 0;
  72. }
  73. uint8_t cd_hash[CS_CDHASH_LEN];
  74. ret = hash_code_directory(chosen_csdir, cd_hash);
  75. if (ret != 0) {
  76. ERROR(@"failed to hash code directory");
  77. close_img(&img);
  78. return 0;
  79. }
  80. NSData *ns_cdhash = [[NSData alloc] initWithBytes:cd_hash length:sizeof(cd_hash)];
  81. [*info setValue: ns_cdhash forKey:@"CdHash"];
  82. const char *hash_name = get_hash_name(chosen_csdir->hashType);
  83. INFO(@"magic was performed [%08x (%s)]: %@", ntohl(*(uint64_t *)cd_hash), hash_name, file);
  84. /*
  85. // let's check entitlements, add platform-application if necessary
  86. ret = fixup_platform_application(file.UTF8String,
  87. file_off,
  88. cs,
  89. cs_length,
  90. cd_hash,
  91. cdir_offset,
  92. entitlements);
  93. if (ret != 0) {
  94. ERROR(@"fixup_platform_application returned: %d", ret);
  95. }
  96. */
  97. close_img(&img);
  98. return 0;
  99. }
  100. void *hook_funcs(void *arg) {
  101. INFO(@"created new thread");
  102. // This is some wicked crazy shit that needs to happen to correctly patch
  103. // after amfid has been killed & launched & patched again... it's nuts.
  104. // shouldn't even work. creds whoever came up w this @ ElectraTeam
  105. void *libmis = dlopen("/usr/lib/libmis.dylib", RTLD_NOW);
  106. old_MISValidateSignatureAndCopyInfo = dlsym(libmis, "MISValidateSignatureAndCopyInfo");
  107. struct rebinding rebindings[] = {
  108. { "MISValidateSignatureAndCopyInfo", (void *)fake_MISValidateSignatureAndCopyInfo, (void **)&old_MISValidateSignatureAndCopyInfo_broken }
  109. /* you can say that again ^^^^^^ */
  110. };
  111. rebind_symbols(rebindings, 1);
  112. // touch file so Meridian know's we're alive in here
  113. fclose(fopen("/var/tmp/amfid_payload.alive", "w+"));
  114. return NULL;
  115. }
  116. __attribute__ ((constructor))
  117. static void ctor(void) {
  118. INFO("preparing to fuck up amfid :)");
  119. kern_return_t ret = host_get_special_port(mach_host_self(), HOST_LOCAL_NODE, 4, &tfp0);
  120. if (ret != KERN_SUCCESS || tfp0 == MACH_PORT_NULL) {
  121. INFO("failed to get tfp0!");
  122. return;
  123. }
  124. INFO("got tfp0: %x", tfp0);
  125. NSDictionary *off_file = [NSDictionary dictionaryWithContentsOfFile:@"/meridian/offsets.plist"];
  126. kernel_base = strtoull([off_file[@"KernelBase"] UTF8String], NULL, 16);
  127. kernel_slide = strtoull([off_file[@"KernelSlide"] UTF8String], NULL, 16);
  128. offset_zonemap = strtoull([off_file[@"ZoneMap"] UTF8String], NULL, 16) + kernel_slide;
  129. offset_kernel_task = strtoull([off_file[@"KernelTask"] UTF8String], NULL, 16) + kernel_slide;
  130. offset_vfs_context_current = strtoull([off_file[@"VfsContextCurrent"] UTF8String], NULL, 16) + kernel_slide;
  131. offset_vnode_getfromfd = strtoull([off_file[@"VnodeGetFromFD"] UTF8String], NULL, 16) + kernel_slide;
  132. offset_vnode_getattr = strtoull([off_file[@"VnodeGetAttr"] UTF8String], NULL, 16) + kernel_slide;
  133. offset_csblob_ent_dict_set = strtoull([off_file[@"CSBlobEntDictSet"] UTF8String], NULL, 16) + kernel_slide;
  134. offset_sha1_init = strtoull([off_file[@"SHA1Init"] UTF8String], NULL, 16) + kernel_slide;
  135. offset_sha1_update = strtoull([off_file[@"SHA1Update"] UTF8String], NULL, 16) + kernel_slide;
  136. offset_sha1_final = strtoull([off_file[@"SHA1Final"] UTF8String], NULL, 16) + kernel_slide;
  137. INFO(@"grabbed all offsets! eg: %llx, %llx, slide: %llx", offset_kernel_task, offset_sha1_final, kernel_slide);
  138. init_kernel(kernel_base, NULL);
  139. init_kexecute();
  140. pthread_t thread;
  141. pthread_create(&thread, NULL, hook_funcs, NULL);
  142. }