1 #include <mach-o/loader.h> 2 #include <mach/machine.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <uuid/uuid.h> 6 7 int main() { 8 int size_of_load_cmds = 9 sizeof(struct segment_command_64) + sizeof(struct uuid_command); 10 uint8_t *macho_buf = 11 (uint8_t *)malloc(sizeof(struct mach_header_64) + size_of_load_cmds); 12 uint8_t *p = macho_buf; 13 struct mach_header_64 mh; 14 mh.magic = MH_MAGIC_64; 15 mh.cputype = CPU_TYPE_ARM64; 16 mh.cpusubtype = 0; 17 mh.filetype = MH_EXECUTE; 18 mh.ncmds = 2; 19 mh.sizeofcmds = size_of_load_cmds; 20 mh.flags = MH_NOUNDEFS | MH_DYLDLINK | MH_TWOLEVEL | MH_PIE; 21 22 memcpy(p, &mh, sizeof(mh)); 23 p += sizeof(mh); 24 25 struct segment_command_64 seg; 26 seg.cmd = LC_SEGMENT_64; 27 seg.cmdsize = sizeof(seg); 28 strcpy(seg.segname, "__TEXT"); 29 seg.vmaddr = 0x5000; 30 seg.vmsize = 0x1000; 31 seg.fileoff = 0; 32 seg.filesize = 0; 33 seg.maxprot = 0; 34 seg.initprot = 0; 35 seg.nsects = 0; 36 seg.flags = 0; 37 38 memcpy(p, &seg, sizeof(seg)); 39 p += sizeof(seg); 40 41 struct uuid_command uuid; 42 uuid.cmd = LC_UUID; 43 uuid.cmdsize = sizeof(uuid); 44 uuid_clear(uuid.uuid); 45 uuid_parse("1b4e28ba-2fa1-11d2-883f-b9a761bde3fb", uuid.uuid); 46 47 memcpy(p, &uuid, sizeof(uuid)); 48 p += sizeof(uuid); 49 50 // If this needs to be debugged, the memory buffer can be written 51 // to a file with 52 // (lldb) mem rea -b -o /tmp/t -c `p - macho_buf` macho_buf 53 // (lldb) platform shell otool -hlv /tmp/t 54 // to verify that it is well formed. 55 56 // And inside lldb, it should be inspectable via 57 // (lldb) script print(lldb.frame.locals["macho_buf"][0].GetValueAsUnsigned()) 58 // 105553162403968 59 // (lldb) process plugin packet send 60 // 'jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[105553162403968]}]' 61 62 return 0; // break here 63 } 64