Advertisement
bottomy

feedface 0.21 [WIP]

Jun 6th, 2012
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * feedface: An injection, scanning, and general interaction tool for Mac OS X (for interaction with 32 bit and 64 bit x86 processes).
  3.  *
  4.  * Written for Mac OS X 10.6+ as a 64 bit application.
  5.  *
  6.  * Compilation instructions:
  7.  * clang feedface.m -o feedface -framework Foundation
  8.  * gcc feedface.m -o feedface -std=gnu99 -framework Foundation
  9.  * llvm-gcc feedface.m -o feedface -std=gnu99 -framework Foundation
  10.  *
  11.  * Executable: http://www.mediafire.com/?fk3u06yn3338cg3
  12.  *
  13.  * Version: 0.21
  14.  * Changes:
  15.  * Added support for relocating an address for a specific image in the target task.
  16.  */
  17.  
  18. #import <Foundation/Foundation.h>
  19.  
  20. #import <mach/mach.h>
  21. #import <mach/mach_vm.h>
  22. #import <mach-o/dyld_images.h>
  23. #import <mach-o/loader.h>
  24.  
  25.  
  26. void DisplayUsage(void);
  27. int GetBytesFromString(const char * restrict, const size_t, uint8_t * restrict);
  28. int InjectBytes(vm_map_t, mach_vm_address_t, mach_vm_address_t, const size_t);
  29. int ReadBytes(vm_map_t, mach_vm_address_t, mach_vm_address_t, const size_t, size_t *);
  30. int IsProc64(vm_map_t, _Bool * const);
  31. void *Locate_dlsym(vm_map_t);
  32. int SuspendTaskWithNoExecutionInRange(vm_map_t, mach_vm_address_t, mach_vm_address_t); //Wow what a name :P
  33. int AddressFromString(vm_map_t, const char *, mach_vm_address_t *);
  34. int RelocateAddressInTask(vm_map_t, mach_vm_address_t * const, const char * const);
  35.  
  36.  
  37. int Command_Bytes(vm_map_t, vm_map_t, const char **, const int);
  38. int Command_String(vm_map_t, vm_map_t, const char **, const int);
  39. int Command_Codecave(vm_map_t, vm_map_t, const char **, const int);
  40. //int Command_Bundle(vm_map_t, vm_map_t, const char **, const int);
  41.  
  42.  
  43. //See mach-o/dyld_images.h to update for later versions.
  44. struct dyld_all_image_infos32 {
  45.     uint32_t version;
  46.     uint32_t infoArrayCount;
  47.     uint32_t infoArray;
  48.     uint32_t notification;
  49.     bool processDetachedFromSharedRegion;
  50.     bool libSystemInitialized;
  51.     uint32_t dyldImageLoadAddress;
  52.     uint32_t jitInfo;
  53.     uint32_t dyldVersion;
  54.     uint32_t errorMessage;
  55.     uint32_t terminationFlags;
  56.     uint32_t coreSymbolicationShmPage;
  57.     uint32_t systemOrderFlag;
  58.     uint32_t uuidArrayCount;
  59.     uint32_t uuidArray;
  60.     uint32_t dyldAllImageInfosAddress;
  61.     uint32_t initialImageCount;
  62.     uint32_t errorKind;
  63.     uint32_t errorClientOfDylibPath;
  64.     uint32_t errorTargetDylibPath;
  65.     uint32_t errorSymbol;
  66.     uint32_t sharedCacheSlide;
  67. };
  68.  
  69. struct dyld_image_info32 {
  70.     uint32_t imageLoadAddress;
  71.     uint32_t imageFilePath;
  72.     uint32_t imageFileModDate;
  73. };
  74.  
  75. struct dyld_all_image_infos64 {
  76.     uint32_t version;
  77.     uint32_t infoArrayCount;
  78.     uint64_t infoArray;
  79.     uint64_t notification;
  80.     bool processDetachedFromSharedRegion;
  81.     bool libSystemInitialized;
  82.     uint64_t dyldImageLoadAddress;
  83.     uint64_t jitInfo;
  84.     uint64_t dyldVersion;
  85.     uint64_t errorMessage;
  86.     uint64_t terminationFlags;
  87.     uint64_t coreSymbolicationShmPage;
  88.     uint64_t systemOrderFlag;
  89.     uint64_t uuidArrayCount;
  90.     uint64_t uuidArray;
  91.     uint64_t dyldAllImageInfosAddress;
  92.     uint64_t initialImageCount;
  93.     uint64_t errorKind;
  94.     uint64_t errorClientOfDylibPath;
  95.     uint64_t errorTargetDylibPath;
  96.     uint64_t errorSymbol;
  97.     uint64_t sharedCacheSlide;
  98. };
  99.  
  100. struct dyld_image_info64 {
  101.     uint64_t imageLoadAddress;
  102.     uint64_t imageFilePath;
  103.     uint64_t imageFileModDate;
  104. };
  105.  
  106. const struct {
  107.     const char *flag;
  108.     const char *example;
  109.     int min, max;
  110.     int (*execute)(vm_map_t, vm_map_t, const char **, const int);
  111. } Options[] = {
  112.     { .flag = "-bytes", .example = "[bytes in hex (no spaces)] [address in process to inject to]", 2, 2, Command_Bytes },
  113.     { .flag = "-string", .example = "[string (use \\\\x for hex values)] [address in process to inject to]", 2, 2, Command_String },
  114.     { .flag = "-codecave", .example = "[address in process to codecave from] [optional (min = 5 for 32 bit or 14 for 64 bit, if not used defaults to min): -s followed by the size of original code to remove] [code to be injected: [optional: -oc will place the original code before your code] [optional: bytes in hex (no spaces)]]", 2, INT_MAX, Command_Codecave },
  115.     //{ .flag = "-bundle", .example = "", 0, 0, Command_Bundle }
  116. };
  117.  
  118. int main(int argc, char *argv[])
  119. {
  120.     if (argc < 3)
  121.     {
  122.         DisplayUsage();
  123.         return EXIT_FAILURE;
  124.     }
  125.    
  126.    
  127.     errno = 0;
  128.     pid_t Target = (pid_t)strtol(argv[1], NULL, 10);
  129.    
  130.     if (errno)
  131.     {
  132.         //Don't bother checking just report invalid number
  133.         printf("Invalid format for pid: %s\n",  argv[1]);
  134.         return EXIT_FAILURE;
  135.     }
  136.    
  137.     vm_map_t RemoteTask, TaskSelf = mach_task_self();
  138.     mach_error_t err = task_for_pid(TaskSelf, Target, &RemoteTask);
  139.     if (err != KERN_SUCCESS)
  140.     {
  141.         mach_error("task_for_pid", err);
  142.         if (err == 5) printf("Invalid PID or not running as root\n");
  143.        
  144.         return EXIT_FAILURE;
  145.     }
  146.    
  147.     for (size_t Loop = 0; Loop < sizeof(Options) / sizeof(typeof(*Options)); Loop++)
  148.     {
  149.         if (!strcmp(Options[Loop].flag, argv[2]))
  150.         {
  151.             if ((argc < 3 + Options[Loop].min) || (argc > (unsigned int)(3 + Options[Loop].max)))
  152.             {
  153.                 DisplayUsage();
  154.                 return EXIT_FAILURE;
  155.             }
  156.            
  157.             return Options[Loop].execute(TaskSelf, RemoteTask, (const char**)&argv[3], argc - 3);
  158.         }
  159.     }
  160.    
  161.    
  162.     printf("Invalid option: %s\n", argv[2]);
  163.     DisplayUsage();
  164.    
  165.     return EXIT_FAILURE;
  166. }
  167.  
  168. void DisplayUsage(void)
  169. {
  170.     printf("inject pid Option\n"
  171.            "Options:\n");
  172.    
  173.     for (size_t Loop = 0; Loop < sizeof(Options) / sizeof(typeof(*Options)); Loop++)
  174.     {
  175.         printf("\t%s %s\n", Options[Loop].flag, Options[Loop].example);
  176.     }
  177. }
  178.  
  179. int GetBytesFromString(const char * restrict Str, const size_t Length, uint8_t * restrict Bytes)
  180. {
  181.     errno = 0;
  182.     const char *Hex = Str;
  183.     for (size_t Loop = 0; Loop < Length; Loop += 2, Hex += 2)
  184.     {
  185.         Bytes[Loop / 2] = strtol((char[3]){ Hex[0], Hex[1], 0 }, NULL, 16);
  186.        
  187.         if (errno)
  188.         {
  189.             //Don't bother checking just report invalid number
  190.             printf("Invalid hexadecimal value (%2s) in bytes: %s\n", Hex, Str);
  191.             return -1;
  192.         }
  193.     }
  194.    
  195.     return 0;
  196. }
  197.  
  198. int InjectBytes(vm_map_t RemoteTask, mach_vm_address_t Address, mach_vm_address_t Bytes, const size_t Size)
  199. {
  200.     mach_vm_size_t RegionSize;
  201.     vm_region_basic_info_data_64_t Info;
  202.     mach_port_t ObjectName;
  203.     mach_msg_type_number_t Count = VM_REGION_BASIC_INFO_COUNT_64;
  204.    
  205.     mach_error_t err = mach_vm_region(RemoteTask, &(mach_vm_address_t){ Address }, &RegionSize, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&Info, &Count, &ObjectName);
  206.     if (err != KERN_SUCCESS)
  207.     {
  208.         mach_error("mach_vm_region", err);
  209.         printf("Region error: %u\n", err);
  210.         return -1;
  211.     }
  212.    
  213.    
  214.     err = mach_vm_protect(RemoteTask, Address, Size, FALSE, VM_PROT_ALL);
  215.     if (err != KERN_SUCCESS)
  216.     {
  217.         mach_error("mach_vm_protect", err);
  218.         printf("Protection error: %u\n", err);
  219.         return -1;
  220.     }
  221.    
  222.    
  223.     err = mach_vm_write(RemoteTask, Address, Bytes, (mach_msg_type_number_t)Size);
  224.     if (err != KERN_SUCCESS)
  225.     {
  226.         mach_error("mach_vm_write", err);
  227.         printf("Writing error: %u\n", err);
  228.         return -1;
  229.     }
  230.    
  231.    
  232.     err = mach_vm_protect(RemoteTask, Address, Size, FALSE, Info.protection);
  233.     if (err != KERN_SUCCESS)
  234.     {
  235.         mach_error("mach_vm_protect", err);
  236.         printf("Protection error: %u\n", err);
  237.        
  238.         /*
  239.          While the injection should have succeeded, was unable to return
  240.          the protection for that region back to it's original rights.
  241.          */
  242.        
  243.         printf("Current protection left as VM_PROT_ALL, but was originally:");
  244.        
  245.         if (Info.protection & VM_PROT_READ)
  246.         {
  247.             printf(" VM_PROT_READ");
  248.         }
  249.        
  250.         if (Info.protection & VM_PROT_WRITE)
  251.         {
  252.             printf(" VM_PROT_WRITE");
  253.         }
  254.        
  255.         if (Info.protection & VM_PROT_EXECUTE)
  256.         {
  257.             printf(" VM_PROT_EXECUTE");
  258.         }
  259.        
  260.         printf("\n");
  261.        
  262.         return -1;
  263.     }
  264.    
  265.     return 0;
  266. }
  267.  
  268. int ReadBytes(vm_map_t RemoteTask, mach_vm_address_t Address, mach_vm_address_t Store, const size_t Size, size_t *ReadSize)
  269. {
  270.     /*
  271.      This much like InjectBytes is a rather redundant process, it should really only be used when unsure of the current access rights.
  272.      */
  273.    
  274.     mach_vm_size_t RegionSize;
  275.     vm_region_basic_info_data_64_t Info;
  276.     mach_port_t ObjectName;
  277.     mach_msg_type_number_t Count = VM_REGION_BASIC_INFO_COUNT_64;
  278.    
  279.     mach_error_t err = mach_vm_region(RemoteTask, &(mach_vm_address_t){ Address }, &RegionSize, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&Info, &Count, &ObjectName);
  280.     if (err != KERN_SUCCESS)
  281.     {
  282.         mach_error("mach_vm_region", err);
  283.         printf("Region error: %u\n", err);
  284.         return -1;
  285.     }
  286.    
  287.    
  288.     err = mach_vm_protect(RemoteTask, Address, Size, FALSE, VM_PROT_ALL);
  289.     if (err != KERN_SUCCESS)
  290.     {
  291.         mach_error("mach_vm_protect", err);
  292.         printf("Protection error: %u\n", err);
  293.         return -1;
  294.     }
  295.    
  296.    
  297.     mach_vm_size_t Read;
  298.     err = mach_vm_read_overwrite(RemoteTask, Address, Size, Store, &Read);
  299.     if (err != KERN_SUCCESS)
  300.     {
  301.         mach_error("mach_vm_read_overwrite", err);
  302.         printf("Read error: %u\n", err);
  303.         return -1;
  304.     }
  305.    
  306.     if (ReadSize) *ReadSize = Read;
  307.    
  308.    
  309.     err = mach_vm_protect(RemoteTask, Address, Size, FALSE, Info.protection);
  310.     if (err != KERN_SUCCESS)
  311.     {
  312.         mach_error("mach_vm_protect", err);
  313.         printf("Protection error: %u\n", err);
  314.        
  315.        
  316.         printf("Current protection left as VM_PROT_ALL, but was originally:");
  317.        
  318.         if (Info.protection & VM_PROT_READ)
  319.         {
  320.             printf(" VM_PROT_READ");
  321.         }
  322.        
  323.         if (Info.protection & VM_PROT_WRITE)
  324.         {
  325.             printf(" VM_PROT_WRITE");
  326.         }
  327.        
  328.         if (Info.protection & VM_PROT_EXECUTE)
  329.         {
  330.             printf(" VM_PROT_EXECUTE");
  331.         }
  332.        
  333.         printf("\n");
  334.        
  335.         return -1;
  336.     }
  337.    
  338.     return 0;
  339. }
  340.  
  341. int IsProc64(vm_map_t Task, _Bool * const Is64)
  342. {
  343.     task_dyld_info_data_t DyldInfo;
  344.     mach_error_t err = task_info(Task, TASK_DYLD_INFO, (task_info_t)&DyldInfo, &(mach_msg_type_number_t){ TASK_DYLD_INFO_COUNT });
  345.    
  346.     if (err != KERN_SUCCESS)
  347.     {
  348.         mach_error("task_info", err);
  349.         printf("Task info error: %u\n", err);
  350.         return -1;
  351.     }
  352.    
  353.     if (!DyldInfo.all_image_info_addr)
  354.     {
  355.         printf("Error\n");
  356.         return -1;
  357.     }
  358.    
  359.     *Is64 = (uint64_t)DyldInfo.all_image_info_addr > UINT32_MAX; //Quick cheap hack, but as of now it should always work because of what regions are reserved for what.
  360.     return 0;
  361. }
  362.  
  363. void *Locate_dlsym(vm_map_t RemoteTask)
  364. {
  365.     void *dlsymPtr = NULL;
  366.     mach_msg_type_number_t Count = TASK_DYLD_INFO_COUNT;
  367.     task_dyld_info_data_t DyldInfo;
  368.     mach_error_t err = task_info(RemoteTask, TASK_DYLD_INFO, (task_info_t)&DyldInfo, &Count);
  369.    
  370.     if (err != KERN_SUCCESS)
  371.     {
  372.         mach_error("task_info", err);
  373.         printf("Task info error: %u\n", err);
  374.         return NULL;
  375.     }
  376.    
  377.     if (!DyldInfo.all_image_info_addr)
  378.     {
  379.         printf("Error\n");
  380.         return NULL;
  381.     }
  382.    
  383.    
  384.    
  385.     mach_vm_size_t ReadSize;
  386.     union {
  387.         struct dyld_all_image_infos32 infos32;
  388.         struct dyld_all_image_infos64 infos64;
  389.     } ImageInfos;
  390.    
  391.     size_t ImageInfosSize = DyldInfo.all_image_info_size;
  392.     if (sizeof(ImageInfos) < ImageInfosSize) ImageInfosSize = sizeof(ImageInfos); //Later version being used. If needing new elements add them.
  393.    
  394.     err = mach_vm_read_overwrite(RemoteTask, DyldInfo.all_image_info_addr, ImageInfosSize, (mach_vm_address_t)&ImageInfos, &ReadSize);
  395.    
  396.     if (err != KERN_SUCCESS)
  397.     {
  398.         mach_error("mach_vm_read_overwrite", err);
  399.         printf("Read error: %u\n", err);
  400.         return NULL;
  401.     }
  402.    
  403.     _Bool Is64 = (uint64_t)DyldInfo.all_image_info_addr > UINT32_MAX; //Quick cheap hack, but as of now it should always work because of what regions are reserved for what.
  404.     mach_vm_address_t DyldImageLoadAddress = (mach_vm_address_t)(Is64? ImageInfos.infos64.dyldImageLoadAddress : ImageInfos.infos32.dyldImageLoadAddress);
  405.    
  406.    
  407.     struct mach_header DyldHeader;
  408.     err = mach_vm_read_overwrite(RemoteTask, DyldImageLoadAddress, sizeof(DyldHeader), (mach_vm_address_t)&DyldHeader, &ReadSize);
  409.    
  410.     if (err != KERN_SUCCESS)
  411.     {
  412.         mach_error("mach_vm_read_overwrite", err);
  413.         printf("Read error: %u\n", err);
  414.         return NULL;
  415.     }
  416.    
  417.    
  418.     void *LoadCommands = malloc(DyldHeader.sizeofcmds);
  419.     if (!LoadCommands)
  420.     {
  421.         printf("Could not allocate memory to copy libdyld.dylib's load commands\n");
  422.         return NULL;
  423.     }
  424.    
  425.    
  426.     size_t MachHeaderSize = (DyldHeader.magic == MH_MAGIC_64 ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
  427.    
  428.     err = mach_vm_read_overwrite(RemoteTask, DyldImageLoadAddress + MachHeaderSize, DyldHeader.sizeofcmds, (mach_vm_address_t)LoadCommands, &ReadSize);
  429.    
  430.     if (err != KERN_SUCCESS)
  431.     {
  432.         mach_error("mach_vm_read_overwrite", err);
  433.         printf("Read error: %u\n", err);
  434.         free(LoadCommands);
  435.         return NULL;
  436.     }
  437.    
  438.    
  439.     ptrdiff_t CommandSize = 0;
  440.     for (uint32_t Loop2 = 0; Loop2 < DyldHeader.ncmds; Loop2++)
  441.     {
  442.         const uint32_t cmd = ((struct load_command*)(LoadCommands + CommandSize))->cmd;
  443.         if ((Is64 = (cmd == LC_SEGMENT_64)) || (cmd == LC_SEGMENT))
  444.         {
  445.             const void *DataSections;
  446.             uint32_t NSects;
  447.             const char *Segname;
  448.             size_t SectionSize, SectionMember_sectname, SectionMember_size, SectionMember_addr;
  449.             uint64_t Cap;
  450.            
  451.             if (Is64)
  452.             {
  453.                 const struct segment_command_64* const Segment = (struct segment_command_64*)(LoadCommands + CommandSize);
  454.                 Segname = Segment->segname;
  455.                 NSects = Segment->nsects;
  456.                 DataSections = (struct section_64*)(LoadCommands + CommandSize + sizeof(struct segment_command_64));
  457.                 SectionSize = sizeof(struct section_64);
  458.                 SectionMember_sectname = offsetof(struct section_64, sectname); //Not needed (nor would it be changed anytime in the near future, since it would break things), but will be used for clarity.
  459.                 SectionMember_size = offsetof(struct section_64, size);
  460.                 SectionMember_addr = offsetof(struct section_64, addr);
  461.                
  462.                 Cap = UINT64_MAX;
  463.             }
  464.            
  465.             else
  466.             {
  467.                 const struct segment_command* const Segment = (struct segment_command*)(LoadCommands + CommandSize);
  468.                 Segname = Segment->segname;
  469.                 NSects = Segment->nsects;
  470.                 DataSections = (struct section*)(LoadCommands + CommandSize + sizeof(struct segment_command));
  471.                 SectionSize = sizeof(struct section);
  472.                 SectionMember_sectname = offsetof(struct section, sectname);
  473.                 SectionMember_size = offsetof(struct section, size);
  474.                 SectionMember_addr = offsetof(struct section, addr);
  475.                
  476.                 Cap = UINT32_MAX;
  477.             }
  478.            
  479.            
  480.             if (!strcmp("__DATA", Segname))
  481.             {
  482.                 for (uint32_t Loop3 = 0; Loop3 < NSects; Loop3++)
  483.                 {
  484.                     const void *TempDataSection = DataSections + (Loop3 * SectionSize);
  485.                     if (!strcmp("__const", (char*)(TempDataSection + SectionMember_sectname))) //__DATA,__const contains the dyld_func table
  486.                     {
  487.                         void * const DyldFuncs = malloc(*(uint64_t*)(TempDataSection + SectionMember_size) & Cap);
  488.                         if (!DyldFuncs)
  489.                         {
  490.                             printf("Could not allocate memory to copy __dyld__dyld_funcs\n");
  491.                             free(LoadCommands);
  492.                             return NULL;
  493.                         }
  494.                        
  495.                        
  496.                         /*
  497.                          Account for relocation, since the header contains fixed offsets.
  498.                          
  499.                          e.g.
  500.                          
  501.                          fixed
  502.                          all_image_info_addr: 0x7fff5fc36d10
  503.                          dyldImageLoadAddress: 0x7fff5fc00000
  504.                          __DATA,__const: 0x7fff5fc35900
  505.                          
  506.                          
  507.                          not-fixed
  508.                          all_image_info_addr: 0x7fff6bdeed10
  509.                          dyldImageLoadAddress: 0x7fff6bdb8000
  510.                          __DATA,__const: 0x7fff5fc35900
  511.                          
  512.                          Correct address in the second one would be 0x7fff6bded900
  513.                          
  514.                          Or for 32 bit
  515.                          fixed
  516.                          dyldImageLoadAddress: 0x8fe00000
  517.                          __DATA,__const: 0x8fe336c0
  518.                          
  519.                          
  520.                          not-fixed
  521.                          dyldImageLoadAddress: 0x8fe84000
  522.                          __DATA,__const: 0x8fe336c0
  523.                          
  524.                          Correct address in the second one would be 0x8feb76c0
  525.                          */
  526.                        
  527.                         ptrdiff_t Base = DyldImageLoadAddress;
  528.                         Base += (*(uint64_t*)(TempDataSection + SectionMember_addr) /*& Cap*/) & 0xfffff;
  529.                        
  530.                         err = mach_vm_read_overwrite(RemoteTask, (mach_vm_address_t)Base, *(uint64_t*)(TempDataSection + SectionMember_size) & Cap, (mach_vm_address_t)DyldFuncs, &ReadSize);
  531.                        
  532.                         if (err != KERN_SUCCESS)
  533.                         {  
  534.                             mach_error("mach_vm_read_overwrite", err);
  535.                             printf("Read error: %u\n", err);
  536.                             free(LoadCommands);
  537.                             free(DyldFuncs);
  538.                             return NULL;
  539.                         }
  540.                        
  541.                        
  542.                         //If the table's location ever changes, instead should scan through it until coming up to table.
  543.                         const size_t RowSize = Is64? sizeof(uint64_t) * 2 : sizeof(uint32_t) * 2, TableElement_addr = Is64? sizeof(uint64_t) : sizeof(uint32_t);
  544.                         for (uint64_t Loop4 = 0, DyldFuncCount = (*(uint64_t*)(TempDataSection + SectionMember_size) & Cap) / RowSize; Loop4 < DyldFuncCount; Loop4++)
  545.                         {
  546.                             void *TempRow = DyldFuncs + (Loop4 * RowSize);
  547.                             mach_vm_address_t Name = *(uint64_t*)(TempRow) & Cap;
  548.                             if (!Name) break;
  549.                            
  550.                             char FunctionName[512]; //Just an estimate. If it's ever a problem, change it.
  551.                             /*
  552.                              A better way to go about it may be to copy the __TEXT,__cstring section and adjust the pointers
  553.                              appropriately.
  554.                              */
  555.                             err = mach_vm_read_overwrite(RemoteTask, (mach_vm_address_t)Name, sizeof(FunctionName), (mach_vm_address_t)FunctionName, &ReadSize);
  556.                            
  557.                             if (err != KERN_SUCCESS)
  558.                             {
  559.                                 mach_error("mach_vm_read_overwrite", err);
  560.                                 printf("Read error: %u\n", err);
  561.                                 break;
  562.                             }
  563.                            
  564.                             if (!strcmp("__dyld_dlsym", FunctionName))
  565.                             {
  566.                                 dlsymPtr = (void*)(*(uint64_t*)(TempRow + TableElement_addr) & Cap);
  567.                                 break;
  568.                             }
  569.                         }
  570.                        
  571.                         free(DyldFuncs);
  572.                         break;
  573.                     }
  574.                 }
  575.                
  576.                 break;
  577.             }
  578.         }
  579.        
  580.         CommandSize += ((struct load_command*)(LoadCommands + CommandSize))->cmdsize;
  581.     }
  582.    
  583.     free(LoadCommands);
  584.    
  585.     return dlsymPtr;
  586. }
  587.  
  588. int SuspendTaskWithNoExecutionInRange(vm_map_t RemoteTask, mach_vm_address_t Start, mach_vm_address_t End)
  589. {
  590.     _Bool Is64;
  591.     if (IsProc64(RemoteTask, &Is64) == -1) return -1;
  592.    
  593.     mach_error_t err = task_suspend(RemoteTask);
  594.    
  595.     if (err != KERN_SUCCESS)
  596.     {
  597.         mach_error("task_suspend", err);
  598.         printf("Task suspension error: %u\n", err);
  599.         return -1;
  600.     }
  601.    
  602.    
  603.     thread_act_port_array_t Threads;
  604.     mach_msg_type_number_t Count;
  605.     err = task_threads(RemoteTask, &Threads, &Count);
  606.    
  607.     if (err != KERN_SUCCESS)
  608.     {
  609.         mach_error("task_threads", err);
  610.         printf("Task thread query error: %u\n", err);
  611.        
  612.         err = task_resume(RemoteTask);
  613.        
  614.         if (err != KERN_SUCCESS)
  615.         {
  616.             mach_error("task_resume", err);
  617.             printf("Task continuation error: %u\n", err);
  618.         }
  619.        
  620.         return -1;
  621.     }
  622.    
  623.    
  624.    
  625.     if (Is64)
  626.     {
  627.         x86_thread_state64_t ThreadState;
  628.        
  629.         for (size_t Loop = 0; Loop < Count; Loop++)
  630.         {
  631.             mach_msg_type_number_t ThreadStateCount = x86_THREAD_STATE64_COUNT;
  632.             err = thread_get_state(Threads[Loop], x86_THREAD_STATE64, (thread_state_t)&ThreadState, &ThreadStateCount);
  633.            
  634.             if (err != KERN_SUCCESS)
  635.             {
  636.                 mach_error("thread_get_state", err);
  637.                 printf("Thread state query error: %u\n", err);
  638.                
  639.                 err = task_resume(RemoteTask);
  640.                
  641.                 if (err != KERN_SUCCESS)
  642.                 {
  643.                     mach_error("task_resume", err);
  644.                     printf("Task continuation error: %u\n", err);
  645.                 }
  646.                
  647.                 return -1;
  648.             }
  649.            
  650.            
  651.             if ((ThreadState.__rip >= Start) && (ThreadState.__rip <= End))
  652.             {
  653.                 err = task_resume(RemoteTask);
  654.                
  655.                 if (err != KERN_SUCCESS)
  656.                 {
  657.                     mach_error("task_resume", err);
  658.                     printf("Task continuation error: %u\n", err);
  659.                     return -1;
  660.                 }
  661.                
  662.                 [NSThread sleepForTimeInterval: 0.25];
  663.                 //Hope infinite recursions will not occur (obviously producing a crash)
  664.                 return SuspendTaskWithNoExecutionInRange(RemoteTask, Start, End);
  665.             }
  666.         }
  667.     }
  668.    
  669.     else
  670.     {
  671.         x86_thread_state32_t ThreadState;
  672.        
  673.         for (size_t Loop = 0; Loop < Count; Loop++)
  674.         {
  675.             mach_msg_type_number_t ThreadStateCount = x86_THREAD_STATE32_COUNT;
  676.             err = thread_get_state(Threads[Loop], x86_THREAD_STATE32, (thread_state_t)&ThreadState, &ThreadStateCount);
  677.            
  678.             if (err != KERN_SUCCESS)
  679.             {
  680.                 mach_error("thread_get_state", err);
  681.                 printf("Thread state query error: %u\n", err);
  682.                
  683.                 err = task_resume(RemoteTask);
  684.                
  685.                 if (err != KERN_SUCCESS)
  686.                 {
  687.                     mach_error("task_resume", err);
  688.                     printf("Task continuation error: %u\n", err);
  689.                 }
  690.                
  691.                 return -1;
  692.             }
  693.            
  694.            
  695.             if ((ThreadState.__eip >= Start) && (ThreadState.__eip <= End))
  696.             {
  697.                 err = task_resume(RemoteTask);
  698.                
  699.                 if (err != KERN_SUCCESS)
  700.                 {
  701.                     mach_error("task_resume", err);
  702.                     printf("Task continuation error: %u\n", err);
  703.                     return -1;
  704.                 }
  705.                
  706.                 [NSThread sleepForTimeInterval: 0.25];
  707.                 return SuspendTaskWithNoExecutionInRange(RemoteTask, Start, End);
  708.             }
  709.         }
  710.     }
  711.    
  712.    
  713.     return 0;
  714. }
  715.  
  716. int RelocateAddressInTask(vm_map_t Task, mach_vm_address_t * const Address, const char * const Image)
  717. {
  718.     mach_msg_type_number_t Count = TASK_DYLD_INFO_COUNT;
  719.     task_dyld_info_data_t DyldInfo;
  720.     mach_error_t err = task_info(Task, TASK_DYLD_INFO, (task_info_t)&DyldInfo, &Count);
  721.    
  722.     if (err != KERN_SUCCESS)
  723.     {
  724.         mach_error("task_info", err);
  725.         printf("Task info error: %u\n", err);
  726.         return -1;
  727.     }
  728.    
  729.     if (!DyldInfo.all_image_info_addr)
  730.     {
  731.         printf("Error\n");
  732.         return -1;
  733.     }
  734.    
  735.    
  736.    
  737.     mach_vm_size_t ReadSize;
  738.     union {
  739.         struct dyld_all_image_infos32 infos32;
  740.         struct dyld_all_image_infos64 infos64;
  741.     } ImageInfos;
  742.    
  743.     size_t ImageInfosSize = DyldInfo.all_image_info_size;
  744.     if (sizeof(ImageInfos) < ImageInfosSize) ImageInfosSize = sizeof(ImageInfos); //Later version being used. If needing new elements add them.
  745.    
  746.     err = mach_vm_read_overwrite(Task, DyldInfo.all_image_info_addr, ImageInfosSize, (mach_vm_address_t)&ImageInfos, &ReadSize);
  747.    
  748.     if (err != KERN_SUCCESS)
  749.     {
  750.         mach_error("mach_vm_read_overwrite", err);
  751.         printf("Read error: %u\n", err);
  752.         return -1;
  753.     }
  754.    
  755.     _Bool Is64 = (uint64_t)DyldInfo.all_image_info_addr > UINT32_MAX; //Quick cheap hack, but as of now it should always work because of what regions are reserved for what.
  756.    
  757.    
  758.     uint32_t InfoArrayCount;
  759.     uint64_t InfoArray, ImageInfoSize;
  760.    
  761.     if (Is64)
  762.     {
  763.         InfoArrayCount = ImageInfos.infos64.infoArrayCount;
  764.         InfoArray = ImageInfos.infos64.infoArray;
  765.         ImageInfoSize = sizeof(struct dyld_image_info64);
  766.     }
  767.    
  768.     else
  769.     {
  770.         InfoArrayCount = ImageInfos.infos32.infoArrayCount;
  771.         InfoArray = ImageInfos.infos32.infoArray;
  772.         ImageInfoSize = sizeof(struct dyld_image_info32);
  773.     }
  774.    
  775.    
  776.     union {
  777.         struct dyld_image_info64 info64;
  778.         struct dyld_image_info32 info32;
  779.     } ImageInfo;
  780.    
  781.     if (Image)
  782.     {
  783.         const _Bool FullPath = (strchr(Image, '/') != NULL);
  784.        
  785.         _Bool Match = FALSE;
  786.         for (uint32_t Loop = 0; (Loop < InfoArrayCount) && (!Match); Loop++)
  787.         {
  788.             err = mach_vm_read_overwrite(Task, (mach_vm_address_t)(InfoArray + (ImageInfoSize * Loop)), ImageInfoSize, (mach_vm_address_t)&ImageInfo, &ReadSize);
  789.            
  790.             if (err != KERN_SUCCESS)
  791.             {
  792.                 mach_error("mach_vm_read_overwrite", err);
  793.                 printf("Read error: %u\n", err);
  794.                 return -1;
  795.             }
  796.            
  797.            
  798.             char FilePath[PATH_MAX];
  799.             err = mach_vm_read_overwrite(Task, (mach_vm_address_t)(Is64? ImageInfo.info64.imageFilePath : ImageInfo.info32.imageFilePath), sizeof(FilePath), (mach_vm_address_t)FilePath, &ReadSize);
  800.            
  801.             if (err != KERN_SUCCESS)
  802.             {
  803.                 mach_error("mach_vm_read_overwrite", err);
  804.                 printf("Read error: %u\n", err);
  805.                 return -1;
  806.             }
  807.            
  808.            
  809.             if (FullPath)
  810.             {
  811.                 Match = !strcmp(Image, FilePath);
  812.             }
  813.            
  814.             else
  815.             {
  816.                 NSAutoreleasePool *Pool = [NSAutoreleasePool new];
  817.                 Match = !strcmp(Image, [[[[NSString stringWithUTF8String: FilePath] pathComponents] lastObject] UTF8String]);
  818.                 [Pool drain];
  819.             }
  820.         }
  821.        
  822.         if (!Match)
  823.         {
  824.             printf("Could not find image: %s\n", Image);
  825.             return -1;
  826.         }
  827.     }
  828.    
  829.     else
  830.     {
  831.         //Assumes first element in info array is the app itself.
  832.         err = mach_vm_read_overwrite(Task, (mach_vm_address_t)InfoArray, ImageInfoSize, (mach_vm_address_t)&ImageInfo, &ReadSize);
  833.        
  834.         if (err != KERN_SUCCESS)
  835.         {
  836.             mach_error("mach_vm_read_overwrite", err);
  837.             printf("Read error: %u\n", err);
  838.             return -1;
  839.         }
  840.     }
  841.    
  842.    
  843.     *Address = (*Address & 0xfffffff) + (mach_vm_address_t)(Is64? ImageInfo.info64.imageLoadAddress : ImageInfo.info32.imageLoadAddress);
  844.    
  845.     return 0;
  846. }
  847.  
  848. int AddressFromString(vm_map_t Task, const char *String, mach_vm_address_t * const Address)
  849. {
  850.     errno = 0;
  851.    
  852.     if (!strncmp(String, "rel", 3))
  853.     {
  854.         *Address = strtol(&String[4], NULL, 16);
  855.         if (errno)
  856.         {
  857.             //Don't bother checking just report invalid number
  858.             printf("Invalid address, value must be hexadecimal: %s\n", String);
  859.             return -1;
  860.         }
  861.        
  862.         char *ImageFile = NULL;
  863.         char File[PATH_MAX];
  864.         size_t Image = strcspn(&String[4], ",:- ") + 5;
  865.         if (String[Image - 1])
  866.         {
  867.             size_t Length = strlen(&String[Image]) - (String[3] != ' ');
  868.             strncpy(File, &String[Image], Length);
  869.             File[Length] = 0;
  870.             ImageFile = File;
  871.         }
  872.        
  873.         return RelocateAddressInTask(Task, Address, ImageFile);
  874.     }
  875.    
  876.     else
  877.     {
  878.         *Address = strtol(String, NULL, 16);
  879.         if (errno)
  880.         {
  881.             //Don't bother checking just report invalid number
  882.             printf("Invalid address, value must be hexadecimal: %s\n", String);
  883.             return -1;
  884.         }
  885.     }
  886.    
  887.     return 0;
  888. }
  889.  
  890. int Command_Bytes(vm_map_t TaskSelf, vm_map_t RemoteTask, const char **Args, const int Argc)
  891. {
  892.     mach_vm_address_t Address;
  893.     if (AddressFromString(RemoteTask, Args[1], &Address) == -1) return EXIT_FAILURE;
  894.    
  895.     const size_t TotalLength = strlen(Args[0]);
  896.     if (TotalLength & 1)
  897.     {
  898.         printf("Bytes must be multiples of 2\n");
  899.         return EXIT_FAILURE;
  900.     }
  901.    
  902.     mach_vm_address_t Bytes;
  903.     const size_t Length = TotalLength / 2;
  904.    
  905.     mach_error_t err = mach_vm_allocate(TaskSelf, &Bytes, Length, VM_FLAGS_ANYWHERE);
  906.     if (err != KERN_SUCCESS)
  907.     {
  908.         mach_error("mach_vm_allocate", err);
  909.         printf("Allocation error: %u\n", err);
  910.         return EXIT_FAILURE;
  911.     }
  912.    
  913.     int RetVal;
  914.     if (GetBytesFromString(Args[0], TotalLength, (uint8_t*)Bytes) == -1)
  915.     {
  916.         RetVal = EXIT_FAILURE;
  917.     }
  918.    
  919.     else
  920.     {
  921.         RetVal = InjectBytes(RemoteTask, Address, Bytes, Length) == -1 ? EXIT_FAILURE : EXIT_SUCCESS;
  922.     }
  923.    
  924.    
  925.    
  926.     mach_vm_deallocate(TaskSelf, Bytes, Length);
  927.     /*
  928.      Just assume this passes, otherwise just let OS clean up. So still return
  929.      success, as the injection operation has succeeded.
  930.      */
  931.    
  932.     return RetVal;
  933. }
  934.  
  935. int Command_String(vm_map_t TaskSelf, vm_map_t RemoteTask, const char **Args, const int Argc)
  936. {
  937.     mach_vm_address_t Address;
  938.     if (AddressFromString(RemoteTask, Args[1], &Address) == -1) return EXIT_FAILURE;
  939.    
  940.     size_t Length = strlen(Args[0]);
  941.     mach_vm_address_t Bytes;
  942.     mach_error_t err = mach_vm_allocate(TaskSelf, &Bytes, Length, VM_FLAGS_ANYWHERE);
  943.     if (err != KERN_SUCCESS)
  944.     {
  945.         mach_error("mach_vm_allocate", err);
  946.         printf("Allocation error: %u\n", err);
  947.         return EXIT_FAILURE;
  948.     }
  949.    
  950.     size_t Size = 0;
  951.     const char *String = Args[0];
  952.     for (size_t Loop = 0; Loop < Length; Loop++)
  953.     {
  954.         if (Loop + 3 < Length)
  955.         {
  956.             if ((String[Loop] == '\\') && (String[Loop + 1] == 'x'))
  957.             {
  958.                 const unsigned char Val = strtol((char[3]){ String[Loop + 2], String[Loop + 3], 0 }, NULL, 16);
  959.                
  960.                 if (!errno)
  961.                 {
  962.                     ((unsigned char*)Bytes)[Size++] = Val;
  963.                     Loop += 3;
  964.                 }
  965.                
  966.                 else ((unsigned char*)Bytes)[Size++] = String[Loop];
  967.                 continue;
  968.             }
  969.            
  970.         }
  971.        
  972.         ((unsigned char*)Bytes)[Size++] = String[Loop];
  973.     }
  974.    
  975.    
  976.     int RetVal = InjectBytes(RemoteTask, Address, Bytes, Size) == -1 ? EXIT_FAILURE : EXIT_SUCCESS;
  977.    
  978.     mach_vm_deallocate(TaskSelf, Bytes, Length);
  979.     /*
  980.      Just assume this passes, otherwise just let OS clean up. So still return
  981.      success, as the injection operation has succeeded.
  982.      */
  983.    
  984.     return RetVal;
  985. }
  986.  
  987. int Command_Codecave(vm_map_t TaskSelf, vm_map_t RemoteTask, const char **Args, const int Argc)
  988. {
  989.     mach_vm_address_t Address;
  990.     if (AddressFromString(RemoteTask, Args[0], &Address) == -1) return EXIT_FAILURE;
  991.    
  992.     _Bool Is64;
  993.     if (IsProc64(RemoteTask, &Is64) == -1)
  994.     {
  995.         return EXIT_FAILURE;
  996.     }
  997.    
  998.     size_t Size = Is64? 14 : 5, ArgIndex = 1;
  999.     if (!strcmp("-s", Args[ArgIndex]))
  1000.     {
  1001.         size_t TempSize = strtol(Args[++ArgIndex], NULL, 10);
  1002.         if (errno)
  1003.         {
  1004.             printf("Invalid size, value must be decimal: %s\n", Args[2]);
  1005.             return EXIT_FAILURE;
  1006.         }
  1007.        
  1008.         if (TempSize > Size) Size = TempSize;
  1009.         ArgIndex++;
  1010.     }
  1011.    
  1012.    
  1013.     void *dlsymPtr = Locate_dlsym(RemoteTask);
  1014.     if (!dlsymPtr)
  1015.     {
  1016.         printf("Could not located dlsym\n"); //Later change it to prompt user
  1017.         return EXIT_FAILURE;
  1018.     }
  1019.    
  1020.    
  1021.     size_t ReadSize = 0;
  1022.     void *OriginalCode = malloc(Size);
  1023.     if (OriginalCode)
  1024.     {
  1025.         if (ReadBytes(RemoteTask, Address, (mach_vm_address_t)OriginalCode, Size, &ReadSize) == -1)
  1026.         {
  1027.             free(OriginalCode);
  1028.             OriginalCode = NULL;
  1029.         }
  1030.     }
  1031.    
  1032.    
  1033.    
  1034.     size_t CodeSize = 0;
  1035.     uint8_t *Data = NULL;
  1036.     int RetVal = EXIT_SUCCESS;
  1037.     for (size_t Loop = ArgIndex; Loop < Argc; Loop++)
  1038.     {
  1039.         if (!strcmp("-oc", Args[Loop]))
  1040.         {
  1041.             const size_t NewCodeSize = CodeSize + ReadSize;
  1042.             uint8_t *TempData = realloc(Data, sizeof(uint8_t) * NewCodeSize);
  1043.            
  1044.             if (!TempData)
  1045.             {
  1046.                 printf("Allocation error\n");
  1047.                 RetVal = EXIT_FAILURE;
  1048.                 break;
  1049.             }
  1050.            
  1051.             Data = TempData;
  1052.             memcpy(Data + CodeSize, OriginalCode, ReadSize);
  1053.             CodeSize = NewCodeSize;
  1054.         }
  1055.        
  1056.         else if (!strncmp("rel", Args[Loop], 3))
  1057.         {
  1058.             mach_vm_address_t RelAddr;
  1059.             if (AddressFromString(RemoteTask, Args[Loop], &RelAddr) == -1)
  1060.             {
  1061.                 RetVal = EXIT_FAILURE;
  1062.                 break;
  1063.             }
  1064.            
  1065.             if (Is64)
  1066.             {
  1067.                 const size_t NewCodeSize = CodeSize + sizeof(uint64_t);
  1068.                 uint8_t *TempData = realloc(Data, sizeof(uint8_t) * NewCodeSize);
  1069.                
  1070.                 if (!TempData)
  1071.                 {
  1072.                     printf("Allocation error\n");
  1073.                     RetVal = EXIT_FAILURE;
  1074.                     break;
  1075.                 }
  1076.                
  1077.                 Data = TempData;
  1078.                 memcpy(Data + CodeSize, &RelAddr, sizeof(uint64_t));
  1079.                 CodeSize = NewCodeSize;
  1080.             }
  1081.            
  1082.             else
  1083.             {
  1084.                 const size_t NewCodeSize = CodeSize + sizeof(uint32_t);
  1085.                 uint8_t *TempData = realloc(Data, sizeof(uint8_t) * NewCodeSize);
  1086.                
  1087.                 if (!TempData)
  1088.                 {
  1089.                     printf("Allocation error\n");
  1090.                     RetVal = EXIT_FAILURE;
  1091.                     break;
  1092.                 }
  1093.                
  1094.                 Data = TempData;
  1095.                 memcpy(Data + CodeSize, (&(uint32_t){ (uint32_t)RelAddr }), sizeof(uint32_t));
  1096.                 CodeSize = NewCodeSize;
  1097.             }
  1098.         }
  1099.        
  1100.         else
  1101.         {
  1102.             const size_t TotalLength = strlen(Args[Loop]);
  1103.             if (TotalLength & 1)
  1104.             {
  1105.                 printf("Bytes must be multiples of 2\n");
  1106.                 RetVal = EXIT_FAILURE;
  1107.                 break;
  1108.             }
  1109.            
  1110.             const size_t NewCodeSize = CodeSize + (TotalLength / 2);
  1111.             uint8_t *TempData = realloc(Data, sizeof(uint8_t) * NewCodeSize);
  1112.            
  1113.             if (!TempData)
  1114.             {
  1115.                 printf("Allocation error\n");
  1116.                 RetVal = EXIT_FAILURE;
  1117.                 break;
  1118.             }
  1119.            
  1120.             Data = TempData;
  1121.            
  1122.             if (GetBytesFromString(Args[Loop], TotalLength, Data + CodeSize) == -1)
  1123.             {
  1124.                 RetVal = EXIT_FAILURE;
  1125.                 break;
  1126.             }
  1127.            
  1128.             CodeSize = NewCodeSize;
  1129.         }
  1130.     }
  1131.    
  1132.     if (OriginalCode) free(OriginalCode);
  1133.    
  1134.     if ((RetVal == EXIT_SUCCESS) && (Data))
  1135.     {
  1136.         const size_t Length = CodeSize + (Is64? sizeof(uint64_t) + 14 : sizeof(uint32_t) + 5);
  1137.         mach_vm_address_t Bytes = 0;
  1138.         mach_error_t err = mach_vm_allocate(TaskSelf, &Bytes, Length, VM_FLAGS_ANYWHERE);
  1139.         if (err != KERN_SUCCESS)
  1140.         {
  1141.             mach_error("mach_vm_allocate", err);
  1142.             printf("Allocation error: %u\n", err);
  1143.             free(Data);
  1144.             return EXIT_FAILURE;
  1145.         }
  1146.        
  1147.        
  1148.         memcpy((void*)Bytes, Data, CodeSize);
  1149.         free(Data);
  1150.        
  1151.         mach_vm_address_t Codecave;
  1152.         err = mach_vm_allocate(RemoteTask, &Codecave, Length, VM_FLAGS_ANYWHERE);
  1153.         if (err != KERN_SUCCESS)
  1154.         {
  1155.             mach_error("mach_vm_allocate", err);
  1156.             printf("Allocation error: %u\n", err);
  1157.             return EXIT_FAILURE;
  1158.         }
  1159.        
  1160.        
  1161.         if (Is64)
  1162.         {
  1163.             /*
  1164.              jmpq *(%rip)
  1165.              .quad address
  1166.              */
  1167.             uint8_t Return[14] = { 0xff, 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  1168.             *(uint64_t*)&Return[6] = Address + 14;
  1169.             memcpy((void*)(Bytes + CodeSize), Return, sizeof(Return));
  1170.             memcpy((void*)(Bytes + CodeSize + sizeof(Return)), &dlsymPtr, sizeof(uint64_t));
  1171.         }
  1172.        
  1173.         else
  1174.         {
  1175.             uint8_t Return[5] = { 0xe9 }; //jmp rel32
  1176.             *(uint32_t*)&Return[1] = (uint32_t)(Address - (Codecave + CodeSize));
  1177.             memcpy((void*)(Bytes + CodeSize), Return, sizeof(Return));
  1178.             memcpy((void*)(Bytes + CodeSize + sizeof(Return)), &(uint32_t){ (uint32_t)dlsymPtr }, sizeof(uint32_t));
  1179.         }
  1180.        
  1181.        
  1182.         err = mach_vm_protect(RemoteTask, Codecave, Length, FALSE, VM_PROT_ALL);
  1183.         if (err != KERN_SUCCESS)
  1184.         {
  1185.             mach_error("mach_vm_protect", err);
  1186.             printf("Protection error: %u\n", err);
  1187.             return EXIT_FAILURE;
  1188.         }
  1189.        
  1190.         err = mach_vm_write(RemoteTask, Codecave, Bytes, (mach_msg_type_number_t)Length);
  1191.         if (err != KERN_SUCCESS)
  1192.         {
  1193.             mach_error("mach_vm_write", err);
  1194.             printf("Writing error: %u\n", err);
  1195.             return EXIT_FAILURE;
  1196.         }
  1197.        
  1198.         mach_vm_deallocate(TaskSelf, Bytes, Length);
  1199.         printf("Injected to: %p\n", (void*)Codecave);
  1200.        
  1201.        
  1202.        
  1203.        
  1204.         if (!SuspendTaskWithNoExecutionInRange(RemoteTask, Address, Address + Size))
  1205.         {
  1206.             mach_vm_address_t Jump;
  1207.             err = mach_vm_allocate(TaskSelf, &Jump, Size, VM_FLAGS_ANYWHERE);
  1208.             if (err != KERN_SUCCESS)
  1209.             {
  1210.                 mach_error("mach_vm_allocate", err);
  1211.                 printf("Allocation error: %u\n", err);
  1212.                 RetVal = EXIT_FAILURE;
  1213.             }
  1214.            
  1215.             else
  1216.             {
  1217.                 memset((void*)Jump, 0x90 /*nops*/, Size);
  1218.                
  1219.                 if (Is64)
  1220.                 {
  1221.                     uint8_t Patch[14] = { 0xff, 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  1222.                     *(uint64_t*)&Patch[6] = Codecave;
  1223.                     memcpy((void*)Jump, Patch, 14);
  1224.                 }
  1225.                
  1226.                 else
  1227.                 {
  1228.                     *(uint8_t*)Jump = 0xe9;
  1229.                     *(uint32_t*)(Jump + 1) = (uint32_t)(Codecave - (Address + 5));
  1230.                 }
  1231.                
  1232.                 if (InjectBytes(RemoteTask, Address, Jump, Size) == -1) RetVal = EXIT_FAILURE;
  1233.                
  1234.                 mach_vm_deallocate(TaskSelf, Jump, Size);
  1235.             }
  1236.            
  1237.             err = task_resume(RemoteTask);
  1238.            
  1239.             if (err != KERN_SUCCESS)
  1240.             {
  1241.                 mach_error("task_resume", err);
  1242.                 printf("Task continuation error: %u\n", err);
  1243.                 RetVal = EXIT_FAILURE;
  1244.             }
  1245.         }
  1246.        
  1247.         else
  1248.         {
  1249.             RetVal = EXIT_FAILURE;
  1250.         }
  1251.     }
  1252.    
  1253.     else if (Data)
  1254.     {
  1255.         free(Data);
  1256.     }
  1257.    
  1258.    
  1259.     return RetVal;
  1260. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement