static void help_cmd_info(const char *cmd) { int cmd_id; if((cmd_id = command_search(cmd)) == -1) { R_UTILS_ERR("%s isn't a valid command, see the help.", cmd); } else if(cmd_id == -2) { R_UTILS_ERR("Too much commands match %s, be more precise.", cmd); } command_help(cmd_id); exit(EXIT_FAILURE); }
/* Main function of disassemble command */ void dis_cmd(int argc, char **argv) { int stop_next_sym = 0; addr_t sym; r_binfmt_s bin; r_disa_s dis; dis_options_parse(argc, argv); r_binfmt_load(&bin, dis_options_filename, dis_options_arch); /* Init disassembler */ if(!r_disa_init(&dis, bin.arch)) R_UTILS_ERR("Can't init disassembler"); if(!r_disa_set_flavor(&dis, dis_options_flavor)) R_UTILS_ERR("Can't set flavor"); /* Try to find symbol, if option is set */ if(dis_options_sym != NULL) { if((sym = r_binfmt_get_sym_by_name(&bin, dis_options_sym)) == R_BINFMT_BAD_ADDR) R_UTILS_ERR("Symbol <%s> not found", dis_options_sym); dis_options_address = sym; stop_next_sym = 1; } /* Can't disassemble offset + address at the same time */ if(dis_options_offset != R_BINFMT_BAD_OFFSET && dis_options_address != R_BINFMT_BAD_ADDR) R_UTILS_ERR("You must specify offset or address, not twice !"); /* First, try disassemble at offset */ if(dis_options_offset != R_BINFMT_BAD_OFFSET) { dis_offset(&dis, &bin, dis_options_offset, dis_options_len); } else { /* Now check if address if specified */ if(dis_options_address != R_BINFMT_BAD_ADDR) { dis_address(&dis, &bin, dis_options_address, dis_options_len, stop_next_sym); /* If not, try to disassemble starting at entry point */ } else if(bin.entry != 0) { dis_address(&dis, &bin, bin.entry, dis_options_len, stop_next_sym); /* Entry point is bad...Start at beginning of the file */ } else { dis_offset(&dis, &bin, 0, dis_options_len); } } r_binfmt_free(&bin); r_disa_close(&dis); }
/* Disassemble binary in range [offset, offset+len] */ void dis_offset(r_disa_s *dis, r_binfmt_s *bin, u64 offset, u64 len) { r_disa_instr_t *instr; u64 length; u64 off; /* Check offset */ if(offset >= bin->mapped_size) R_UTILS_ERR("Offset out of range"); /* Len is out of range, adjust it */ if(len == 0 || len > bin->mapped_size - offset) len = bin->mapped_size - offset; length = 0; while(length < len) { off = offset + length; r_disa_code(dis, bin->mapped+off, bin->mapped_size-off, off, 1); instr = r_disa_next_instr(dis); /* We have disassembled an instruction */ if(instr != NULL) { R_UTILS_PRINT_GREEN_BG_BLACK(dis_options_color, " %.16"PRIx64" ", off); R_UTILS_PRINT_YELLOW_BG_BLACK(dis_options_color, "%-8s ", instr->mnemonic); R_UTILS_PRINT_RED_BG_BLACK(dis_options_color, "%s\n", instr->op_str); length += instr->size; } else { /* Disassembler failed : print BAD instruction */ R_UTILS_PRINT_GREEN_BG_BLACK(dis_options_color, " %.16"PRIx64" ", off); R_UTILS_PRINT_YELLOW_BG_BLACK(dis_options_color, "BAD\n"); length += 1; } } }
static void patch_address(r_binfmt_s *bin, addr_t addr, void *bytes, u64 len) { r_binfmt_mem_s *m; u64 off; for(m = bin->mlist->head; m; m = m->next) { if(addr >= m->addr && addr <= m->addr+m->length) { if(addr+len >= m->addr+m->length) { R_UTILS_ERR("Too many bytes to copy !"); } off = addr - m->addr; memcpy(m->start+off, bytes, len); return; } } R_UTILS_ERR("Address not found..."); }
static void command_help(int cmd_id) { if(command_list[cmd_id].help != NULL) { command_list[cmd_id].help(); } else { R_UTILS_ERR("No help available for command %s.", command_list[cmd_id].name); } exit(EXIT_FAILURE); }
static void heap_dump_lib(char *filename) { FILE *f; if((f = fopen(filename, "w")) == NULL) R_UTILS_ERR("Can't open %s", filename); fwrite(global_libheap, 1, sizeof(global_libheap), f); fclose(f); }
static void patch_address(r_binfmt_s *bin, addr_t addr, void *bytes, u64 len) { r_binfmt_segment_s *seg; u64 off; size_t i, num; num = r_utils_list_size(&bin->segments); for(i = 0; i < num; i++) { seg = r_utils_list_access(&bin->segments, i); if(addr >= seg->addr && addr <= seg->addr+seg->length) { if(addr+len >= seg->addr+seg->length) { R_UTILS_ERR("Too many bytes to copy !"); } off = addr - seg->addr; memcpy(seg->start+off, bytes, len); return; } } R_UTILS_ERR("Address not found..."); }
void command_execute(const char *cmd, int argc, char **argv) { int cmd_id; assert(cmd != NULL && argv != NULL); assert(argc > 0); if((cmd_id = command_search(cmd)) == -1) { R_UTILS_ERR("%s isn't a valid command, see the help.", cmd); } else if(cmd_id == -2) { printf("Too much commands match \"%s\"\n", cmd); printf("Did you mean : "); command_print_matchs(cmd); printf(" ?!\n"); exit(EXIT_FAILURE); } command_list[cmd_id].cmd(argc, argv); }
void search_cmd(int argc, char **argv) { r_binfmt_s bin; search_options_parse(argc, argv); r_binfmt_load(&bin, search_options_filename, search_options_arch); switch(search_options_mode) { case SEARCH_MODE_STRING_ALL: search_print_all_string_in_bin(&bin); break; case SEARCH_MODE_STRING_SPLIT: search_print_split_string_in_bin(&bin, search_options_string); break; case SEARCH_MODE_STRING: search_print_string_in_bin(&bin, search_options_string); break; case SEARCH_MODE_BYTE: search_print_numeric_in_bin(&bin, search_options_numeric, 1); break; case SEARCH_MODE_WORD: search_print_numeric_in_bin(&bin, search_options_numeric, 2); break; case SEARCH_MODE_DWORD: search_print_numeric_in_bin(&bin, search_options_numeric, 4); break; case SEARCH_MODE_QWORD: search_print_numeric_in_bin(&bin, search_options_numeric, 8); break; default: search_help(); R_UTILS_ERR("I don't know what do you want searching !"); } }
/* Parse command line options */ void patch_options_parse(int argc, char **argv) { int opt; const struct option opts[] = { {"address", required_argument, NULL, 'a'}, {"bytes", required_argument, NULL, 'b'}, {"filename", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"offset", required_argument, NULL, 'o'}, {"output", required_argument, NULL, 'O'}, {"raw", no_argument, NULL, 'r'}, {NULL, 0, NULL, 0 } }; while((opt = getopt_long(argc, argv, "a:b:f:ho:O:r", opts, NULL)) != -1) { switch(opt) { case 'a': patch_options_address = strtoull(optarg, NULL, 0); break; case 'b': patch_options_bytes = r_utils_bytes_unhexlify(optarg); break; case 'f': patch_options_filename = optarg; break; case 'h': patch_help(); exit(EXIT_FAILURE); break; case 'o': patch_options_offset = strtoull(optarg, NULL, 0); break; case 'O': patch_options_output = optarg; break; case 'r': patch_options_arch = R_BINFMT_ARCH_X86; break; default: patch_help(); exit(EXIT_FAILURE); } } if(optind < argc) { patch_options_filename = argv[optind]; } if(patch_options_address == R_BINFMT_BAD_ADDR && patch_options_offset == R_BINFMT_BAD_ADDR) R_UTILS_ERR("Where I patch ? Random location ?! Use --offset or --address options !"); if(patch_options_address != R_BINFMT_BAD_ADDR && patch_options_offset != R_BINFMT_BAD_ADDR) R_UTILS_ERR("I need an offset OR an address, not twice !"); if(patch_options_bytes == NULL) R_UTILS_ERR("I patch what ? use --bytes option !"); }
static void patch_offset(r_binfmt_s *bin, addr_t off, void *bytes, u64 len) { if(off >= bin->mapped_size || off+len > bin->mapped_size) { R_UTILS_ERR("Offset out of range !"); } memcpy(bin->mapped+off, bytes, len); }
/* Parse command line options */ void dis_options_parse(int argc, char **argv) { int opt; const struct option opts[] = { {"address", required_argument, NULL, 'a'}, {"arch", required_argument, NULL, 'A'}, {"sym", required_argument, NULL, 's'}, {"flavor", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"len", required_argument, NULL, 'l'}, {"no-color", no_argument, NULL, 'N'}, {"offset", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0 } }; while((opt = getopt_long(argc, argv, "a:A:s:f:hl:No:", opts, NULL)) != -1) { switch(opt) { case 'a': dis_options_address = strtoull(optarg, NULL, 0); break; case 's': dis_options_sym = optarg; break; case 'A': dis_options_arch = r_binfmt_string_to_arch(optarg); if(dis_options_arch == R_BINFMT_ARCH_UNDEF) R_UTILS_ERR("%s: bad architecture.", optarg); break; case 'f': dis_options_flavor = r_disa_string_to_flavor(optarg); if(dis_options_flavor == R_DISA_FLAVOR_UNDEF) R_UTILS_ERR("%s: bad flavor.", optarg); break; case 'h': dis_help(); exit(EXIT_FAILURE); break; case 'l': dis_options_len = strtoull(optarg, NULL, 0); break; case 'N': dis_options_color = 0; break; case 'o': dis_options_offset = strtoull(optarg, NULL, 0); break; default: dis_help(); exit(EXIT_FAILURE); } } if(optind < argc) { dis_options_filename = argv[optind]; } }
/* Parse command line options */ void search_options_parse(int argc, char **argv) { int opt; const struct option opts[] = { {"all-string", optional_argument, NULL, 'a'}, {"byte", required_argument, NULL, 'b'}, {"bad", required_argument, NULL, 'B'}, {"dword", required_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"no-color", no_argument, NULL, 'n'}, {"qword", required_argument, NULL, 'q'}, {"raw", no_argument, NULL, 'r'}, {"split-string", required_argument, NULL, 's'}, {"string", required_argument, NULL, 'S'}, {"word", required_argument, NULL, 'w'}, {NULL, 0, NULL, 0 } }; while((opt = getopt_long(argc, argv, "a::b:B:d:hnq:rs:S:w:", opts, NULL)) != -1) { switch(opt) { case 'a': search_options_mode = SEARCH_MODE_STRING_ALL; if(optarg) search_options_strlen = strtoull(optarg, NULL, 0); if(search_options_strlen <= 0) R_UTILS_ERR("Bad argument for \"-a\" option ! Must be an integer > 0, e.g : -a5"); break; case 'b': search_options_mode = SEARCH_MODE_BYTE; search_options_numeric = strtoull(optarg, NULL, 0); break; case 'B': search_options_bad = r_utils_bytes_unhexlify(optarg); break; case 'd': search_options_mode = SEARCH_MODE_DWORD; search_options_numeric = strtoull(optarg, NULL, 0); break; case 'h': search_help(); exit(EXIT_FAILURE); break; case 'n': search_options_color = 0; break; case 'q': search_options_mode = SEARCH_MODE_QWORD; search_options_numeric = strtoull(optarg, NULL, 0); break; case 'r': search_options_arch = R_BINFMT_ARCH_X86; break; case 's': search_options_mode = SEARCH_MODE_STRING_SPLIT; search_options_string = r_utils_bytes_unhexlify(optarg); break; case 'S': search_options_mode = SEARCH_MODE_STRING; search_options_string = r_utils_bytes_unhexlify(optarg); break; case 'w': search_options_mode = SEARCH_MODE_WORD; search_options_numeric = strtoull(optarg, NULL, 0); break; default: search_help(); exit(EXIT_FAILURE); } } if(optind < argc) { search_options_filename = argv[optind]; } }