/* Disable all functions of a trace * @param trace trace name * @see etrace_funcsettatus */ int etrace_funcdisableall(char *trace) { u_int index; int keynbr; char **keys; hash_t *table; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (!trace) trace = ETRACE_TYPE_DEFAULT; etrace_init_trace(); keys = hash_get_keys(&traces_table, &keynbr); if (keys) { for (index = 0; index < keynbr; index++) { table = (hash_t *) hash_get(&traces_table, keys[index]); if (table) etrace_funcsetstatus(table, 0); } hash_free_keys(keys); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Display the content of a hash table * @param name Hash table name to display */ int revm_table_display_content(char *name) { hash_t *h; char **keys; int keynbr; int index; char logbuf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); h = hash_get(hash_hash, name); if (!h) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid requested hash parameter", -1); /* Empty hash */ keys = hash_get_keys(h, &keynbr); if (!keynbr) { revm_output(" [*] Hash table is empty \n\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); } /* Display pointers */ for (index = 0; index < keynbr; index++) revm_table_display_element(h, keys[index], 0); snprintf(logbuf, sizeof(logbuf), "\n [*] Displayed %u entries of table %s \n\n", keynbr, name); revm_output(logbuf); hash_free_keys(keys); 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); }
/** * Detail listing of a trace * @param table trace hash table * @param name trace name * @see traces_list */ int traces_list_detail(hash_t *table, char *name) { char **keys; u_int index; int keynbr; trace_t *entrie; char buf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); snprintf(buf, BUFSIZ - 1, " ~> %s: %s\n", aspectworld.colorfieldstr("Trace name"), aspectworld.colorstr(name)); aspectworld.profile(buf); keys = hash_get_keys(table, &keynbr); if (keys && keynbr > 0) { aspectworld.profile("\n"); for (index = 0; index < keynbr; index++) { entrie = (trace_t *) hash_get(table, keys[index]); if (entrie) { snprintf(buf, BUFSIZ - 1, " %s: %s %s: %s\n", aspectworld.colorfieldstr("Function name"), aspectworld.colorstr_fmt("%-15s", entrie->funcname), aspectworld.colorfieldstr("status"), aspectworld.colortypestr(entrie->enable ? "enabled" : "disabled")); aspectworld.profile(buf); aspectworld.endline(); } } aspectworld.profile("\n"); hash_free_keys(keys); } else { aspectworld.profile("\n [*] No function in this trace\n\n"); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Display the content of a hash table */ static void revm_tables_display() { char **keys; int keynbr; int index; hash_t *cur; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); revm_output(" .:: Registered tables \n\n"); keys = hash_get_keys(hash_hash, &keynbr); for (index = 0; index < keynbr; index++) { cur = hash_get(hash_hash, keys[index]); revm_table_display(cur, keys[index]); } hash_free_keys(keys); revm_output("\n Type 'help tables' for more table details.\n\n"); PROFILER_OUT(__FILE__, __FUNCTION__, __LINE__); }
/** * Destroy a hash table. * @param hash Pointer to the hash to destroy */ void hash_destroy(hash_t *hash) { char **keys; int idx; int keynbr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* We should not destroy the elements as they might be in other hashes */ keys = hash_get_keys(hash, &keynbr); for (idx = 0; idx < keynbr; idx++) if (keys[idx]) XFREE(__FILE__, __FUNCTION__, __LINE__, keys[idx]); if (keys) hash_free_keys(keys); hash_del(hash_hash, hash->name); XFREE(__FILE__, __FUNCTION__, __LINE__, hash->ent); PROFILER_OUT(__FILE__, __FUNCTION__, __LINE__); }
/** * 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); }
/* Find breakpoint by ID */ elfshbp_t *e2dbg_breakpoint_from_id(uint32_t bpid) { elfshbp_t *cur; int index; char **keys; int keynbr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); keys = hash_get_keys(&e2dbgworld.bp, &keynbr); for (index = 0; index < keynbr; index++) { cur = hash_get(&e2dbgworld.bp, keys[index]); if (cur->id == bpid) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, cur); } hash_free_keys(keys); PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to find breakpoing by ID", NULL); }
/** * Change the status of a whole trace * @param table trace hash table * @param status new status (0 = disable, 1 = enable) * @see etrace_funcenableall * @see etrace_funcdisableall */ int etrace_funcsetstatus(hash_t *table, int status) { u_int index; int keynbr; char **keys; trace_t *ret_trace; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (!table) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid parameters", -1); etrace_init_trace(); keys = hash_get_keys(table, &keynbr); if (keys) { for (index = 0; index < keynbr; index++) { ret_trace = (trace_t *) hash_get(table, keys[index]); if (ret_trace) { if (ret_trace->enable != status) { if (ret_trace->enable == 1) trace_enabled_count--; else trace_enabled_count++; } ret_trace->enable = status; } } hash_free_keys(keys); } 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); }
/** * Enumerate each trace and detail every functions * @param name not use * @param optarg not use * @see traces_list_detail */ int traces_list(elfshobj_t *file, char *name, char **optarg) { char **keys = NULL; u_int index; int keynbr; hash_t *subtable; char funcreg[256]; size_t len; char buf[BUFSIZ]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); aspectworld.profile(" .: Trace list :.\n"); if (traces_table.ent) keys = hash_get_keys(&traces_table, &keynbr); if (keys) { if (keynbr > 0) aspectworld.profile("\n"); for (index = 0; index < keynbr; index++) { subtable = hash_get(&traces_table, keys[index]); if (subtable) traces_list_detail(subtable, keys[index]); } hash_free_keys(keys); } else { aspectworld.profile("\n [*] No tracing table available\n\n"); } aspectworld.profile(" .: Exclude list :.\n"); /* Reset */ keynbr = 0; keys = NULL; /* Print exclude list */ if (exclude_table.ent) keys = hash_get_keys(&exclude_table, &keynbr); if (keys) { if (exclude_table.ent) aspectworld.profile("\n"); for (index = 0; index < keynbr; index++) { len = strlen(keys[index]); snprintf(funcreg, 255, "%s%s%s", keys[index][0] != '^' ? "^" : "", keys[index], keys[index][len-1] != '$' ? "$" : ""); snprintf(buf, BUFSIZ - 1, " %s %s %s %s %s\n", aspectworld.colornumber("[%02u]", index+1), aspectworld.colorfieldstr("name:"), aspectworld.colorstr_fmt("%-15s", keys[index]), aspectworld.colorfieldstr("regex:"), aspectworld.colorstr(funcreg)); aspectworld.profile(buf); aspectworld.endline(); } hash_free_keys(keys); } else { aspectworld.profile("\n [*] No exclude table available\n"); } aspectworld.profile("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/* Breakpoint command */ int cmd_bp() { char *str; int ret; eresi_Addr addr; char logbuf[BUFSIZ]; int idx; int index; elfsh_SAddr off = 0; char *name; elfshbp_t *cur; char **keys; int keynbr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* build argc */ for (idx = 0; world.curjob->curcmd->param[idx] != NULL; idx++); str = revm_lookup_string(world.curjob->curcmd->param[0]); /* Select subcommand */ switch (idx) { /* List breakpoints */ case 0: e2dbg_output(" .:: Breakpoints ::.\n\n"); keys = hash_get_keys(&e2dbgworld.bp, &keynbr); for (index = 0; index < keynbr; index++) { cur = hash_get(&e2dbgworld.bp, keys[index]); name = revm_resolve(world.curjob->curfile, (eresi_Addr) cur->addr, &off); if (off) snprintf(logbuf, BUFSIZ, " %c [%02u] " XFMT " <%s + " UFMT ">\n", (e2dbg_is_watchpoint(cur) ? 'W' : 'B'), cur->id, cur->addr, name, off); else snprintf(logbuf, BUFSIZ, " %c [%02u] " XFMT " <%s>\n", (e2dbg_is_watchpoint(cur) ? 'W' : 'B'), cur->id, cur->addr, name); e2dbg_output(logbuf); } hash_free_keys(keys); if (!index) e2dbg_output(" [*] No breakpoints\n"); e2dbg_output("\n"); break; /* Supply a new breakpoint */ case 1: if (!elfsh_is_runtime_mode()) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Not in dynamic or debugger mode", -1); if (!str || !(*str)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid argument", -1); /* Break on a supplied virtual address */ if (IS_VADDR(str)) { if (sscanf(str + 2, AFMT, &addr) != 1) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid virtual address requested", (-1)); } /* Resolve first a function name */ else { addr = e2dbg_breakpoint_find_addr(str); if (addr == 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Requested symbol address unknown", -1); } /* Add the breakpoint */ ret = e2dbg_breakpoint_add(addr); if (ret < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Breakpoint insertion failed\n", (-1)); if (ret >= 0) { name = revm_resolve(world.curjob->curfile, addr, &off); if (!off) snprintf(logbuf, BUFSIZ - 1, " [*] Breakpoint added at <%s> (" XFMT ")\n\n", name, addr); else snprintf(logbuf, BUFSIZ - 1, " [*] Breakpoint added at <%s + " UFMT "> (" XFMT ")\n\n", name, off, addr); e2dbg_output(logbuf); } break; /* Wrong command syntax */ default: PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Wrong arg number", (-1)); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (ret)); }
/* Find the correct location for a breakpoint. Avoid putting breakpoints on plt entries when possible */ eresi_Addr e2dbg_breakpoint_find_addr(char *str) { elfsh_Sym *sym; elfsh_Sym *bsym; elfshsect_t *sect; elfshobj_t *parent; char **keys; int keynbr; int index; eresi_Addr addr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); sym = bsym = NULL; /* Sometimes we fix symbols on the disk : we avoid mprotect */ /* Only return success early if not a plt symbol */ keys = NULL; parent = world.curjob->curfile; sym = elfsh_get_metasym_by_name(parent, str); if (!sym || !sym->st_value) { elfsh_toggle_mode(); sym = elfsh_get_metasym_by_name(parent, str); elfsh_toggle_mode(); } if (sym && parent->hdr->e_type == ET_DYN) sym->st_value += parent->rhdr.base; if (sym && sym->st_value) { sect = elfsh_get_parent_section(parent, sym->st_value, NULL); if (!elfsh_is_plt(parent, sect)) goto end; } /* Try to look in other objects */ keys = hash_get_keys(&world.curjob->loaded, &keynbr); for (index = 0; index < keynbr; index++) { if (strstr(keys[index], E2DBG_ARGV0)) continue; parent = hash_get(&world.curjob->loaded, keys[index]); bsym = elfsh_get_metasym_by_name(parent, str); if (!bsym || !bsym->st_value) { elfsh_toggle_mode(); bsym = elfsh_get_metasym_by_name(parent, str); elfsh_toggle_mode(); if (bsym && bsym->st_value) { sect = elfsh_get_parent_section(parent, bsym->st_value, NULL); if (!elfsh_is_plt(parent, sect)) { sym = bsym; if (strstr(parent->name, "libc.so")) goto end; } if (!sym) sym = bsym; } } else { sect = elfsh_get_parent_section(parent, bsym->st_value, NULL); if (!elfsh_is_plt(parent, sect)) { sym = bsym; if (strstr(parent->name, "libc.so")) goto end; } if (!sym) sym = bsym; } #if __DEBUG_BP__ printf("BPSym after %-30s = " XFMT "\n", parent->name, (eresi_Addr) sym); #endif } /* Return error or success, dont forget to free the keys */ end: if (keys) hash_free_keys(keys); if (!sym || !sym->st_value) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "No symbol by that name in the current file", 0); addr = sym->st_value; if (elfsh_get_objtype(parent->hdr) == ET_DYN) { #if __DEBUG_BP__ printf(" [*] Adding base addr " XFMT " of ET_DYN %s\n", parent->rhdr.base, parent->name); #endif addr += parent->rhdr.base; } #if __DEBUG_BP__ printf(" [*] Will set breakpoint on " XFMT " (parent = %s) \n", addr, parent->name); #endif PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, addr); }