Guest User

Untitled

a guest
Feb 22nd, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.81 KB | None | 0 0
  1. #include <inttypes.h>
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <sys/stat.h>
  8. #include <sys/mman.h>
  9. #include <err.h>
  10. #include <string.h>
  11. #include <mach-o/arch.h>
  12. #include <mach-o/loader.h>
  13. #include <mach-o/nlist.h>
  14.  
  15. typedef struct macho_input {
  16. const void *data;
  17. size_t length;
  18. } macho_input_t;
  19.  
  20. struct _dyld {
  21. const struct dyld_info_command *dyld_cmd;
  22. char *name;
  23. };
  24.  
  25. /// Verify that the given range is within bounds
  26. static const void *macho_read (macho_input_t *input, const void *address, size_t length) {
  27. if ((((uint8_t *) address) - ((uint8_t *) input->data)) + length > input->length) {
  28. warnx("Short read parsing Mach-O input");
  29. return NULL;
  30. }
  31. return address;
  32. }
  33.  
  34. // Verify that address + offset + length is within bounds.
  35. static const void *macho_offset (macho_input_t *input, const void *address, size_t offset, size_t length) {
  36. void *result = ((uint8_t *) address) + offset;
  37. return macho_read(input, result, length);
  38. }
  39.  
  40. uintptr_t get_dyld_count(macho_input_t *input, const struct mach_header_64 *header, const struct load_command *cmd) {
  41. uintptr_t ndyld = 0;
  42. for (uintptr_t i = 0; i < header->ncmds; i++) {
  43. uint32_t cmdsize = cmd->cmdsize;
  44. cmd = macho_read(input, cmd, cmdsize);
  45.  
  46. switch(cmd->cmd) {
  47. case LC_ID_DYLIB:
  48. case LC_LOAD_WEAK_DYLIB:
  49. case LC_REEXPORT_DYLIB:
  50. case LC_LOAD_DYLIB: {
  51. ndyld++;
  52. }
  53. }
  54.  
  55. cmd = macho_offset(input, cmd, cmdsize, sizeof(struct load_command));
  56. if (cmd == NULL)
  57. break;
  58. }
  59. return ndyld;
  60. }
  61.  
  62. uint32_t mask_opcode(uint32_t op) {
  63. return (op - (op & 0x0f));
  64. }
  65.  
  66. uintptr_t read_uleb128(uintptr_t i, unsigned char *sym) {
  67. do {
  68. i++;
  69. } while(sym[i-1] & 0x80);
  70. i++;
  71. return i;
  72. }
  73.  
  74. uintptr_t get_dyld_index(unsigned char *sym) {
  75. uintptr_t dyld_index = 0;
  76.  
  77. for(uintptr_t i = 0; i < strlen((char *)sym); i++) {
  78. if(mask_opcode(sym[i]) == 0x40) {
  79. if(mask_opcode(sym[i-1]) == 0x90) {
  80. dyld_index = 0;
  81. break;
  82. }
  83. if(sym[i-2] == 0x20) {
  84. dyld_index = sym[i-1];
  85. break;
  86. }
  87. if(mask_opcode(sym[i-1]) == 0x10) {
  88. dyld_index = sym[i-1] - mask_opcode(sym[i-1]);
  89. break;
  90. }
  91. }
  92. }
  93. return dyld_index;
  94. }
  95.  
  96. uintptr_t get_sym_name_start(unsigned char *sym) {
  97. uintptr_t i;
  98. for(i = 0; i < strlen((char*)sym); i++) {
  99. switch(sym[i]) {
  100. case 0x80: {
  101. i = read_uleb128(i, sym);
  102. break;
  103. }
  104. case 0xA0: {
  105. i = read_uleb128(i, sym);
  106. break;
  107. }
  108. }
  109. if(sym[i] == 0x40 || sym[i] == 0x41) {
  110. i++;
  111. break;
  112. }
  113. }
  114. return i;
  115. }
  116.  
  117. void get_sym_name(unsigned char *sym) {
  118. uintptr_t start_index = get_sym_name_start(sym);
  119. if(start_index) {
  120. int q = 0;
  121. for(uintptr_t i = start_index; i < strlen((char*)sym); i++) {
  122. sym[q] = sym[i];
  123. q++;
  124. }
  125. sym[q] = '';
  126. }
  127. }
  128.  
  129. void free_dyld_array(struct _dyld *dylds) {
  130. size_t arr_size = sizeof(dylds)/sizeof(dylds[0]);
  131. for(int i = 0; i < arr_size; i++) {
  132. free((void *)dylds[i].dyld_cmd);
  133. free(dylds[i].name);
  134. }
  135. free(dylds);
  136. }
  137.  
  138. void free_dyld_cmd(void **dyld_cmd) {
  139. if(dyld_cmd != NULL) {
  140. free(*dyld_cmd);
  141. *dyld_cmd = NULL;
  142. }
  143. }
  144.  
  145. /* Parse a Mach-O header */
  146. void parse_macho (macho_input_t *input) {
  147. //Grab the entire header
  148. const struct mach_header_64 *header = macho_read(input, input->data, sizeof(*header));
  149. //Grab first load command
  150. const struct load_command *cmd = macho_offset(input, header, sizeof(*header), sizeof(struct load_command));
  151.  
  152. //Init the array to store the dyld related load commands
  153. uintptr_t ndyld = get_dyld_count(input, header, cmd);
  154. if(!ndyld) {
  155. warnx("This binary does not seem to use any external frameworks/dylibs");
  156. }
  157.  
  158. struct _dyld *dylds = malloc(sizeof(struct _dyld) * ndyld);
  159. uintptr_t ncmds = header->ncmds;
  160.  
  161. const struct dyld_info_command *dyld_cmd = malloc(sizeof(struct dyld_info_command));
  162. uint32_t bind_off = 0;
  163. uint32_t bind_size = 0;
  164. const void *name_ptr = NULL;
  165. uint32_t placehold = 0;
  166.  
  167. // Iterate over the load commands
  168. for (uintptr_t i = 0; i < ncmds; i++) {
  169. uint32_t cmdsize = cmd->cmdsize;
  170. cmd = macho_read(input, cmd, cmdsize);
  171. uint32_t cmd_type = cmd->cmd;
  172. switch (cmd_type) {
  173. case LC_DYLD_INFO_ONLY: {
  174. dyld_cmd = (const struct dyld_info_command *)cmd;
  175. bind_off = dyld_cmd->bind_off;
  176. bind_size = dyld_cmd->bind_size;
  177. break;
  178. }
  179. case LC_ID_DYLIB:
  180. case LC_LOAD_WEAK_DYLIB:
  181. case LC_REEXPORT_DYLIB:
  182. case LC_LOAD_DYLIB: {
  183. dylds[placehold].dyld_cmd = (const struct dyld_info_command *)cmd;
  184. size_t name_len = cmdsize - sizeof(struct dylib_command);
  185. name_ptr = macho_offset(input, dylds[placehold].dyld_cmd, sizeof(struct dylib_command), name_len);
  186. dylds[placehold].name = malloc(name_len);
  187. memcpy(dylds[placehold].name, name_ptr, name_len);
  188. placehold++;
  189. break;
  190. }
  191. }
  192. // Load next command
  193. cmd = macho_offset(input, cmd, cmdsize, sizeof(struct load_command));
  194. }
  195.  
  196. const void *pos_pointer = macho_offset(input, input->data, bind_off, 100);
  197. uintptr_t dyld_hold = 0;
  198. uint32_t offset_counter = 0;
  199. unsigned char *sym = malloc(1024);
  200. uintptr_t i = 1;
  201.  
  202. while(offset_counter < (bind_size - 4)) {
  203. memcpy(sym, pos_pointer, 1024);
  204. pos_pointer+= (strlen((char*)sym) + 1);
  205. offset_counter += (strlen((char*)sym) + 1);
  206. uintptr_t dyld_index = get_dyld_index(sym);
  207.  
  208. if(dyld_index) {
  209. dyld_hold = dyld_index;
  210. } else {
  211. dyld_index = dyld_hold;
  212. }
  213.  
  214. get_sym_name(sym);
  215. if(strlen((char *)sym)) {
  216. printf("%lu : %s : %sn", i, sym, dylds[dyld_index].name);
  217. }
  218.  
  219. i++;
  220. }
  221.  
  222. free(sym);
  223. free_dyld_array(dylds);
  224. }
  225.  
  226. int main (int argc, char *argv[]) {
  227. const char *path = argv[1];
  228. int fd = open(path, O_RDONLY);
  229.  
  230. struct stat stbuf;
  231. stat(path, &stbuf);
  232.  
  233. void *data = mmap(NULL, stbuf.st_size, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
  234.  
  235. macho_input_t input_file;
  236. input_file.data = data;
  237. input_file.length = stbuf.st_size;
  238.  
  239. parse_macho(&input_file);
  240.  
  241. munmap(data, stbuf.st_size);
  242. close(fd);
  243. printf("Donen");
  244. exit(0);
  245. }
Add Comment
Please, Sign In to add comment