/* Display the header of a list */ int revm_list_display(list_t *list, char *name) { char logbuf[BUFSIZ]; char *type; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (!list) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid NULL parameter", -1); type = revm_ascii_ltype(list); snprintf(logbuf, sizeof(logbuf), " + %-40s\t ElemType: %-15s ElemNbr: %u \n", name, type, list->elmnbr); revm_output(logbuf); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * The real main function * @ingroup evarista */ int eva_main(int ac, char **av) { /* Interface tweak */ eva_setup_quit_msg(); eva_setup_prompt(); revm_setup(ac, av, 0, 0); if (world.state.revm_mode != REVM_STATE_CMDLINE) eva_banner_print(av[1]); revm_config(EVARISTA_CONFIG); setup_local_cmdhash(); revm_output(" [*] Type help for regular commands \n\n"); revm_run(ac, av); return (0); }
int cmd_kmem_disasm() { int ret, len; eresi_Addr addr; char *new_buff; revmlist_t *actual; char buff[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); ret = len = 0; addr = 0; actual = world.curjob->curcmd->disasm + 0; if (actual) { kernsh_addrlen(actual, &addr, &len); XALLOC(__FILE__, __FUNCTION__, __LINE__, new_buff, len, -1); memset(new_buff, '\0', len); ret = elfsh_readmema(libkernshworld.root, addr, new_buff, len); if (ret == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Impossible to read mem", -1); memset(buff, '\0', sizeof(buff)); snprintf(buff, sizeof(buff), "Disassembling kernel memory %s %s strlen(%s)\n\n", revm_colorstr("@"), revm_coloraddress(XFMT, (eresi_Addr) addr), revm_colornumber("%u", len)); revm_output(buff); kernsh_disasm(new_buff, len, addr); XFREE(__FILE__, __FUNCTION__, __LINE__, new_buff); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Display the content of all hash tables that match the regex */ static int revm_list_display_regx(char *regx) { regex_t rx; int keynbr; char **keys; int index; int match; char buf[50]; char *lastmatch; list_t *cur; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (regcomp(&rx, regx, REG_EXTENDED) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to compute regex", -1); /* Look for matching tables */ keys = hash_get_keys(hash_lists, &keynbr); for (lastmatch = NULL, match = index = 0; index < keynbr; index++) { if (!regexec(&rx, keys[index], 0, 0, 0)) { cur = hash_get(hash_lists, keys[index]); revm_list_display(cur, keys[index]); match++; lastmatch = keys[index]; } } /* Print the content of the table if we had a unique match */ if (match == 1) revm_list_display_content(lastmatch); else { snprintf(buf, sizeof(buf), "\n [*] Matched %u list%c \n\n", match, (match > 1 ? 's' : ' ')); revm_output(buf); } hash_free_keys(keys); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Translate in destination type */ int cmd_into() { PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (!world.curjob->recur[world.curjob->curscope].rwrt.matched) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); if (world.curjob->recur[world.curjob->curscope].rwrt.replaced) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot transform a second time", -1); if (!world.curjob->recur[world.curjob->curscope].rwrt.matchexpr) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot transform outside a rewrite", -1); if (revm_case_transform(world.curjob->recur[world.curjob->curscope].rwrt.matchexpr, strdup(world.curjob->curcmd->param[0])) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to transform expression", -1); world.curjob->recur[world.curjob->curscope].rwrt.replaced = 1; if (!world.state.revm_quiet) revm_output(" [*] Expression transformed succesfully \n\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Display the content of all hash tables that match the regex * @param tableregx Regular expression matching table names * @param elemregx Regular expression matching element keys */ static int revm_table_display_regx2(char *tableregx, char *elemregx) { regex_t rx, ex; int keynbr, keynbr2; char **keys, **keys2; int index, index2; hash_t *cur; u_int match; char logbuf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (regcomp(&rx, tableregx, REG_EXTENDED) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to compute regex", -1); if (regcomp(&ex, elemregx, REG_EXTENDED) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to compute regex", -1); /* Look for matching tables */ keys = hash_get_keys(hash_hash, &keynbr); for (match = index = 0; index < keynbr; index++) if (!regexec(&rx, keys[index], 0, 0, 0)) { cur = hash_get(hash_hash, keys[index]); //fprintf(stderr, "MATCHED TABLE %s of %u elems \n", cur->name, cur->elmnbr); keys2 = hash_get_keys(cur, &keynbr2); for (index2 = 0; index2 < keynbr2; index2++) if (!regexec(&ex, keys2[index2], 0, 0, 0)) { match++; revm_table_display_element(cur, keys2[index2], 1); } } hash_free_keys(keys); hash_free_keys(keys2); snprintf(logbuf, sizeof(logbuf), "\n [*] Matched %u entries in all tables\n\n", match); revm_output(logbuf); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Display the content of all hash tables that match the regex * @param tableregx Regular expression matching table names * @param elemregx Regular expression matching element keys */ static int revm_list_display_regx2(char *tableregx, char *elemregx) { regex_t rx, ex; int keynbr; char **keys; int index; list_t *cur; listent_t *curent; u_int match; char logbuf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (regcomp(&rx, tableregx, REG_EXTENDED) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to compute regex", -1); if (regcomp(&ex, elemregx, REG_EXTENDED) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to compute regex", -1); /* Look for matching tables */ keys = hash_get_keys(hash_lists, &keynbr); for (match = index = 0; index < keynbr; index++) if (!regexec(&rx, keys[index], 0, 0, 0)) { cur = hash_get(hash_lists, keys[index]); for (curent = cur->head; curent; curent = curent->next) if (!regexec(&ex, curent->key, 0, 0, 0)) { match++; revm_list_display_element(cur, curent->key, 1); } } hash_free_keys(keys); snprintf(logbuf, sizeof(logbuf), "\n [*] Matched %u entries in all lists \n\n", match); revm_output(logbuf); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Print the etrace banner * @ingroup evarista */ void eva_banner_print() { char logbuf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); snprintf(logbuf, BUFSIZ - 1, "\n\n\t The %s %s (%s) .::. \n\n %s", EVARISTA_NAME, REVM_VERSION, #if defined(ERESI32) "32 bits built", #elif defined(ERESI64) "64 bits built", #else "Unknown built", #endif "\t .::. This software is under the General Public License V.2 \n" "\t .::. Please visit http://www.gnu.org \n\n"); revm_output(logbuf); PROFILER_OUT(__FILE__, __FUNCTION__, __LINE__); }
/** * Precise a general weak bounded regex for all options */ int cmd_glregx() { char *str; char logbuf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); str = strdup(world.curjob->curcmd->param[0]); if (regcomp(&world.state.revm_regx, str, REG_EXTENDED) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to compute regex", -1); world.state.revm_use_regx = 1; if (world.state.revm_sregx) XFREE(__FILE__, __FUNCTION__, __LINE__,world.state.revm_sregx); world.state.revm_sregx = str; if (!world.state.revm_quiet) { snprintf(logbuf, BUFSIZ - 1, " [*] Changed global regex to %s \n\n", str); revm_output(logbuf); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Read the sorting parameter */ int cmd_sort() { char logbuf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (world.curjob->curcmd->param[0][0] != ELFSH_SORT_BY_ADDR && world.curjob->curcmd->param[0][0] != ELFSH_SORT_BY_SIZE) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid sorting type", -1); if (!world.state.revm_quiet) { snprintf(logbuf, BUFSIZ - 1, " [*] Switched to %s sorting\n\n", (world.curjob->curcmd->param[0][0] == ELFSH_SORT_BY_ADDR ? "ADDR" : "SIZE")); revm_output(logbuf); } world.state.sort = world.curjob->curcmd->param[0]; PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Display the dynamic symbol table */ int cmd_dynsym() { elfshsect_t *sct; elfsh_Sym *dynsym; regex_t *tmp; int num; char logbuf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); dynsym = elfsh_get_dynsymtab(world.curjob->curfile, &num); if (dynsym == NULL) RET(-1); else { sct = elfsh_get_section_by_name(world.curjob->curfile, ELFSH_SECTION_NAME_ALTDYNSYM, NULL, NULL, &num); if (!sct) sct = elfsh_get_section_by_type(world.curjob->curfile, SHT_DYNSYM, 0, NULL, NULL, &num); if (!sct) RET(-1); num = num / sizeof(elfsh_Sym); } snprintf(logbuf, BUFSIZ - 1, " [DYNAMIC SYMBOL TABLE]\n [Object %s]\n [Section %s]\n", world.curjob->curfile->name, sct->name); revm_output(logbuf); FIRSTREGX(tmp); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, ds(world.curjob->curfile, sct, num, tmp, elfsh_get_dynsymbol_name)); }
int cmd_kmem_info() { char buff[BUFSIZ]; char *data; int val; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); data = (char *)config_get_data(LIBKERNSH_CONFIG_DEVICE); snprintf(buff, sizeof(buff), "DEVICE : %s\n", data); revm_output(buff); data = (char *)config_get_data(LIBKERNSH_CONFIG_MODE); snprintf(buff, sizeof(buff), "FLAGS : %s\n", data); revm_output(buff); switch(libkernshworld.mem) { case LIBKERNSH_MEM_MODE : snprintf(buff, sizeof(buff), "MODE : DYNAMIC\n"); break; case LIBKERNSH_STATIC_MODE : snprintf(buff, sizeof(buff), "MODE : STATIC\n"); break; } revm_output(buff); data = (char *)config_get_data(LIBKERNSH_CONFIG_SYSTEMMAP); snprintf(buff, sizeof(buff), "SYSTEMMAP : %s\n", data); revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_MMAP); switch (val) { case 0 : snprintf(buff, sizeof(buff), "MMAP : OFF\n"); break; case 1 : snprintf(buff, sizeof(buff), "MMAP : ON\n"); break; } revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_MMAP_SIZE); snprintf(buff, sizeof(buff), "MMAP_SIZE : 0x%lx\n", (unsigned long)val); revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_KERNEL_START); snprintf(buff, sizeof(buff), "KERNEL_START : 0x%lx\n", (unsigned long)val); revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_KERNEL_END); snprintf(buff, sizeof(buff), "KERNEL_END : 0x%lx\n", (unsigned long)val); revm_output(buff); data = (char *)config_get_data(LIBKERNSH_CONFIG_KERNEL); snprintf(buff, sizeof(buff), "KERNEL : %s\n", data); revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_USE_KERNEL); switch (val) { case 0 : snprintf(buff, sizeof(buff), "USE_KERNEL : OFF\n"); break; case 1 : snprintf(buff, sizeof(buff), "USE_KERNEL : ON\n"); break; } revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_ALLOC); switch (val) { case 0 : snprintf(buff, sizeof(buff), "ALLOC : CONTIGUOUS\n"); break; case 1 : snprintf(buff, sizeof(buff), "ALLOC : NO CONTIGUOUS\n"); break; } revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_NB_SYSCALLS); snprintf(buff, sizeof(buff), "NB_SYSCALLS : %d\n", val); revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_NIL_SYSCALL); snprintf(buff, sizeof(buff), "NIL_SYSCALL : %d\n", val); revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_USEVM); switch (val) { case 0 : snprintf(buff, sizeof(buff), "USE_VM : OFF\n"); break; case 1 : snprintf(buff, sizeof(buff), "USE_VM : ON\n"); break; } revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_VIRTM); switch (val) { case LIBKERNSH_KERNEL_MODE: snprintf(buff, sizeof(buff), "VIRTM : PROC\n"); break; case LIBKERNSH_USER_MODE : snprintf(buff, sizeof(buff), "VIRTM : SYSCALL\n"); break; } revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_VIRTM_NIL_SYSCALL); snprintf(buff, sizeof(buff), "VIRTM_NIL_SYSCALL : %d\n", val); revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_HASH); switch (val) { case LIBKERNSH_HASH_MD5: snprintf(buff, sizeof(buff), "HASH : MD5\n"); break; case LIBKERNSH_HASH_SHA1 : snprintf(buff, sizeof(buff), "HASH : SHA1\n"); break; } revm_output(buff); val = (int)config_get_data(LIBKERNSH_CONFIG_VMA); switch (val) { case LIBKERNSH_VMA_USERLAND: snprintf(buff, sizeof(buff), "VMA : USERLAND\n"); break; case LIBKERNSH_VMA_KERNELLAND : snprintf(buff, sizeof(buff), "VMA : KERNELLAND\n"); break; } revm_output(buff); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Need doxygen comment */ int cmd_workspace() { revmjob_t *job; u_int idx; u_int index; char logbuf[BUFSIZ]; char *nl; char *time; elfshobj_t *obj; char **keys; int keynbr; char **loadedkeys; int loadedkeynbr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); //printf("workspace argc %u \n", world.curjob->curcmd->argc); switch (world.curjob->curcmd->argc) { /* $ workspace */ case 0: revm_output(" .::. Workspaces .::. \n"); keys = hash_get_keys(&world.jobs, &keynbr); for (index = 0; index < keynbr; index++) { job = (revmjob_t *) hash_get(&world.jobs, keys[index]); if (revm_own_job(job)) { time = ctime(&job->ws.createtime); nl = strchr(time, '\n'); if (nl) *nl = 0x00; snprintf(logbuf, BUFSIZ - 1, " [%s] %s %c \n", keys[index], time, (job->ws.active ? '*' : ' ')); revm_output(logbuf); if (hash_size(&job->loaded)) { loadedkeys = hash_get_keys(&job->loaded, &loadedkeynbr); for (idx = 0; idx < loadedkeynbr; idx++) { obj = hash_get(&job->loaded, loadedkeys[idx]); snprintf(logbuf, BUFSIZ - 1, " \t %c %s \n", (job->curfile == obj ? '*' : ' '), obj->name); revm_output(logbuf); } } else { snprintf(logbuf, BUFSIZ - 1, " \t No files\n"); revm_output(logbuf); } } } revm_output("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); /* $ workspace name */ case 1: PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, revm_create_new_workspace(revm_get_cur_job_parameter(0))); /* Unknown command format */ default: PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Wrong arg number", -1); } }
/** * The infinite main loop of the interactive command */ int revm_loop(int argc, char **argv) { int ret; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); ret = 0; do { /* Come back to the loop if a script turns into interactive mode */ reenter: /* Fill argv from stdin if we are in interactive mode */ if ((world.state.revm_mode != REVM_STATE_CMDLINE && world.state.revm_mode != REVM_STATE_TRACER) || world.state.revm_net == 1) { if (world.state.revm_mode != REVM_STATE_SCRIPT) { if (revm_select() < 0) { fprintf(stderr,"revm_select : failed \n"); revm_exit(-1); } /* If the FIFO does not exist anymore, the server has quit, so we quit too */ if (world.state.revm_mode == REVM_STATE_EMBEDDED && (access(REVM_FIFO_S2C, F_OK) < 0 || access(REVM_FIFO_C2S, F_OK) < 0)) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); } /* Take a line, execute old command if void line */ argv = revm_input(&argc, NULL); if (world.state.revm_mode == REVM_STATE_INTERACTIVE || world.state.revm_mode == REVM_STATE_EMBEDDED || world.state.revm_mode == REVM_STATE_SCRIPT || world.state.revm_net) { if (argv == ((char **) REVM_INPUT_VOID)) continue; else if (argv == ((char **) REVM_INPUT_TRANSFERED)) continue; } /* CTRL-D -> !argv */ if (!argv) { revm_output("\n"); /* when debugging -> back to main program */ if (world.state.revm_mode == REVM_STATE_EMBEDDED) { revm_callback_handler_remove(); revm_cleanup(); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, ret); } /* if net is enable but we are not in e2dbg -> ignore */ if (world.state.revm_net) continue; /* othewise exit */ break; } } /* Fetch the current scripting command */ if (revm_parseopt(argc, argv) < 0) { if (world.state.revm_mode != REVM_STATE_CMDLINE && world.state.revm_mode != REVM_STATE_TRACER) { XFREE(__FILE__, __FUNCTION__, __LINE__, argv); if (world.state.revm_mode != REVM_STATE_INTERACTIVE && world.state.revm_mode != REVM_STATE_EMBEDDED) goto end; } else if (!world.state.revm_net) revm_exit(-1); } /* Just execute one command if we are not in script mode */ if (world.state.revm_mode != REVM_STATE_SCRIPT) { world.curjob->curcmd = world.curjob->recur[0].script; switch (revm_execmd()) { case REVM_SCRIPT_CONTINUE: //printf(" [*] e2dbg continue from revm_execmd \n"); revm_callback_handler_remove(); revm_cleanup(); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, ret); case REVM_SCRIPT_ERROR: profiler_error(); default: break; } } /* Quit parsing if necessary */ if ((!world.curjob->curcmd && world.state.revm_mode == REVM_STATE_SCRIPT)) break; } while ((world.state.revm_mode != REVM_STATE_CMDLINE && world.state.revm_mode != REVM_STATE_TRACER) || world.state.revm_net); /* If we are in scripting, execute commands list now */ if (world.state.revm_mode == REVM_STATE_SCRIPT) { fprintf(stderr, "we are in script mode from revm_loop ! \n"); world.curjob->curcmd = world.curjob->recur[0].script; ret = revm_execscript(); if (ret == REVM_SCRIPT_STOP) { XCLOSE(world.curjob->ws.io.input_fd, -1); world.curjob->ws.io.input_fd = 0; goto reenter; } else if (ret < 0) profiler_error(); } end: revm_postexec(ret); revm_callback_handler_remove(); revm_cleanup(); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (ret)); }
int cmd_kmem_write() { revmexpr_t *e1; revmexpr_t *e2; revmobj_t *o1; revmobj_t *o2; void *dat; int ret, size; eresi_Addr addr; char buff[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Sanity checks */ if (world.curjob->curcmd->param[0] == NULL || world.curjob->curcmd->param[1] == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Needs 2 parameters", -1); if (IS_VADDR(world.curjob->curcmd->param[0])) { if (sscanf(world.curjob->curcmd->param[0] + 2, AFMT, &addr) != 1) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid virtual address requested", -1); } else { e1 = revm_lookup_param(world.curjob->curcmd->param[0], 1); o1 = e1->value; switch (o1->otype->type) { case ASPECT_TYPE_LONG: case ASPECT_TYPE_CADDR: case ASPECT_TYPE_DADDR: addr = (o1->immed ? o1->immed_val.ent : o1->get_obj(o1->parent)); break; case ASPECT_TYPE_INT: addr = (o1->immed ? o1->immed_val.word : o1->get_obj(o1->parent)); break; } } e2 = revm_lookup_param(world.curjob->curcmd->param[1], 1); o2 = e2->value; /* Convert Integers into raw data */ if (o2->otype->type != ASPECT_TYPE_RAW && o2->otype->type != ASPECT_TYPE_STR) if (revm_convert_object(e2, ASPECT_TYPE_RAW) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to convert dest object to RAW", (-1)); /* Get the source buff */ dat = (o2->immed ? o2->immed_val.str : o2->otype->type == ASPECT_TYPE_STR ? o2->get_name(o2->root, o2->parent) : o2->get_data(o2->parent, o2->off, o2->sizelem)); /* Set size */ size = o2->size; if (size <= 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Source offset too big", -1); printf("WRITE @ 0x%lx %d %d %s\n", (unsigned long)addr, size, strlen(world.curjob->curcmd->param[1]), world.curjob->curcmd->param[1]); memset(buff, '\0', sizeof(buff)); snprintf(buff, sizeof(buff), "Writing into kernel memory %s %s strlen(%s)\n\n", revm_colorstr("@"), revm_coloraddress(XFMT, (eresi_Addr) addr), revm_colornumber("%u", size)); revm_output(buff); kernsh_hexdump((unsigned char *)dat, size, (unsigned int)dat); ret = elfsh_writemem(libkernshworld.root, addr, dat, size); if (ret != size) { PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Impossible to write mem", -1); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
void elfsh_fini() { revm_output(" [*] ELFsh modremap fini -OK- \n"); revm_command_del(CMD_REMAP); }
int remap_cmd() { elfshobj_t *file; elfshsect_t *cur; u_int new_base; u_int real_base = 0xffffffff; int diff; int i; int cnt; u_int count_raw = 0; u_int count_pht = 0; u_int count_sht = 0; u_int count_ent = 0; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Sanity checks */ i = sscanf(world.curjob->curcmd->param[0], "0x%X", &new_base); if (new_base == 0 || i != 1) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid new base address", -1); file = world.curjob->curfile; if (elfsh_read_obj(file) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to read object file", -1); if (elfsh_get_symtab(file, NULL) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to read symbol table", -1); /* Calculate delta */ real_base = elfsh_get_object_baseaddr(file); if (real_base == 0xffffffff) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Base address not found", -1); if (new_base & 0xfff) { revm_output(" [*] Base address adapted to be congruent pagesize \n"); new_base &= 0xfffff000; } diff = new_base - real_base; printf(" [*] Delta is %08X \n", diff); /* Update entry point */ if (file->hdr->e_entry > real_base) { file->hdr->e_entry += diff; count_ent++; } /* For all sections of the current object */ for (cur = file->sectlist; cur != NULL; cur = cur->next) { cnt = elfsh_relocate_section(cur, diff); if (cnt < 0) { printf(" [*] MODREMAP : Section %s wont be relocated\n", cur->name); continue; } count_raw += cnt; } /* Fixup SHT */ count_sht += elfsh_reloc_sht(file, diff); /* Fixup PHT */ count_pht += elfsh_reloc_pht(file, diff); /* Print msg */ printf(" [*] Total number of modified references : %u \n" "\t PHT relocation : %u \n" "\t SHT relocation : %u \n" "\t ENT relocation : %u \n" "\t RAW relocation : %u \n", count_pht + count_sht + count_ent + count_raw, count_pht , count_sht , count_ent , count_raw); printf(" [*] Remapping at base %08X -OK-\n\n", new_base); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Inject a .o into an executable */ int cmd_relinject() { elfshobj_t *host; elfshobj_t *rel; int idx; char logbuf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Check to avoid non-runtime (static) injection from e2bdg the debugger that would desynchronize the memory perspective of the program. The debugger is not supposed to do that, it is a job for elfsh */ if (world.state.revm_mode == REVM_STATE_EMBEDDED && elfsh_is_static_mode()) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "E2dbg must inject in memory, switch to dynamic mode.", -1); /* Load host file */ idx = atoi(world.curjob->curcmd->param[0]); host = (idx ? revm_getfile(idx) : hash_get(&file_hash, world.curjob->curcmd->param[0])); if (host == NULL) { host = elfsh_map_obj(world.curjob->curcmd->param[0]); if (host == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot map host file", -1); } /* Load relocatable file */ idx = atoi(world.curjob->curcmd->param[1]); rel = (idx > 0 ? revm_getfile(idx) : hash_get(&file_hash, world.curjob->curcmd->param[1])); if (rel == NULL) { rel = elfsh_map_obj(world.curjob->curcmd->param[1]); if (rel == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot map relocatable file", -1); } /* Call libelfsh relocatable object injector */ idx = elfsh_inject_etrel_hash(host, rel, &world.curjob->loaded, &world.shared_hash); if (idx < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to inject ET_REL with workspace", (-1)); /* Success : put the modified object as current */ world.curjob->curfile = host; if (!world.state.revm_quiet) { snprintf(logbuf, BUFSIZ - 1, "\n [*] ET_REL %s injected succesfully in %s %s\n\n", rel->name, (host->hdr->e_type == ET_EXEC ? "ET_EXEC" : host->hdr->e_type == ET_DYN ? "ET_DYN" : "unknown host file"), host->name); revm_output(logbuf); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
void elfsh_init() { revm_output(" [*] ELFsh modremap init -OK- \n"); revm_command_add(CMD_REMAP, remap_cmd, revm_getoption, 1, "Try to remap a non-relocatable file"); }
/** * @brief Display relocation entries */ int cmd_rel() { elfshsect_t *sect; elfsh_Rel *rel; regex_t *tmp; char *type; char *typeshort; char *name; u_int index; u_int index2; u_int typenum; char buff[256]; u_int size; revmconst_t *types; char addstr[32]; char logbuf[BUFSIZ]; void *data; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Sanity checks */ sect = elfsh_get_reloc(world.curjob->curfile, 0, &size); if (sect == NULL) RET(-1); /* Choose between global or local regx */ FIRSTREGX(tmp); snprintf(logbuf, BUFSIZ - 1, " [RELOCATION TABLES]\n [Object %s]\n\n", world.curjob->curfile->name); revm_output(logbuf); /* We need to iterate as much as there is .rel* sections */ for (index2 = 0; sect; index2++) { snprintf(logbuf, BUFSIZ - 1, " {Section %s} \n", elfsh_get_section_name(world.curjob->curfile, sect)); revm_output(logbuf); /* Iterate on the .rel entries array for each .rel section */ data = elfsh_readmem(sect); for (index = 0; index < size; index++) { /* Get the current relocation entry */ if (sect->shdr->sh_type == SHT_RELA) { rel = (void *) ((elfsh_Rela *) data + index); snprintf(addstr, sizeof(addstr), "add[%s]", revm_colornumber("%08u", (unsigned int) ((elfsh_Rela *) rel)->r_addend)); } else { rel = (elfsh_Rel *) data + index; addstr[0] = 0x00; } /* Get linked symbol name */ name = elfsh_get_symname_from_reloc(world.curjob->curfile, rel); typenum = elfsh_get_reltype(rel); types = revm_getrelascii(world.curjob->curfile); type = (char *) (typenum > ELFSH_RELOC_MAX(world.curjob->curfile) ? NULL : types[typenum].desc); typeshort = (char *) (typenum > ELFSH_RELOC_MAX(world.curjob->curfile) ? NULL : types[typenum].name); /* Output is different depending on the quiet flag */ if (!world.state.revm_quiet) snprintf(buff, sizeof(buff), " [%s] %s %s %s%s%s : %s %s => %s\n", revm_colornumber("%03u", index), revm_colortypestr_fmt("%-15s", typeshort), revm_coloraddress(XFMT, elfsh_get_reloffset(rel)), revm_colorfieldstr("sym["), revm_colornumber("%03u", elfsh_get_relsym(rel)), revm_colorfieldstr("]"), (name != NULL ? revm_colorstr_fmt("%-30s", name) : revm_colorwarn_fmt("%-30s", "<?>")), addstr, revm_colortypestr(type)); else snprintf(buff, sizeof(buff), " [%s] %s %s %s%s%s : %s %s\n", revm_colornumber("%03u", index), revm_colortypestr_fmt("%-15s", typeshort), revm_coloraddress(XFMT, elfsh_get_reloffset(rel)), revm_colorfieldstr("sym["), revm_colornumber("%03u", elfsh_get_relsym(rel)), revm_colorfieldstr("]"), (name != NULL ? revm_colorstr_fmt("%-22s", name) : revm_colorwarn_fmt("%-22s", "<?>")), addstr); /* Print it if it matchs the regex */ if (NULL == tmp || (tmp != NULL && name != NULL && 0 == regexec(tmp, buff, 0, 0, 0))) switch (revm_output(buff)) { case -1: revm_endline(); revm_output("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); case -2: revm_endline(); goto next; } revm_endline(); } next: sect = elfsh_get_reloc(world.curjob->curfile, index2 + 1, &size); revm_output("\n"); } revm_output("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * List all the loaded objects */ int cmd_dolist() { elfshobj_t *actual; int index; char *time; char *nl; char c; char c2; char logbuf[BUFSIZ]; char optbuf[BUFSIZ]; char **keys; int keynbr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); index = 1; /* Private descriptors */ if (hash_size(&world.curjob->loaded)) { revm_output(" .::. Static Working files .::. \n"); keys = hash_get_keys(&world.curjob->loaded, &keynbr); for (index = 0; index < keynbr; index++) { actual = hash_get(&world.curjob->loaded, keys[index]); time = ctime(&actual->loadtime); nl = strchr(time, '\n'); if (nl) *nl = 0x00; c = (world.curjob->curfile == actual ? '*' : ' '); c2 = ((actual->linkmap || actual->rhdr.base) ? 'M' : ' '); if (elfsh_is_runtime_mode()) snprintf(optbuf, BUFSIZ, "(" XFMT ")", actual->rhdr.base); else snprintf(optbuf, BUFSIZ, "%s", ""); snprintf(logbuf, BUFSIZ - 1, " %s %c%c %s ID: %10u %s %-31s ", time, c, c2, optbuf, actual->id, elfsh_get_objtype(actual->hdr) == ET_REL ? "ET_REL " : elfsh_get_objtype(actual->hdr) == ET_DYN ? "ET_DYN " : elfsh_get_objtype(actual->hdr) == ET_EXEC ? "ET_EXEC" : elfsh_get_objtype(actual->hdr) == ET_CORE ? "ET_CORE" : "UNKNOWN", actual->name); revm_output(logbuf); revm_dolist_dep(actual); revm_output("\n"); /* printf("-> Hashes for object : PAR[%u] ROOT[%u] CHILD[%u] \n", hash_size(&actual->parent_hash), hash_size(&actual->root_hash), hash_size(&actual->child_hash)); */ } } /* Shared descriptors */ if (hash_size(&world.shared_hash)) { revm_output("\n .::. Shared Working files .::. \n"); keys = hash_get_keys(&world.shared_hash, &keynbr); for (index = 0; index < keynbr; index++) { actual = hash_get(&world.shared_hash, keys[index]); time = ctime(&actual->loadtime); nl = strchr(time, '\n'); if (nl) *nl = 0x00; c = (world.curjob->curfile == actual ? '*' : ' '); c2 = (actual->linkmap ? 'L' : ' '); if (elfsh_is_runtime_mode()) snprintf(optbuf, BUFSIZ, "(" XFMT ")", actual->rhdr.base); else snprintf(optbuf, BUFSIZ, "%s", ""); snprintf(logbuf, BUFSIZ - 1, " [%02u] %s %c%c %s ID: %02u %-31s \n", index + 1, time, c, c2, optbuf, actual->id, actual->name); revm_output(logbuf); } } if (!hash_size(&world.curjob->loaded) && !hash_size(&world.shared_hash)) revm_output(" [*] No loaded file\n"); revm_output("\n"); revm_modlist(); revm_output("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * display info about the core file */ int cmd_coreinfo() { char buff[256]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); snprintf(buff,sizeof(buff)," [CORE FILE NOTES_ENTRY]\n [Object %s | %s]\n\n", world.curjob->curfile->name, world.curjob->curfile->coretype == ELFSH_CORE_LINUX ? "Linux":"FreeBSD"); revm_output(buff); switch(world.curjob->curfile->coretype) { case ELFSH_CORE_LINUX: { elfsh_prstatus_t *ps; elfsh_prpsinfo_t *pr; elfsh_uregset_t regs; ps = &world.curjob->curfile->core.prstatus; pr = &world.curjob->curfile->core.prpsinfo; snprintf(buff, sizeof(buff), " Received Signal: %d (%s)\n\n", ps->pr_cursig, get_signal(ps->pr_cursig)); revm_output(buff); regs = *((elfsh_uregset_t *)(&ps->pr_reg)); snprintf(buff, sizeof(buff), " [ FILE INFO ]\n"); revm_output(buff); snprintf(buff, sizeof(buff), " Executable filename: %s\n UID: %d\tGID: %d\n PID: %d\n\n", pr->pr_fname, pr->pr_uid, pr->pr_gid, ps->pr_pid); revm_output(buff); snprintf(buff, sizeof(buff), " [ REGISTERS INFO ]\n"); revm_output(buff); snprintf(buff, sizeof(buff), " EAX: %08x\n EBX: %08x\n ECX: %08x\n EDX: %08x\n", (u_int)regs.eax, (u_int)regs.ebx, (u_int)regs.ecx, (u_int)regs.edx); revm_output(buff); snprintf(buff, sizeof(buff), " ESP: %08x\n ESI: %08x\n EDI: %08x\n EIP: %08x\n" " EFLAGS: %08x\n\n", (u_int)regs.esp, (u_int)regs.esi, (u_int)regs.edi, (u_int)regs.eip, (u_int)regs.eflags); revm_output(buff); } break; case ELFSH_CORE_FREEBSD: { elfsh_bsdprstatus_t *ps; elfsh_bsdprpsinfo_t *pr; elfsh_bsduregset_t regs; ps = &world.curjob->curfile->bsdcore.prstatus; pr = &world.curjob->curfile->bsdcore.prpsinfo; snprintf(buff, sizeof(buff), " Received Signal: %d (%s)\n\n", ps->pr_cursig, get_signal(ps->pr_cursig)); revm_output(buff); regs = *((elfsh_bsduregset_t *)(&ps->pr_reg)); snprintf(buff, sizeof(buff), " [ FILE INFO ]\n"); revm_output(buff); snprintf(buff, sizeof(buff), " Executable filename: %s\n PID: %d\n\n", pr->pr_fname, ps->pr_pid); revm_output(buff); snprintf(buff, sizeof(buff), " [ REGISTERS INFO ]\n"); revm_output(buff); } break; } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/* Declare a new typed variable */ int cmd_declare() { aspectype_t *type; char *varname; char buf[BUFSIZ]; u_int curlen; u_int curidx; u_int curpidx; u_int openbrace; u_int closebrace; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Preliminary checks */ if (world.curjob->curcmd->argc < 3 || strcmp(world.curjob->curcmd->param[1], "=")) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid syntax for command", -1); /* Preliminary checks */ type = aspect_type_get_by_name(world.curjob->curcmd->name); if (!type) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unknown type for new variable", -1); /* Create the new data structure */ bzero(buf, BUFSIZ); /* Create a unique string for the value of the object */ for (openbrace = closebrace = curlen = 0, curidx = 2; world.curjob->curcmd->param[curidx]; curidx++, curlen += curpidx) for (curpidx = 0; world.curjob->curcmd->param[curidx][curpidx]; curpidx++) switch (world.curjob->curcmd->param[curidx][curpidx]) { case '(': *(buf + curlen + curpidx) = '('; openbrace++; break; case ')': *(buf + curlen + curpidx) = ')'; closebrace++; if (closebrace > openbrace) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid closing structure for variable", -1); break; case ' ': *(buf + curlen + curpidx) = ','; break; default: *(buf + curlen + curpidx) = world.curjob->curcmd->param[curidx][curpidx]; break; } /* Some first checks on the value */ if (closebrace != openbrace) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid nesting structure for variable", -1); #if __DEBUG_EXPRS__ fprintf(stderr, "Expression to write in variable: %s \n", buf); #endif curlen = strlen(world.curjob->curcmd->param[0]); varname = alloca(curlen + 2); snprintf(varname, curlen + 2, "$%s", world.curjob->curcmd->param[0]); /* Perform the real operation now */ if (type->childs) { if (!revm_expr_create(type, varname, buf)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid value for variable", -1); } else { if (!revm_simple_expr_create(type, varname, buf)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid value for variable", -1); } /* Print success */ if (!world.state.revm_quiet) { snprintf(buf, sizeof(buf), " [*] Variable %s succesfully initialized \n\n", world.curjob->curcmd->param[0]); revm_output(buf); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/* Make hash ! */ int cmd_kmem_hash() { int i, fd, len, new_size; revmlist_t *actual, *second; char buff[BUFSIZ]; char buffhash[BUFSIZ]; eresi_Addr vaddr; unsigned char *hashbuffer; char *tmp; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); memset(buff, '\0', sizeof(buff)); memset(buffhash, '\0', sizeof(buffhash)); vaddr = -1; actual = world.curjob->curcmd->disasm + 0; second = world.curjob->curcmd->disasm + 1; if (actual->rname) { kernsh_addrlen(actual, &vaddr, &len); hashbuffer = kernsh_hash(vaddr+actual->off, len, &new_size); if (hashbuffer == NULL) { PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to make hash", -1); } i = 0; tmp = buffhash; while(hashbuffer[i] != '\0') { sprintf(tmp, "%02x", hashbuffer[i]); i++; tmp += 2; } snprintf(buff, sizeof(buff), "MD5 @ %s : \n\t%s\n\n", revm_coloraddress(XFMT, (eresi_Addr) vaddr), revm_colorstr((char *)buffhash)); revm_output(buff); snprintf(buff, sizeof(buff), "%s:%s:%s:%s:%s:%s\n\n", revm_coloraddress(XFMT, (eresi_Addr) vaddr), revm_colornumber("%u", libkernshworld.mem), revm_colornumber("%u", (int)config_get_data(LIBKERNSH_CONFIG_HASH)), revm_colornumber("%u", new_size), revm_colornumber("%u", actual->off), revm_colorstr((char *)buffhash)); revm_output(buff); snprintf(buff, sizeof(buff), "0x%lx:%d:%d:%d:%d:%s\n", (unsigned long) vaddr, libkernshworld.mem, (int)config_get_data(LIBKERNSH_CONFIG_HASH), new_size, actual->off, buffhash); revm_setvar_str(REVM_VAR_RESULT, (char *)buffhash); export_var((char *)buffhash, 0, 0, buff, 2); if (second != NULL && second->rname != NULL) { XOPEN(fd, second->rname, O_CREAT|O_APPEND|O_RDWR, 0777, -1); memset(buff, '\0', sizeof(buff)); snprintf(buff, sizeof(buff), "0x%lx:%d:%d:%d:%d:%s\n", (unsigned long) vaddr, libkernshworld.mem, (int)config_get_data(LIBKERNSH_CONFIG_HASH), new_size, actual->off, buffhash); XWRITE(fd, buff, strlen(buff), -1); XCLOSE(fd, -1); } } XFREE(__FILE__, __FUNCTION__, __LINE__, hashbuffer); revm_endline(); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Reflect command disassemble the block cache of the parameter and create a list of instr exprs */ int cmd_reflect() { container_t *container; container_t *instrcontainer; mjrblock_t *curblock; asm_instr cur; elfsh_Half machine; char logbuf[BUFSIZ]; char logbuf2[BUFSIZ]; eresi_Addr addr; eresi_Addr daddr; u_int off; int ret; aspectype_t *curtype; void *blocdata; int fileoff; list_t *instrlist; revmexpr_t *expr; u_int insnbr; u_int reqnbr; u_int readsize; revmexpr_t *immed; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); curtype = aspect_type_get_by_name("instr"); if (!curtype) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed reflection : unknown type : instr", -1); /* Validate parameters */ if (world.curjob->curcmd->argc != 1 && world.curjob->curcmd->argc != 2) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Command expect one or two parameters \n", -1); /* Init proc */ if (!world.curjob->proc) { switch (machine = elfsh_get_arch(world.curjob->curfile->hdr)) { case EM_386: world.curjob->proc = &world.proc_ia32; break; case EM_SPARC: case EM_SPARC32PLUS: case EM_SPARCV9: world.curjob->proc = &world.proc_sparc; break; case EM_ARM: world.curjob->proc = &world.proc_arm; break; case EM_MIPS: case EM_MIPS_RS3_LE: world.curjob->proc = &world.proc_mips; break; default: snprintf(logbuf, sizeof (logbuf), "Architecture %s not supported. No disassembly available\n", elfsh_get_machine_string(machine)); revm_output(logbuf); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); } } /* Now lookup the block by its addr or symbol */ immed = revm_lookup_param(world.curjob->curcmd->param[0], 1); if (!immed) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to lookup parameter address expr", -1); if (revm_convert_object(immed, ASPECT_TYPE_CADDR) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid address parameter", 0); addr = (immed->value->immed ? immed->value->immed_val.ent : immed->value->get_obj(immed->value->parent)); /* Analyse the binary if not already done */ /* if (!world.mjr_session.cur->analysed) { maxdepth = (int) config_get_data(CONFIG_CFGDEPTH); ret = mjr_analyse(&world.mjr_session, world.curjob->curfile->hdr->e_entry, maxdepth, 0); if (ret < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed analyzing current object", -1); } */ /* One more param enables lightweight mode: lookup data from a binary file section - no CFG needed */ if (world.curjob->curcmd->argc == 2) { immed = revm_lookup_param(world.curjob->curcmd->param[1], 1); if (revm_convert_object(immed, ASPECT_TYPE_INT) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid size parameter", 0); reqnbr = (immed->value->immed ? (u_int) immed->value->immed_val.ent : (u_int) immed->value->get_obj(immed->value->parent)); if (reqnbr <= 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid instruction number to reflect", -1); readsize = 16 * reqnbr; blocdata = alloca(readsize); } /* Only one param (an addr/symbol) --> Lookup data from a basic block on the CFG */ else { container = mjr_block_get_by_vaddr(world.mjr_session.cur, addr, MJR_BLOCK_GET_STRICT); if (!container) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to find bloc at this virtual address", -1); curblock = (mjrblock_t *) container->data; readsize = curblock->size; blocdata = alloca(readsize); reqnbr = 0; } /* Read data -- could be imported from a remote process, so needs to copy buffer */ fileoff = elfsh_get_foffset_from_vaddr(world.curjob->curfile, addr); if (elfsh_readmemf(world.curjob->curfile, fileoff, blocdata, readsize) != readsize) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to read data to reflect", -1); /* Create the new list of instructions in expression form */ XALLOC(__FILE__, __FUNCTION__, __LINE__, instrlist, sizeof(list_t), -1); snprintf(logbuf2, sizeof(logbuf2), AFMT, addr); elist_init(instrlist, strdup(logbuf2), ASPECT_TYPE_EXPR); /* Reflection all instructions of the basic bloc in the list */ for (insnbr = off = 0; off < readsize; off += ret, insnbr++) { /* If reached the number of requested instruction, stop now even without reaching buffer end */ if (reqnbr && insnbr == reqnbr) break; /* Fetch the current instruction */ ret = asm_read_instr(&cur, (u_char *) blocdata + off, readsize - off + 10, world.curjob->proc); if (ret < 0) { elist_destroy(instrlist); PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to fetch code for basic bloc", -1); } /* Also add the instruction to the current reflected list for this block */ instrcontainer = container_create(curtype->type, (void *) &cur, NULL, NULL, 0); snprintf(logbuf, sizeof (logbuf), "$instr-"XFMT, addr + off); daddr = (eresi_Addr) instrcontainer; expr = revm_inform_type_addr(curtype->name, strdup(logbuf), daddr, NULL, 0, 1); elist_add(instrlist, strdup(logbuf), expr); } /* Reverse instrlist and add it to the hash of lists */ instrlist = elist_reverse(instrlist); hash_add(&instrlists_hash, strdup(logbuf2), instrlist); /* Printing message if we are not in quiet mode */ if (!world.state.revm_quiet) { snprintf(logbuf, sizeof(logbuf), " [*] Code at address " AFMT " reflected succesfully (%u instrs) \n\n", addr, insnbr); revm_output(logbuf); } /* Put the current bloc in the last result variable */ /* revm_expr_destroy_by_name(REVM_VAR_RESULT); revm_expr_copy(expr, REVM_VAR_RESULT); */ PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/* Check a hash */ int cmd_kmem_chash() { int i, ret, mode, stype, type, nsize, size, off, origmode, val; char buff[BUFSIZ], buff2[256]; char *param, *str; unsigned long addr; revmexpr_t *expr; revmobj_t *obj; unsigned char origbuffer[BUFSIZ]; char buffhash[BUFSIZ]; unsigned char *hashbuffer; char *tmp; FILE *fd; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); val = 0; memset(buff, '\0', sizeof(buff)); memset(buff2, '\0', sizeof(buff2)); param = world.curjob->curcmd->param[0]; stype = (int)config_get_data(LIBKERNSH_CONFIG_HASH); if (param != NULL) { expr = revm_lookup_param(param, 1); obj = expr->value; if (obj->otype->type == ASPECT_TYPE_STR) { str = (obj->immed ? obj->immed_val.str : obj->get_name(obj->root, obj->parent)); memcpy(buff2, str, sizeof(buff2)); param = buff2; } /* We must get hash in a file ? */ if (!strstr(param, ":")) { fd = fopen(param, "r"); if (fd == NULL) { PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to open file", -1); } while(fgets(buff, sizeof(buff), fd) != NULL) { buff[strlen(buff) - 1] = '\0'; if (buff[0] == '#') continue; if (extract_info(buff, &addr, &mode, &type, &size, &off, origbuffer, sizeof(origbuffer))) { PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Bad format", -1); } /* Switch to the mode where the hash has been done */ origmode = elfsh_get_mode(); elfsh_set_mode(mode); config_update_key(LIBKERNSH_CONFIG_HASH, (void *)type); hashbuffer = kernsh_hash(addr+off, size, &nsize); elfsh_set_mode(origmode); i = 0; tmp = buffhash; while((i < sizeof(buffhash)) && (hashbuffer[i] != '\0')) { sprintf(tmp, "%02x", hashbuffer[i]); i++; tmp += 2; } memset(buff, '\0', sizeof(buff)); if (!strncmp((const char *)origbuffer, (const char *)buffhash, sizeof(origbuffer))) { snprintf(buff, sizeof(buff), "%s @ %s with size = %s and offset = %s\n", revm_colorstr("HASH MATCH @ !"), revm_coloraddress(XFMT, (eresi_Addr) addr), revm_colornumber("%u", size), revm_colornumber("%u", off)); revm_output(buff); revm_endline(); } else { snprintf(buff, sizeof(buff), "%s @ %s with size = %s and offset = %s\n %s != %s\n", revm_colorstr("HASH MISMATCH @ !"), revm_coloraddress(XFMT, (eresi_Addr) addr), revm_colornumber("%u", size), revm_colornumber("%u", off), revm_colorstr((char *)origbuffer), revm_colorstr((char *)buffhash)); revm_output(buff); revm_endline(); val++; } } fclose(fd); } else { if (extract_info(param, &addr, &mode, &type, &size, &off, origbuffer, sizeof(origbuffer))) { PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Bad format", -1); } origmode = elfsh_get_mode(); elfsh_set_mode(mode); config_update_key(LIBKERNSH_CONFIG_HASH, (void *)type); hashbuffer = kernsh_hash(addr+off, size, &nsize); elfsh_set_mode(origmode); i = 0; tmp = buffhash; while((i < sizeof(buffhash)) && (hashbuffer[i] != '\0')) { sprintf(tmp, "%02x", hashbuffer[i]); i++; tmp += 2; } if (hashbuffer == NULL) { PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to make hash", -1); } memset(buff, '\0', sizeof(buff)); if (!strncmp((const char *)origbuffer, (const char *)buffhash, sizeof(origbuffer))) { snprintf(buff, sizeof(buff), "%s @ %s with size = %s and offset = %s\n\n", revm_colorstr("HASH MATCH @ !"), revm_coloraddress(XFMT, (eresi_Addr) addr), revm_colornumber("%u", size), revm_colornumber("%u", off)); revm_output(buff); } else { snprintf(buff, sizeof(buff), "%s @ %s with size = %s and offset = %s\n %s != %s\n\n", revm_colorstr("HASH MISMATCH @ !"), revm_coloraddress(XFMT, (eresi_Addr) addr), revm_colornumber("%u", size), revm_colornumber("%u", off), revm_colorstr((char *)origbuffer), revm_colorstr((char *)buffhash)); revm_output(buff); val++; } } } config_update_key(LIBKERNSH_CONFIG_HASH, (void *)stype); revm_setvar_int(REVM_VAR_RESULT, val); revm_endline(); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, ret); }
/** * Print a specific type * * @param type * @param mode * @return */ int revm_type_print(char *type, char mode) { aspectype_t *cur; aspectype_t *child; char buf[BUFSIZ]; char prefix[128]; int len; char *size; char offset[128]; int idx; int sz; char *pad; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); cur = hash_get(&types_hash, type); if (!cur) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unknown type", 0); /* Set up things */ revm_endline(); /* Setup first part of the line */ snprintf(prefix, sizeof(prefix), "%s%s%s", revm_colorfieldstr("{"), revm_colornumber("%u", cur->size), revm_colorfieldstr("}")); len = snprintf(buf, sizeof(buf), " %s %s %-20s %s %-10s", revm_colornumber("id:%-10u", cur->type), revm_colorfieldstr("Type"), revm_colortypestr_fmt("%-20s", type), revm_colorfieldstr("size"), prefix); size = alloca(20); /* If the type is a structure */ if (cur->childs) { len += snprintf(buf + len, sizeof(buf) - len, "%s", revm_colorfieldstr(" = {")); /* Prepare the padding after each field name */ sz = len - revm_color_size(buf) - 16; /* -16 is dirty: some bug in colors */ pad = alloca(sz + 1); memset(pad, ' ', sz); pad[sz] = 0x00; /* For each child field type */ for (child = cur->childs; child; child = child->next) { /* Compute the size field */ if (child->type == ASPECT_TYPE_RAW) snprintf(size, sizeof(size), "%s%s%s", revm_colorfieldstr("["), revm_colornumber("%u", child->size), revm_colorfieldstr("]")); else if (child->dimnbr && child->elemnbr) { for (sz = idx = 0; idx < child->dimnbr; idx++) sz += 20; size = alloca(sz); for (sz = idx = 0; idx < child->dimnbr; idx++) sz += snprintf(size + sz, sz, "%s%s%s", revm_colorfieldstr("["), revm_colornumber("%u", child->elemnbr[idx]), revm_colorfieldstr("]")); } else *size = 0x00; /* Format the whole thing */ if (mode) *offset = 0x00; else snprintf(offset, sizeof(offset), "%s%s", revm_colornumber("%u", child->off), revm_colorfieldstr(":")); len += snprintf(buf + len, sizeof(buf) - len, "%s%s%s%s%s%s%s", offset, revm_colorstr(child->fieldname), revm_colorfieldstr(":"), revm_colortypestr((child->isptr ? "*" : "")), revm_colortypestr(child->name), size, revm_colorfieldstr((child->next ? ",\n" : "}\n\n"))); /* Print field and next padding */ revm_output(buf); revm_endline(); if (child->next) revm_output(pad); *buf = 0x00; len = 0; } } /* Print non-structures types */ else { revm_output(buf); revm_output("\n"); } /* Return success */ PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 1); }
/** * Print the chosen symbol table * @param file * @param sect * @param tab * @param num * @param regx * @param get_symname * @return */ int ds(elfshobj_t *file, elfshsect_t *sect, u_int num, regex_t *regx, char *(*get_symname)(elfshobj_t *f, elfsh_Sym *s)) { elfsh_Sym *table; char *name; char *type; char *bind; u_int typenum; u_int bindnum; u_int foff; u_int index; char *sect_name; char buff[512]; char off[50]; char type_unk[ERESI_MEANING + 1]; char bind_unk[ERESI_MEANING + 1]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Sort the table if necessary */ if (world.state.sort != NULL) switch (*world.state.sort) { case ELFSH_SORT_BY_ADDR: table = sect->altdata; break; case ELFSH_SORT_BY_SIZE: table = sect->terdata; break; default: PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unknown sort mode", -1); } /* Avoid reading inexistant memory in the process for .symtab */ else table = (elfsh_Sym *) (sect->shdr->sh_addr ? elfsh_readmem(sect) : sect->data); /* Browse symtab */ for (index = 0; index < num; index++) { /* Retreive names */ typenum = elfsh_get_symbol_type(table + index); bindnum = elfsh_get_symbol_bind(table + index); type = (char *) (typenum > ELFSH_SYMTYPE_MAX ? revm_build_unknown(type_unk, "type", typenum) : elfsh_sym_type[typenum].desc); bind = (char *) (bindnum >= ELFSH_SYMBIND_MAX ? revm_build_unknown(bind_unk, "type", bindnum) : elfsh_sym_bind[bindnum].desc); name = get_symname(world.curjob->curfile, table + index); sect_name = NULL; sect = elfsh_get_parent_section(world.curjob->curfile, table[index].st_value, NULL); if (sect == NULL && table[index].st_shndx) sect = elfsh_get_section_by_index(world.curjob->curfile, table[index].st_shndx, NULL, NULL); if (sect != NULL) sect_name = elfsh_get_section_name(world.curjob->curfile, sect); /* Fixup names */ if (name == NULL || *name == 0) name = ELFSH_NULL_STRING; if (type == NULL || *type == 0) type = ELFSH_NULL_STRING; if (bind == NULL || *bind == 0) bind = ELFSH_NULL_STRING; if (sect_name == NULL) sect_name = ELFSH_NULL_STRING; foff = (!table[index].st_value ? 0 : elfsh_get_foffset_from_vaddr(world.curjob->curfile, table[index].st_value)); if (sect && sect->shdr->sh_addr != table[index].st_value) snprintf(off, sizeof(off), " + %s", revm_colornumber("%u", (u_int) (table[index].st_value - sect->shdr->sh_addr))); else *off = '\0'; /* Different output depending on the quiet flag */ if (!world.state.revm_quiet) { snprintf(buff, sizeof(buff), " %s %s %s %s %s%s " "%s%s %s%s %s%s => %s%s\n", revm_colornumber("[%03u]", index), revm_coloraddress(XFMT, (eresi_Addr) elfsh_get_symbol_value(table + index) + file->rhdr.base), revm_colortypestr_fmt("%-8s", type), revm_colorstr_fmt("%-40s", name), revm_colorfieldstr("size:"), revm_colornumber("%010u", elfsh_get_symbol_size(table + index)), revm_colorfieldstr("foffset:"), revm_colornumber("%06u", foff), revm_colorfieldstr("scope:"), revm_colortypestr_fmt("%-6s", bind), revm_colorfieldstr("sctndx:"), revm_colornumber("%02u", elfsh_get_symbol_link(table + index)), revm_colorstr(sect_name), off); } else { snprintf(buff, sizeof(buff), " %s %s %s %s %s%s %s%s %s%-6s\n", revm_colornumber("[%03u]", index), revm_coloraddress(XFMT, (eresi_Addr) elfsh_get_symbol_value(table + index) + file->rhdr.base), revm_colortypestr_fmt("%-8s", type), revm_colorstr_fmt("%-15s", name), revm_colorfieldstr("sz:"), revm_colornumber("%06u", elfsh_get_symbol_size(table + index)), revm_colorfieldstr("foff:"), revm_colornumber("%06u", foff), revm_colorfieldstr("scop:"), revm_colortypestr_fmt("%-6s", bind)); } if (regx == NULL || (regx != NULL && regexec(regx, buff, 0, 0, 0) == 0)) { /* If the user ask quit, we just break */ if (revm_output(buff) == -1) break; } revm_endline(); } revm_endline(); revm_output("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/* Redirect a function on a OS independant manner */ int cmd_hijack() { elfsh_Sym *dst; eresi_Addr addr; int err; char *rev; char logbuf[BUFSIZ]; elfshredir_t *redir; listent_t *actual; int idx; int idx2; int printed; eresi_Addr hookedaddr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* If no parameter is given, print the redirection list */ if (!world.curjob->curcmd->param[0]) { printed = 0; /* Simple printing */ for (idx2 = idx = 0; idx < world.curjob->curfile->redir_hash.size; idx++) for (actual = world.curjob->curfile->redir_hash.ent + idx; actual != NULL && actual->key != NULL; actual = actual->next) { redir = (elfshredir_t *) actual->data; if (!printed) { revm_output("\t .::. ELFsh redirection list \n\n"); printed = 1; } snprintf(logbuf, BUFSIZ, "\t [%02u] TYPE:%-6s [" AFMT "] <%s> redirected on [" AFMT "] <%s> \n", idx2, (redir->type == ELFSH_REDIR_CFLOW ? "CFLOW" : redir->type == ELFSH_REDIR_ALTPLT ? "ALTPLT" : redir->type == ELFSH_REDIR_ALTGOT ? "ALTGOT" : "UNK"), redir->addr[0], redir->name[0], redir->addr[1], redir->name[1]); revm_output(logbuf); idx2++; } /* End message */ if (!printed) revm_output("\t .::. No redirection performed on current file \n\n"); else revm_output("\n\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); } /* Some sanity checks first */ if (!world.curjob->curcmd->param[1]) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Redirection destination needed", (-1)); /* Resolve destination parameter */ dst = elfsh_get_metasym_by_name(world.curjob->curfile, world.curjob->curcmd->param[1]); if (!dst && elfsh_is_runtime_mode()) { elfsh_toggle_mode(); dst = elfsh_get_metasym_by_name(world.curjob->curfile, world.curjob->curcmd->param[1]); elfsh_toggle_mode(); } /* If not found */ if (dst == NULL) { err = sscanf(world.curjob->curcmd->param[1], XFMT, (eresi_Addr *) &addr); /* If the hook function is not supplied as an address */ if (err != 1 && elfsh_dynamic_file(world.curjob->curfile)) { elfsh_setup_hooks(); /* First bootstrap ALTPLT if not done */ err = elfsh_copy_plt(world.curjob->curfile, elfsh_get_pagesize(world.curjob->curfile)); if (err < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed at copying PLT", (-1)); /* Request a PLT entry since we have no symbol yet */ dst = elfsh_request_pltent(world.curjob->curfile, world.curjob->curcmd->param[1]); if (dst) addr = dst->st_value; else PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "PLT entry request failed", (-1)); } /* Insert a symbol on the requested address to avoid this */ else PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Need a symbol to redirect", -1); rev = revm_reverse(world.curjob->curfile, addr); } /* The first resolution worked, we take the address */ else { addr = dst->st_value; rev = NULL; } #if __DEBUG_HIJACK__ printf("[cmd_hijack] Resolved %s as %08X \n", world.curjob->curcmd->param[1], addr); #endif /* Hijack function */ err = elfsh_hijack_function_by_name(world.curjob->curfile, ELFSH_HIJACK_TYPE_FLOW, world.curjob->curcmd->param[0], addr, &hookedaddr); /* Last checks */ if (err < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Function redirection failed", (-1)); /* Add it to redirection hash table */ redir = revm_create_REDIR((u_char) err, world.curjob->curcmd->param[0], world.curjob->curcmd->param[1], hookedaddr, addr); hash_add(&world.curjob->curfile->redir_hash, world.curjob->curcmd->param[0], (void *) redir); /* Print final information */ if (!world.state.revm_quiet) { snprintf(logbuf, BUFSIZ - 1, "\n [*] Function %s redirected to addr " XFMT " <%s> \n\n", world.curjob->curcmd->param[0], (eresi_Addr) addr, (rev == NULL ? world.curjob->curcmd->param[1] : rev)); revm_output(logbuf); } if (rev != NULL) XFREE(__FILE__, __FUNCTION__, __LINE__,rev); /* Everything is ok */ PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * @brief Display a PHT * @param phdr * @param num * @param base */ void revm_pht_print(elfsh_Phdr *phdr, uint16_t num, eresi_Addr base) { elfsh_Shdr *shdr; int shtnum; int index; int index2; char *type; u_int typenum; elfshsect_t *list; regex_t *tmp; char buff[512]; char warnmsg[256]; char logbuf[BUFSIZ]; int check; eresi_Addr addr; eresi_Addr addr_end; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); FIRSTREGX(tmp); /* Primary view (2 modes, depending on the quiet flag) */ for (index = 0; index < num; index++) { typenum = elfsh_get_segment_type(phdr + index); type = (char *) (typenum >= ELFSH_SEGTYPE_MAX ? revm_display_pdesc(typenum) : elfsh_seg_type[typenum].desc); addr = phdr[index].p_vaddr; addr_end = phdr[index].p_vaddr + phdr[index].p_memsz; if (elfsh_is_runtime_mode()) { addr_end += base; addr += base; } /* We check if we have a correct alignment */ check = (addr - phdr[index].p_offset) & (phdr[index].p_align - 1); if (check != 0) snprintf(warnmsg, 255, "Wrong alignment (%d)", check); if (!world.state.revm_quiet) snprintf(buff, sizeof(buff), " %s %s -> %s %c%c%c %s%s%s " "%s%s%s %s%s%s %s%s%s => %s %s\n", revm_colornumber("[%02u]", index), revm_coloraddress(XFMT, addr), revm_coloraddress(XFMT, addr_end), (elfsh_segment_is_readable(&phdr[index]) ? 'r' : '-'), (elfsh_segment_is_writable(&phdr[index]) ? 'w' : '-'), (elfsh_segment_is_executable(&phdr[index]) ? 'x' : '-'), revm_colorfieldstr("memsz("), revm_colornumber(UFMT, phdr[index].p_memsz), revm_colorfieldstr(")"), revm_colorfieldstr("foffset("), revm_colornumber(UFMT, phdr[index].p_offset), revm_colorfieldstr(")"), revm_colorfieldstr("filesz("), revm_colornumber(UFMT, phdr[index].p_filesz), revm_colorfieldstr(")"), revm_colorfieldstr("align("), revm_colornumber(UFMT, phdr[index].p_align), revm_colorfieldstr(")"), revm_colortypestr(type), check != 0 ? revm_colorwarn(warnmsg) : "" ); else snprintf(buff, sizeof(buff), " %s %s -> %s %c%c%c %s%s%s " "%s%s%s %s%s%s\n", revm_colornumber("[%02u]", index), revm_coloraddress(XFMT, addr), revm_coloraddress(XFMT, addr_end), (elfsh_segment_is_readable(&phdr[index]) ? 'r' : '-'), (elfsh_segment_is_writable(&phdr[index]) ? 'w' : '-'), (elfsh_segment_is_executable(&phdr[index]) ? 'x' : '-'), revm_colorfieldstr("memsz("), revm_colornumber(UFMT, phdr[index].p_memsz), revm_colorfieldstr(")"), revm_colorfieldstr("foffset("), revm_colornumber(UFMT, phdr[index].p_offset), revm_colorfieldstr(")"), revm_colorfieldstr("filesz("), revm_colornumber(UFMT, phdr[index].p_filesz), revm_colorfieldstr(")")); if (!tmp || (tmp && !regexec(tmp, buff, 0, 0, 0))) revm_output(buff); revm_endline(); } snprintf(logbuf, BUFSIZ - 1, "\n [SHT correlation]" "\n [Object %s]\n\n", world.curjob->curfile->name); revm_output(logbuf); /* Retreive the sht */ if ((shdr = elfsh_get_sht(world.curjob->curfile, &shtnum)) == 0) PROFILER_OUT(__FILE__, __FUNCTION__, __LINE__); snprintf(logbuf, BUFSIZ - 1, " [*] SHT %s \n", (world.curjob->curfile->shtrb ? "has been rebuilt \n" : "is not stripped \n")); revm_output(logbuf); /* Alternate View */ for (index = 0; index < num; index++, index2 = 0) { typenum = elfsh_get_segment_type(phdr + index); type = (char *) (typenum >= ELFSH_SEGTYPE_MAX ? revm_display_pname(typenum) : elfsh_seg_type[typenum].name); snprintf(logbuf, BUFSIZ - 1, " %s %s \t", revm_colornumber("[%02u]", index), revm_colortypestr_fmt("%-10s", type)); revm_output(logbuf); revm_endline(); /* In SHT */ for (index2 = 0, list = world.curjob->curfile->sectlist; list; list = list->next) if (elfsh_segment_is_parent(list, phdr + index)) { index2++; snprintf(logbuf, BUFSIZ - 1, "%s%s ", (list->shdr->sh_offset + list->shdr->sh_size > phdr[index].p_offset + phdr[index].p_filesz ? "|" : ""), revm_colorstr(elfsh_get_section_name(world.curjob->curfile, list))); revm_output(logbuf); revm_endline(); } /* In RSHT */ for (index2 = 0, list = world.curjob->curfile->rsectlist; list; list = list->next) if (elfsh_segment_is_parent(list, phdr + index)) { index2++; snprintf(logbuf, BUFSIZ - 1, "%s%s ", (list->shdr->sh_addr + list->shdr->sh_size > phdr[index].p_vaddr + phdr[index].p_memsz ? "|" : ""), revm_colorstr(elfsh_get_section_name(world.curjob->curfile, list))); revm_output(logbuf); revm_endline(); } revm_output("\n"); } PROFILER_OUT(__FILE__, __FUNCTION__, __LINE__); }