unsigned char *Model::process_binary(const unsigned char *input, int size, int *size_out) { unsigned char *output; CopyCollector collector(&output, size_out); process_binary(input, size, &collector); return output; }
int main(int argc, char **argv, char **envp) { handle_t *handle; char *token = NULL, **args; int ac, i, status, ret; pid_t pid; long ptraceOpts; char *argv0; if (argc < 3) usage(); if (argv[1][0] != '-') usage(); /* * XXX handle is huge because of branch_site (Which is a massive array) * so we must use heap. In the future move branch_site from array to * list or tree for fast lookup. */ handle = (handle_t *)heapAlloc(sizeof(handle_t)); memset((void *)handle, 0, sizeof(handle_t)); memset((void *)&opts, 0, sizeof(opts)); if (argv[1][0] != '-') usage(); if (argv[1][1] != 'b' && argv[1][1] != 'p') { for (token = (argv[1] + 1); *token != '\0'; token++) { switch(*token) { case 'v': opts.verbose++; break; case 's': opts.strings++; break; case 'c': opts.cflow++; break; case 'e': opts.elfdata++; break; case 'f': opts.ehframe++; break; case 't': opts.threads++; break; case 'd': opts.debug++; break; default: printf("Unknown option: '%c'\n", *token); usage(); } } if (argc < 4) usage(); if (argv[2][0] != '-') usage(); if (argv[2][1] == 'b') handle->path = strdup(argv[3]); else if (argv[2][1] == 'p') handle->pid = atoi(argv[3]); else usage(); argv0 = handle->path ? xstrdup(argv[3]) : get_path(handle->pid); ac = parse_sub_args(&argv[4], argc - 4, &handle->args, argv0); } else { if (argv[1][0] != '-') usage(); if (argv[1][1] == 'b') handle->path = strdup(argv[2]); else if (argv[1][1] == 'p') handle->pid = atoi(argv[2]); else usage(); argv0 = handle->path ? xstrdup(argv[2]) : get_path(handle->pid); ac = parse_sub_args(&argv[3], argc - 3, &handle->args, argv0); } switch(__ELF_NATIVE_CLASS) { case 32: opts.arch = 32; break; case 64: opts.arch = 64; break; default: fprintf(stderr, "[!] Unsupported architecture: %d\n", __ELF_NATIVE_CLASS); exit(0); } handle->arch = opts.arch; pid = handle->pid; if (pid) { if (opts.verbose) printf("[+] Attaching to pid: %d\n", pid); opts.attach++; handle->path = get_path(handle->pid); } if (!validate_em_type(handle->path)) { printf("[!] ELF Architecture is set to %d, the target %s is not the same architecture\n", opts.arch, handle->path); exit(-1); } /* * process_binary() will create the mapping of branch instructions * and layout of the executable, so that we can instrument it before * execution. */ if ((ret = process_binary(handle) < 0)) { fprintf(stderr, "process_binary() failed on [%s]\n", handle->path); exit(-1); } if (!opts.attach) { if ((pid = fork()) < 0) { perror("fork"); exit(-1); } if (pid == 0) { if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1) { perror("PTRACE_TRACEME"); exit(-1); } ptraceOpts = PTRACE_O_TRACECLONE|PTRACE_O_TRACEFORK|PTRACE_O_TRACEEXEC|PTRACE_O_TRACEEXIT|PTRACE_O_EXITKILL; ptrace(PTRACE_SETOPTIONS, 0, 0, ptraceOpts); execve(handle->path, handle->args, envp); exit(0); } wait(&status); handle->pid = pid; if (opts.debug) printf("[+] Calling instrument_process()\n"); instrument_process(handle); if (opts.debug) printf("[+] Calling examine_process()\n"); examine_process(handle); goto done; } printf("Attaching to %d\n", handle->pid); if (ptrace(PTRACE_ATTACH, handle->pid, NULL, NULL) == -1) { perror("PTRACE_ATTACH"); exit(-1); } wait(&status); // waitpid(handle->pid, &status, WUNTRACED); instrument_process(handle); examine_process(handle); for (i = 0; i < ac; i++) printf("arg[%d]: %s\n", i, handle->args[i]); done: free(handle); exit(0); }