mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-04 11:43:39 +00:00
Fix regression logic in agv and update help
This commit is contained in:
parent
7c0f154dea
commit
90fee6d5dd
178
libr/core/anal.c
178
libr/core/anal.c
@ -3155,181 +3155,3 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
|
||||
free (op.mnemonic);
|
||||
r_cons_break_end ();
|
||||
}
|
||||
|
||||
#define VTABLE_BUFF_SIZE 10
|
||||
|
||||
typedef struct vtable_info_t {
|
||||
ut64 saddr; //starting address
|
||||
int methods;
|
||||
RList* funtions;
|
||||
} vtable_info;
|
||||
|
||||
static RList* getVtableMethods(RCore *core, vtable_info *table) {
|
||||
RList* vtableMethods = r_list_new ();
|
||||
if (table && core && vtableMethods) {
|
||||
int curMethod = 0;
|
||||
int totalMethods = table->methods;
|
||||
ut64 startAddress = table->saddr;
|
||||
int bits = r_config_get_i (core->config, "asm.bits");
|
||||
int wordSize = bits / 8;
|
||||
while (curMethod < totalMethods) {
|
||||
ut64 curAddressValue = r_io_read_i (core->io, startAddress, 8);
|
||||
RAnalFunction *curFuntion = r_anal_get_fcn_in (core->anal, curAddressValue, 0);
|
||||
r_list_append (vtableMethods, curFuntion);
|
||||
startAddress += wordSize;
|
||||
curMethod++;
|
||||
}
|
||||
table->funtions = vtableMethods;
|
||||
return vtableMethods;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int inTextSection(RCore *core, ut64 curAddress) {
|
||||
//section of the curAddress
|
||||
RBinSection* value = r_bin_get_section_at (core->bin->cur->o, curAddress, true);
|
||||
//If the pointed value lies in .text section
|
||||
return value && !strcmp (value->name, ".text");
|
||||
}
|
||||
|
||||
static int valueInTextSection(RCore *core, ut64 curAddress) {
|
||||
//value at the current address
|
||||
ut64 curAddressValue = r_io_read_i (core->io, curAddress, 8);
|
||||
//if the value is in text section
|
||||
return inTextSection (core, curAddressValue);
|
||||
}
|
||||
|
||||
static int isVtableStart(RCore *core, ut64 curAddress) {
|
||||
RAsmOp asmop = {0};
|
||||
RAnalRef *xref;
|
||||
RListIter *xrefIter;
|
||||
ut8 buf[VTABLE_BUFF_SIZE];
|
||||
if (!curAddress || curAddress == UT64_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (valueInTextSection (core, curAddress)) {
|
||||
// total xref's to curAddress
|
||||
RList *xrefs = r_anal_xrefs_get (core->anal, curAddress);
|
||||
if (!r_list_empty (xrefs)) {
|
||||
r_list_foreach (xrefs, xrefIter, xref) {
|
||||
// section in which currenct xref lies
|
||||
if (inTextSection (core, xref->addr)) {
|
||||
r_io_read_at (core->io, xref->addr, buf, VTABLE_BUFF_SIZE);
|
||||
if (r_asm_disassemble (core->assembler, &asmop, buf, VTABLE_BUFF_SIZE) > 0) {
|
||||
if ((!strncmp (asmop.buf_asm, "mov", 3)) ||
|
||||
(!strncmp (asmop.buf_asm, "lea", 3))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RList* search_virtual_tables(RCore *core){
|
||||
if (!core) {
|
||||
return NULL;
|
||||
}
|
||||
ut64 startAddress;
|
||||
ut64 endAddress;
|
||||
RListIter * iter;
|
||||
RIOSection *section;
|
||||
RList *vtables = r_list_new();
|
||||
ut64 bits = r_config_get_i (core->config, "asm.bits");
|
||||
int wordSize = bits / 8;
|
||||
if (!vtables) {
|
||||
return NULL;
|
||||
}
|
||||
r_list_foreach (core->io->sections, iter, section) {
|
||||
if (!strcmp (section->name, ".rodata")) {
|
||||
ut8 *segBuff = calloc (1, section->size);
|
||||
r_io_read_at( core->io, section->offset, segBuff, section->size);
|
||||
startAddress = section->vaddr;
|
||||
endAddress = startAddress + (section->size) - (bits/8);
|
||||
while (startAddress <= endAddress) {
|
||||
if (isVtableStart (core, startAddress)) {
|
||||
vtable_info *vtable = calloc (1, sizeof(vtable_info));
|
||||
vtable->saddr = startAddress;
|
||||
int noOfMethods = 0;
|
||||
while (valueInTextSection (core, startAddress)) {
|
||||
noOfMethods++;
|
||||
startAddress += wordSize;
|
||||
}
|
||||
vtable->methods = noOfMethods;
|
||||
r_list_append (vtables, vtable);
|
||||
continue;
|
||||
}
|
||||
startAddress += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r_list_empty (vtables)) {
|
||||
// stripped binary?
|
||||
eprintf ("No virtual tables found\n");
|
||||
r_list_free (vtables);
|
||||
return NULL;
|
||||
}
|
||||
return vtables;
|
||||
}
|
||||
|
||||
R_API void r_core_anal_list_vtables(void *core, bool printJson) {
|
||||
ut64 bits = r_config_get_i (((RCore *)core)->config, "asm.bits");
|
||||
RList* vtables = search_virtual_tables ((RCore *)core);
|
||||
const char *noMethodName = "No Name found";
|
||||
RListIter* vtableMethodNameIter;
|
||||
RAnalFunction *curMethod;
|
||||
int wordSize = bits / 8;
|
||||
RListIter* vtableIter;
|
||||
vtable_info* table;
|
||||
|
||||
if (vtables) {
|
||||
if (printJson) {
|
||||
bool isFirstElement = true;
|
||||
r_cons_print ("[");
|
||||
r_list_foreach (vtables, vtableIter, table) {
|
||||
if (!isFirstElement) {
|
||||
r_cons_print (",");
|
||||
}
|
||||
r_cons_printf ("{\"offset\":%"PFMT64d",\"methods\":%d}",
|
||||
table->saddr, table->methods);
|
||||
isFirstElement = false;
|
||||
}
|
||||
r_cons_println ("]");
|
||||
} else {
|
||||
r_list_foreach (vtables, vtableIter, table) {
|
||||
ut64 vtableStartAddress = table->saddr;
|
||||
RList *vtableMethods = getVtableMethods ((RCore *)core, table);
|
||||
if (vtableMethods) {
|
||||
r_cons_printf ("\nVtable Found at 0x%08"PFMT64x"\n", vtableStartAddress);
|
||||
r_list_foreach (vtableMethods, vtableMethodNameIter, curMethod) {
|
||||
if (curMethod->name) {
|
||||
r_cons_printf ("0x%08"PFMT64x" : %s\n", vtableStartAddress, curMethod->name);
|
||||
} else {
|
||||
r_cons_printf ("0x%08"PFMT64x" : %s\n", vtableStartAddress, noMethodName);
|
||||
}
|
||||
vtableStartAddress += wordSize;
|
||||
}
|
||||
r_cons_newline ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
R_API void r_core_anal_list_vtables_all(void *core){
|
||||
RList* vtables = search_virtual_tables ((RCore *)core);
|
||||
RListIter* vtableIter;
|
||||
RListIter* vtableMethodNameIter;
|
||||
RAnalFunction* function;
|
||||
vtable_info* table;
|
||||
|
||||
r_list_foreach (vtables, vtableIter, table) {
|
||||
RList *vtableMethods = getVtableMethods ((RCore *)core, table);
|
||||
r_list_foreach (vtableMethods, vtableMethodNameIter, function) {
|
||||
// char *ret = r_str_newf ("vtable.%s", table->funtio);
|
||||
r_cons_printf ("f %s=0x%08"PFMT64x"\n", function->name, function->addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
178
libr/core/anal_vt.c
Normal file
178
libr/core/anal_vt.c
Normal file
@ -0,0 +1,178 @@
|
||||
#define VTABLE_BUFF_SIZE 10
|
||||
|
||||
typedef struct vtable_info_t {
|
||||
ut64 saddr; //starting address
|
||||
int methods;
|
||||
RList* funtions;
|
||||
} vtable_info;
|
||||
|
||||
static RList* getVtableMethods(RCore *core, vtable_info *table) {
|
||||
RList* vtableMethods = r_list_new ();
|
||||
if (table && core && vtableMethods) {
|
||||
int curMethod = 0;
|
||||
int totalMethods = table->methods;
|
||||
ut64 startAddress = table->saddr;
|
||||
int bits = r_config_get_i (core->config, "asm.bits");
|
||||
int wordSize = bits / 8;
|
||||
while (curMethod < totalMethods) {
|
||||
ut64 curAddressValue = r_io_read_i (core->io, startAddress, 8);
|
||||
RAnalFunction *curFuntion = r_anal_get_fcn_in (core->anal, curAddressValue, 0);
|
||||
r_list_append (vtableMethods, curFuntion);
|
||||
startAddress += wordSize;
|
||||
curMethod++;
|
||||
}
|
||||
table->funtions = vtableMethods;
|
||||
return vtableMethods;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int inTextSection(RCore *core, ut64 curAddress) {
|
||||
//section of the curAddress
|
||||
RBinSection* value = r_bin_get_section_at (core->bin->cur->o, curAddress, true);
|
||||
//If the pointed value lies in .text section
|
||||
return value && !strcmp (value->name, ".text");
|
||||
}
|
||||
|
||||
static int valueInTextSection(RCore *core, ut64 curAddress) {
|
||||
//value at the current address
|
||||
ut64 curAddressValue = r_io_read_i (core->io, curAddress, 8);
|
||||
//if the value is in text section
|
||||
return inTextSection (core, curAddressValue);
|
||||
}
|
||||
|
||||
static int isVtableStart(RCore *core, ut64 curAddress) {
|
||||
RAsmOp asmop = {0};
|
||||
RAnalRef *xref;
|
||||
RListIter *xrefIter;
|
||||
ut8 buf[VTABLE_BUFF_SIZE];
|
||||
if (!curAddress || curAddress == UT64_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (valueInTextSection (core, curAddress)) {
|
||||
// total xref's to curAddress
|
||||
RList *xrefs = r_anal_xrefs_get (core->anal, curAddress);
|
||||
if (!r_list_empty (xrefs)) {
|
||||
r_list_foreach (xrefs, xrefIter, xref) {
|
||||
// section in which currenct xref lies
|
||||
if (inTextSection (core, xref->addr)) {
|
||||
r_io_read_at (core->io, xref->addr, buf, VTABLE_BUFF_SIZE);
|
||||
if (r_asm_disassemble (core->assembler, &asmop, buf, VTABLE_BUFF_SIZE) > 0) {
|
||||
if ((!strncmp (asmop.buf_asm, "mov", 3)) ||
|
||||
(!strncmp (asmop.buf_asm, "lea", 3))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RList* search_virtual_tables(RCore *core){
|
||||
if (!core) {
|
||||
return NULL;
|
||||
}
|
||||
ut64 startAddress;
|
||||
ut64 endAddress;
|
||||
RListIter * iter;
|
||||
RIOSection *section;
|
||||
RList *vtables = r_list_new();
|
||||
ut64 bits = r_config_get_i (core->config, "asm.bits");
|
||||
int wordSize = bits / 8;
|
||||
if (!vtables) {
|
||||
return NULL;
|
||||
}
|
||||
r_list_foreach (core->io->sections, iter, section) {
|
||||
if (!strcmp (section->name, ".rodata")) {
|
||||
ut8 *segBuff = calloc (1, section->size);
|
||||
r_io_read_at( core->io, section->offset, segBuff, section->size);
|
||||
startAddress = section->vaddr;
|
||||
endAddress = startAddress + (section->size) - (bits/8);
|
||||
while (startAddress <= endAddress) {
|
||||
if (isVtableStart (core, startAddress)) {
|
||||
vtable_info *vtable = calloc (1, sizeof(vtable_info));
|
||||
vtable->saddr = startAddress;
|
||||
int noOfMethods = 0;
|
||||
while (valueInTextSection (core, startAddress)) {
|
||||
noOfMethods++;
|
||||
startAddress += wordSize;
|
||||
}
|
||||
vtable->methods = noOfMethods;
|
||||
r_list_append (vtables, vtable);
|
||||
continue;
|
||||
}
|
||||
startAddress += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r_list_empty (vtables)) {
|
||||
// stripped binary?
|
||||
eprintf ("No virtual tables found\n");
|
||||
r_list_free (vtables);
|
||||
return NULL;
|
||||
}
|
||||
return vtables;
|
||||
}
|
||||
|
||||
R_API void r_core_anal_list_vtables(void *core, bool printJson) {
|
||||
ut64 bits = r_config_get_i (((RCore *)core)->config, "asm.bits");
|
||||
RList* vtables = search_virtual_tables ((RCore *)core);
|
||||
const char *noMethodName = "No Name found";
|
||||
RListIter* vtableMethodNameIter;
|
||||
RAnalFunction *curMethod;
|
||||
int wordSize = bits / 8;
|
||||
RListIter* vtableIter;
|
||||
vtable_info* table;
|
||||
|
||||
if (vtables) {
|
||||
if (printJson) {
|
||||
bool isFirstElement = true;
|
||||
r_cons_print ("[");
|
||||
r_list_foreach (vtables, vtableIter, table) {
|
||||
if (!isFirstElement) {
|
||||
r_cons_print (",");
|
||||
}
|
||||
r_cons_printf ("{\"offset\":%"PFMT64d",\"methods\":%d}",
|
||||
table->saddr, table->methods);
|
||||
isFirstElement = false;
|
||||
}
|
||||
r_cons_println ("]");
|
||||
} else {
|
||||
r_list_foreach (vtables, vtableIter, table) {
|
||||
ut64 vtableStartAddress = table->saddr;
|
||||
RList *vtableMethods = getVtableMethods ((RCore *)core, table);
|
||||
if (vtableMethods) {
|
||||
r_cons_printf ("\nVtable Found at 0x%08"PFMT64x"\n", vtableStartAddress);
|
||||
r_list_foreach (vtableMethods, vtableMethodNameIter, curMethod) {
|
||||
if (curMethod->name) {
|
||||
r_cons_printf ("0x%08"PFMT64x" : %s\n", vtableStartAddress, curMethod->name);
|
||||
} else {
|
||||
r_cons_printf ("0x%08"PFMT64x" : %s\n", vtableStartAddress, noMethodName);
|
||||
}
|
||||
vtableStartAddress += wordSize;
|
||||
}
|
||||
r_cons_newline ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void r_core_anal_list_vtables_all(void *core) {
|
||||
RList* vtables = search_virtual_tables ((RCore *)core);
|
||||
RListIter* vtableIter;
|
||||
RListIter* vtableMethodNameIter;
|
||||
RAnalFunction* function;
|
||||
vtable_info* table;
|
||||
|
||||
r_list_foreach (vtables, vtableIter, table) {
|
||||
RList *vtableMethods = getVtableMethods ((RCore *)core, table);
|
||||
r_list_foreach (vtableMethods, vtableMethodNameIter, function) {
|
||||
// char *ret = r_str_newf ("vtable.%s", table->funtio);
|
||||
r_cons_printf ("f %s=0x%08"PFMT64x"\n", function->name, function->addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
#include "r_util.h"
|
||||
#include "r_core.h"
|
||||
|
||||
/* hacky inclusion */
|
||||
#include "anal_vt.c"
|
||||
|
||||
/* better aac for windows-x86-32 */
|
||||
#define JAYRO_03 0
|
||||
|
||||
@ -3920,7 +3923,7 @@ static void cmd_anal_graph(RCore *core, const char *input) {
|
||||
"agn", "[?] title body", "Add a node to the current graph",
|
||||
"ags", " [addr]", "output simple graphviz call graph of function (only bb offset)",
|
||||
"agt", " [addr]", "find paths from current offset to given address",
|
||||
"agv", "[acdltfl] [a]", "view function using graphviz",
|
||||
"agv", "", "Show function graph in web/png (see graph.web and cmd.graph) or agf for asciiart",
|
||||
NULL };
|
||||
|
||||
switch (input[0]) {
|
||||
@ -3988,15 +3991,23 @@ static void cmd_anal_graph(RCore *core, const char *input) {
|
||||
R_CORE_ANAL_GRAPHBODY | R_CORE_ANAL_GRAPHDIFF);
|
||||
break;
|
||||
case 'v': // "agv"
|
||||
r_core_cmd0 (core, "=H /graph/");
|
||||
if (r_config_get_i (core->config, "graph.web")) {
|
||||
r_core_cmd0 (core, "=H /graph/");
|
||||
} else {
|
||||
const char *cmd = r_config_get (core->config, "cmd.graph");
|
||||
if (cmd && *cmd) {
|
||||
r_core_cmd0 (core, cmd);
|
||||
} else {
|
||||
r_core_cmd0 (core, "agf");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '?': // "ag?"
|
||||
r_core_cmd_help (core, help_msg);
|
||||
break;
|
||||
case ' ': // "ag"
|
||||
arg = strchr (input, ' ');
|
||||
if (arg) arg++;
|
||||
r_core_anal_graph (core, r_num_math (core->num, arg),
|
||||
r_core_anal_graph (core, r_num_math (core->num, arg? arg + 1: NULL),
|
||||
R_CORE_ANAL_GRAPHBODY);
|
||||
break;
|
||||
case 0:
|
||||
|
Loading…
Reference in New Issue
Block a user