Add 'ai' - address info, Enhace 'ad' (support patterns and sequences)

- ai shows: exec,read,write,flag,func,stack,heap,reg
- Add r_reg_regset_get()
- Implement r2.cmdj in r2.js
This commit is contained in:
pancake 2014-10-15 02:24:22 +02:00
parent 676ed9e861
commit 42232354a7
13 changed files with 297 additions and 32 deletions

View File

@ -1,4 +1,3 @@
Do you want to perform more than one search at a time? '> /k0 keyword1', '> /k1 keyword2' and '> /r 0-1'
Disassembly not pretty enough? Try changing the values with 'e asm.' Disassembly not pretty enough? Try changing the values with 'e asm.'
Have you setup your ~/.radare2rc today? Have you setup your ~/.radare2rc today?
You can mark an offset in visual mode with the cursor and the ',' key. Later press '.' to go back You can mark an offset in visual mode with the cursor and the ',' key. Later press '.' to go back

View File

@ -82,13 +82,28 @@ static int is_bin(const ut8 *buf, int size) {
// XXX: optimize by removing all strlens here // XXX: optimize by removing all strlens here
R_API char *r_anal_data_to_string (RAnalData *d) { R_API char *r_anal_data_to_string (RAnalData *d) {
int i, idx, mallocsz = 256; int i, len, idx, mallocsz = 1024;
ut32 n32 = (ut32)d->ptr; ut32 n32;
char *line = malloc (mallocsz); char *line;
if (!d) return NULL;
line = malloc (mallocsz);
snprintf (line, mallocsz, "0x%08"PFMT64x" ", d->addr); snprintf (line, mallocsz, "0x%08"PFMT64x" ", d->addr);
for (i=0, idx = strlen (line); i<d->len; i++) { n32 = (ut32)d->ptr;
snprintf (line+idx, mallocsz-idx, "%02x", d->buf[i]); len = R_MIN (d->len, 8);
for (i=0, idx = strlen (line); i<len; i++) {
int msz = mallocsz-idx;
if (msz>1) {
snprintf (line+idx, msz, "%02x", d->buf[i]);
idx += 2;
}
}
if (i>0 && d->len> len) {
int msz = mallocsz-idx;
snprintf (line+idx, msz, "..");
idx += 2; idx += 2;
msz -= 2;
} }
strcat (line, " "); strcat (line, " ");
idx += 2; idx += 2;
@ -117,6 +132,12 @@ R_API char *r_anal_data_to_string (RAnalData *d) {
case R_ANAL_DATA_TYPE_HEADER: case R_ANAL_DATA_TYPE_HEADER:
strcat (line, "header"); strcat (line, "header");
break; break;
case R_ANAL_DATA_TYPE_SEQUENCE:
strcat (line, "sequence");
break;
case R_ANAL_DATA_TYPE_PATTERN:
strcat (line, "pattern");
break;
case R_ANAL_DATA_TYPE_UNKNOWN: case R_ANAL_DATA_TYPE_UNKNOWN:
strcat (line, "unknown"); strcat (line, "unknown");
break; break;
@ -164,7 +185,14 @@ R_API RAnalData *r_anal_data_new (ut64 addr, int type, ut64 n, const ut8 *buf, i
ad->addr = addr; ad->addr = addr;
ad->type = type; ad->type = type;
ad->str = NULL; ad->str = NULL;
ad->len = l; switch (type) {
case R_ANAL_DATA_TYPE_PATTERN:
case R_ANAL_DATA_TYPE_SEQUENCE:
ad->len = len;
break;
default:
ad->len = l;
}
ad->ptr = n; ad->ptr = n;
return ad; return ad;
} }
@ -184,12 +212,39 @@ R_API RAnalData *r_anal_data (RAnal *anal, ut64 addr, const ut8 *buf, int size)
int endi = !anal->big_endian; int endi = !anal->big_endian;
int word = R_MIN (8, bits/8); int word = R_MIN (8, bits/8);
if (size<4)
return NULL;
if (size >= word && is_invalid (buf, word)) if (size >= word && is_invalid (buf, word))
return r_anal_data_new (addr, R_ANAL_DATA_TYPE_INVALID, return r_anal_data_new (addr, R_ANAL_DATA_TYPE_INVALID,
-1, buf, word); -1, buf, word);
{
int i, len = R_MIN (size, 64);
int is_pattern = 0;
int is_sequence = 0;
char ch = buf[0];
char ch2 = ch+1;
for (i=1; i<len; i++) {
if (ch2 == buf[i]) {
ch2++;
is_sequence++;
} else is_sequence = 0;
if (ch==buf[i]) {
is_pattern++;
}
}
//eprintf ("%d %d %d %d\n", is_sequence, is_pattern , len, size);
if (is_sequence>len-2) {
return r_anal_data_new (addr, R_ANAL_DATA_TYPE_SEQUENCE, -1,
buf, is_sequence);
}
if (is_pattern>len-2) {
return r_anal_data_new (addr, R_ANAL_DATA_TYPE_PATTERN, -1,
buf, is_pattern);
}
}
if (size >= word && is_null (buf, word)) if (size >= word && is_null (buf, word))
return r_anal_data_new (addr, R_ANAL_DATA_TYPE_NULL, return r_anal_data_new (addr, R_ANAL_DATA_TYPE_NULL,
0, buf, word); -1, buf, word);
if (is_bin (buf, size)) if (is_bin (buf, size))
return r_anal_data_new (addr, R_ANAL_DATA_TYPE_HEADER, -1, return r_anal_data_new (addr, R_ANAL_DATA_TYPE_HEADER, -1,
buf, word); buf, word);
@ -223,7 +278,10 @@ R_API const char *r_anal_data_kind (RAnal *a, ut64 addr, const ut8 *buf, int len
int word = a->bits /8; int word = a->bits /8;
for (i = j = 0; i<len; j++) { for (i = j = 0; i<len; j++) {
data = r_anal_data (a, addr+i, buf+i, len-i); data = r_anal_data (a, addr+i, buf+i, len-i);
if (data == NULL) continue; if (data == NULL) {
i+= word;
continue;
}
switch (data->type) { switch (data->type) {
case R_ANAL_DATA_TYPE_INVALID: case R_ANAL_DATA_TYPE_INVALID:
inv++; inv++;
@ -238,7 +296,9 @@ R_API const char *r_anal_data_kind (RAnal *a, ut64 addr, const ut8 *buf, int len
i += word; i += word;
break; break;
case R_ANAL_DATA_TYPE_STRING: case R_ANAL_DATA_TYPE_STRING:
i += data->len; //strlen ((const char*)buf+i)+1; if (data->len>0) {
i += data->len; //strlen ((const char*)buf+i)+1;
} else i+=word;
str++; str++;
break; break;
default: default:

View File

@ -751,7 +751,7 @@ struct r_bin_elf_reloc_t* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t
if (bin->shdr[i].sh_type == (bin->ehdr.e_type == ET_REL ? SHT_SYMTAB : SHT_DYNSYM)) { if (bin->shdr[i].sh_type == (bin->ehdr.e_type == ET_REL ? SHT_SYMTAB : SHT_DYNSYM)) {
/* Bad sh_link ! */ /* Bad sh_link ! */
if(bin->shdr[i].sh_link >= bin->ehdr.e_shnum) if (bin->shdr[i].sh_link >= bin->ehdr.e_shnum)
continue; continue;
bin->strtab_section = &bin->shdr[bin->shdr[i].sh_link]; bin->strtab_section = &bin->shdr[bin->shdr[i].sh_link];
@ -772,6 +772,12 @@ struct r_bin_elf_reloc_t* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t
free (strtab); free (strtab);
return NULL; return NULL;
} }
if (bin->shdr[i].sh_size > bin->size) {
eprintf ("Warning: alloc (invalid shsize)\n");
free (sym);
free (strtab);
return NULL;
}
if ((sym = (Elf_(Sym) *)malloc (1+bin->shdr[i].sh_size)) == NULL) { // LEAKS if ((sym = (Elf_(Sym) *)malloc (1+bin->shdr[i].sh_size)) == NULL) { // LEAKS
perror ("malloc (syms)"); perror ("malloc (syms)");
free (strtab); free (strtab);

View File

@ -12,6 +12,71 @@ static void loganal(ut64 from, ut64 to) {
eprintf ("0x%08"PFMT64x" > 0x%08"PFMT64x"\r", from, to); eprintf ("0x%08"PFMT64x" > 0x%08"PFMT64x"\r", from, to);
} }
R_API ut64 r_core_anal_address (RCore *core, ut64 addr) {
ut64 types = 0;
RRegSet *rs = r_reg_regset_get (core->dbg->reg, R_REG_TYPE_GPR);
if (rs) {
RRegItem *r;
RListIter *iter;
r_list_foreach (rs->regs, iter, r) {
ut64 val = r_reg_getv (core->dbg->reg, r->name);
//r_cons_printf ("%s\n", r->name);
if (addr == val) {
types |= R_ANAL_ADDR_TYPE_REG;
break;
}
}
}
if (r_flag_get_i (core->flags, addr))
types |= R_ANAL_ADDR_TYPE_FLAG;
if (r_anal_get_fcn_in (core->anal, addr, 0))
types |= R_ANAL_ADDR_TYPE_FUNC;
// check registers
if (core->io->debug) {
RDebugMap *map;
RListIter *iter;
// use 'dm'
r_debug_map_sync (core->dbg);
r_list_foreach (core->dbg->maps, iter, map) {
if (addr >= map->addr && addr < map->addr_end) {
if (map->perm & R_IO_EXEC)
types |= R_ANAL_ADDR_TYPE_EXEC;
if (map->perm & R_IO_READ)
types |= R_ANAL_ADDR_TYPE_READ;
if (map->perm & R_IO_WRITE)
types |= R_ANAL_ADDR_TYPE_WRITE;
// find function
if (strstr (map->name, "heap"))
types |= R_ANAL_ADDR_TYPE_HEAP;
if (strstr (map->name, "stack"))
types |= R_ANAL_ADDR_TYPE_STACK;
break;
}
}
} else {
RIOSection *ios;
RListIter *iter;
// sections
r_list_foreach (core->io->sections, iter, ios) {
if (addr >= ios->vaddr && addr < (ios->vaddr+ios->vsize)) {
if (ios->rwx & R_IO_EXEC)
types |= R_ANAL_ADDR_TYPE_EXEC;
if (ios->rwx & R_IO_READ)
types |= R_ANAL_ADDR_TYPE_READ;
if (ios->rwx & R_IO_WRITE)
types |= R_ANAL_ADDR_TYPE_WRITE;
// find function
if (strstr (ios->name, "heap"))
types |= R_ANAL_ADDR_TYPE_HEAP;
if (strstr (ios->name, "stack"))
types |= R_ANAL_ADDR_TYPE_STACK;
// break;
}
}
}
return types;
}
R_API char *r_core_anal_fcn_autoname(RCore *core, ut64 addr) { R_API char *r_core_anal_fcn_autoname(RCore *core, ut64 addr) {
int use_getopt = 0; int use_getopt = 0;
int use_isatty = 0; int use_isatty = 0;
@ -1465,6 +1530,7 @@ R_API int r_core_anal_data (RCore *core, ut64 addr, int count, int depth) {
char *str; char *str;
int i, j; int i, j;
count = R_MIN (count, len);
//if (addr != core->offset) { //if (addr != core->offset) {
buf = malloc (len); buf = malloc (len);
if (buf == NULL) if (buf == NULL)
@ -1485,18 +1551,24 @@ R_API int r_core_anal_data (RCore *core, ut64 addr, int count, int depth) {
str = r_anal_data_to_string (d); str = r_anal_data_to_string (d);
r_cons_printf ("%s\n", str); r_cons_printf ("%s\n", str);
switch (d->type) { if (d) {
case R_ANAL_DATA_TYPE_POINTER: switch (d->type) {
r_cons_printf ("`- "); case R_ANAL_DATA_TYPE_POINTER:
dstaddr = r_mem_get_num (buf+i, word, !endi); r_cons_printf ("`- ");
if (depth>0) dstaddr = r_mem_get_num (buf+i, word, !endi);
r_core_anal_data (core, dstaddr, 1, depth-1); if (depth>0)
i += word; r_core_anal_data (core, dstaddr, 1, depth-1);
break; i += word;
case R_ANAL_DATA_TYPE_STRING: break;
i += strlen ((const char*)buf+i)+1; case R_ANAL_DATA_TYPE_STRING:
break; buf[len] = 0;
default: i += strlen ((const char*)buf+i)+1;
break;
default:
if (d->len>3) i += d->len;
else i+= word;
}
} else {
i += word; i += word;
} }
free (str); free (str);

View File

@ -779,6 +779,18 @@ void cmd_anal_reg(RCore *core, const char *str) {
use_color = NULL; use_color = NULL;
} }
switch (str[0]) { switch (str[0]) {
case 'l':
{
RRegSet *rs = r_reg_regset_get (core->anal->reg, R_REG_TYPE_GPR);
if (rs) {
RRegItem *r;
RListIter *iter;
r_list_foreach (rs->regs, iter, r) {
r_cons_printf ("%s\n", r->name);
}
}
}
break;
case '0': case '0':
r_reg_arena_zero (core->anal->reg); r_reg_arena_zero (core->anal->reg);
break; break;
@ -1041,6 +1053,57 @@ sleep (1);
} }
} }
static void cmd_address_info(RCore *core, const char *addrstr, int fmt) {
ut64 addr, type;
if (!addrstr || !*addrstr) {
addr = core->offset;
} else {
addr = r_num_math (core->num, addrstr);
}
type = r_core_anal_address (core, addr);
int isp = 0;
switch(fmt) {
case 'j':
#define COMMA isp++?",":""
r_cons_printf ("{");
if (type & R_ANAL_ADDR_TYPE_EXEC)
r_cons_printf ("%s\"exec\":true", COMMA);
if (type & R_ANAL_ADDR_TYPE_READ)
r_cons_printf ("%s\"read\":true", COMMA);
if (type & R_ANAL_ADDR_TYPE_WRITE)
r_cons_printf ("%s\"write\":true", COMMA);
if (type & R_ANAL_ADDR_TYPE_FLAG)
r_cons_printf ("%s\"flag\":true", COMMA);
if (type & R_ANAL_ADDR_TYPE_FUNC)
r_cons_printf ("%s\"func\":true", COMMA);
if (type & R_ANAL_ADDR_TYPE_STACK)
r_cons_printf ("%s\"stack\":true", COMMA);
if (type & R_ANAL_ADDR_TYPE_HEAP)
r_cons_printf ("%s\"heap\":true", COMMA);
if (type & R_ANAL_ADDR_TYPE_REG)
r_cons_printf ("%s\"reg\":true", COMMA);
r_cons_printf ("}");
break;
default:
if (type & R_ANAL_ADDR_TYPE_EXEC)
r_cons_printf ("exec\n");
if (type & R_ANAL_ADDR_TYPE_READ)
r_cons_printf ("read\n");
if (type & R_ANAL_ADDR_TYPE_WRITE)
r_cons_printf ("write\n");
if (type & R_ANAL_ADDR_TYPE_FLAG)
r_cons_printf ("flag\n");
if (type & R_ANAL_ADDR_TYPE_FUNC)
r_cons_printf ("func\n");
if (type & R_ANAL_ADDR_TYPE_STACK)
r_cons_printf ("stack\n");
if (type & R_ANAL_ADDR_TYPE_HEAP)
r_cons_printf ("heap\n");
if (type & R_ANAL_ADDR_TYPE_REG)
r_cons_printf ("reg\n");
}
}
static int cmd_anal(void *data, const char *input) { static int cmd_anal(void *data, const char *input) {
const char *ptr; const char *ptr;
RCore *core = (RCore *)data; RCore *core = (RCore *)data;
@ -1061,6 +1124,22 @@ static int cmd_anal(void *data, const char *input) {
free (buf); free (buf);
} else eprintf ("Usage: ab [hexpair-bytes]\n"); } else eprintf ("Usage: ab [hexpair-bytes]\n");
break; break;
case 'i':
switch (input[1]) {
case '?':
eprintf ("Usage: ai @ rsp\n");
break;
case ' ':
cmd_address_info (core, input+1, 0);
break;
case 'j':
cmd_address_info (core, input+2, 'j');
break;
default:
cmd_address_info (core, NULL, 0);
break;
}
break;
case 'r': case 'r':
cmd_anal_reg (core, input+1); cmd_anal_reg (core, input+1);
break; break;
@ -1769,7 +1848,7 @@ static int cmd_anal(void *data, const char *input) {
case '\0': case '\0':
{ {
//int word = core->assembler->bits / 8; //int word = core->assembler->bits / 8;
r_core_anal_data (core, core->offset, core->blocksize, 1); r_core_anal_data (core, core->offset, 2+(core->blocksize/4), 1);
} }
break; break;
default:{ default:{

View File

@ -518,6 +518,7 @@ static void cmd_debug_reg(RCore *core, const char *str) {
"drb", " [type]", "Display hexdump of gpr arena (WIP)", "drb", " [type]", "Display hexdump of gpr arena (WIP)",
"drc", " [name]", "Related to conditional flag registers", "drc", " [name]", "Related to conditional flag registers",
"drd", "", "Show only different registers", "drd", "", "Show only different registers",
"drl", "", "List all register names",
"drn", " <pc>", "Get regname for pc,sp,bp,a0-3,zf,cf,of,sg", "drn", " <pc>", "Get regname for pc,sp,bp,a0-3,zf,cf,of,sg",
"dro", "", "Show previous (old) values of registers", "dro", "", "Show previous (old) values of registers",
"drp", " <file>", "Load register metadata file", "drp", " <file>", "Load register metadata file",
@ -533,6 +534,19 @@ static void cmd_debug_reg(RCore *core, const char *str) {
r_core_cmd_help (core, help_message); r_core_cmd_help (core, help_message);
} }
break; break;
case 'l':
//r_core_cmd0 (core, "drp~[1]");
{
RRegSet *rs = r_reg_regset_get (core->dbg->reg, R_REG_TYPE_GPR);
if (rs) {
RRegItem *r;
RListIter *iter;
r_list_foreach (rs->regs, iter, r) {
r_cons_printf ("%s\n", r->name);
}
}
}
break;
case 'b': case 'b':
{ // WORK IN PROGRESS // DEBUG COMMAND { // WORK IN PROGRESS // DEBUG COMMAND
int len; int len;

View File

@ -1068,6 +1068,7 @@ r_anal_esil_set_op (core->anal->esil, "AddressInfo", esil_search_address_info);
"/z"," min max", "search for strings of given size", "/z"," min max", "search for strings of given size",
"\nConfiguration:", "", "", "\nConfiguration:", "", "",
"e", " cmd.hit = x", "command to execute on every search hit", "e", " cmd.hit = x", "command to execute on every search hit",
"e", " search.in = ?", "specify where to search stuff (depends on .from/.to)",
"e", " search.align = 4", "only catch aligned search hits", "e", " search.align = 4", "only catch aligned search hits",
"e", " search.from = 0", "start address", "e", " search.from = 0", "start address",
"e", " search.to = 0", "end address", "e", " search.to = 0", "end address",

View File

@ -58,15 +58,27 @@ typedef struct r_anal_meta_item_t {
enum { enum {
R_ANAL_DATA_TYPE_NULL = 0, R_ANAL_DATA_TYPE_NULL = 0,
R_ANAL_DATA_TYPE_STRING = 1, R_ANAL_DATA_TYPE_UNKNOWN = 1,
R_ANAL_DATA_TYPE_WIDE_STRING = 2, R_ANAL_DATA_TYPE_STRING = 2,
R_ANAL_DATA_TYPE_POINTER = 3, R_ANAL_DATA_TYPE_WIDE_STRING = 3,
R_ANAL_DATA_TYPE_NUMBER = 4, R_ANAL_DATA_TYPE_POINTER = 4,
R_ANAL_DATA_TYPE_INVALID = 5, R_ANAL_DATA_TYPE_NUMBER = 5,
R_ANAL_DATA_TYPE_HEADER = 6, R_ANAL_DATA_TYPE_INVALID = 6,
R_ANAL_DATA_TYPE_UNKNOWN = 7, R_ANAL_DATA_TYPE_HEADER = 7,
R_ANAL_DATA_TYPE_SEQUENCE = 8,
R_ANAL_DATA_TYPE_PATTERN = 9,
}; };
// used from core/anal.c
#define R_ANAL_ADDR_TYPE_EXEC 1
#define R_ANAL_ADDR_TYPE_READ 2
#define R_ANAL_ADDR_TYPE_WRITE 4
#define R_ANAL_ADDR_TYPE_FLAG 8
#define R_ANAL_ADDR_TYPE_FUNC 16
#define R_ANAL_ADDR_TYPE_HEAP 32
#define R_ANAL_ADDR_TYPE_STACK 64
#define R_ANAL_ADDR_TYPE_REG 128
/* type = (R_ANAL_VAR_TYPE_BYTE & R_ANAL_VAR_TYPE_SIZE_MASK) | /* type = (R_ANAL_VAR_TYPE_BYTE & R_ANAL_VAR_TYPE_SIZE_MASK) |
* ( RANAL_VAR_TYPE_SIGNED & RANAL_VAR_TYPE_SIGN_MASK) | * ( RANAL_VAR_TYPE_SIGNED & RANAL_VAR_TYPE_SIGN_MASK) |
* ( RANAL_VAR_TYPE_CONST & RANAL_VAR_TYPE_MODIFIER_MASK) * ( RANAL_VAR_TYPE_CONST & RANAL_VAR_TYPE_MODIFIER_MASK)

View File

@ -277,6 +277,7 @@ R_API char *r_core_disassemble_bytes(RCore *core, ut64 addr, int b);
/* anal.c */ /* anal.c */
R_API RAnalOp* r_core_anal_op(RCore *core, ut64 addr); R_API RAnalOp* r_core_anal_op(RCore *core, ut64 addr);
R_API ut64 r_core_anal_address (RCore *core, ut64 addr);
R_API void r_core_anal_undefine (RCore *core, ut64 off); R_API void r_core_anal_undefine (RCore *core, ut64 off);
R_API void r_core_anal_hint_list (RAnal *a, int mode); R_API void r_core_anal_hint_list (RAnal *a, int mode);
R_API int r_core_anal_search(RCore *core, ut64 from, ut64 to, ut64 ref); R_API int r_core_anal_search(RCore *core, ut64 from, ut64 to, ut64 ref);

View File

@ -51,7 +51,7 @@ typedef struct r_io_section_t {
ut64 vaddr; ut64 vaddr;
ut64 size; ut64 size;
ut64 vsize; ut64 vsize;
int rwx; int rwx; // rename to perm? like in rdebug? what about rbin?
int id; int id;
/* */ /* */
int arch; int arch;

View File

@ -108,6 +108,7 @@ R_API int r_reg_set_name(RReg *reg, int role, const char *name);
R_API int r_reg_set_profile_string(RReg *reg, const char *profile); R_API int r_reg_set_profile_string(RReg *reg, const char *profile);
R_API int r_reg_set_profile(RReg *reg, const char *profile); R_API int r_reg_set_profile(RReg *reg, const char *profile);
R_API RRegSet *r_reg_regset_get(RReg *r, int type);
R_API ut64 r_reg_getv(RReg *reg, const char *name); R_API ut64 r_reg_getv(RReg *reg, const char *name);
R_API ut64 r_reg_setv(RReg *reg, const char *name, ut64 val); R_API ut64 r_reg_setv(RReg *reg, const char *name, ut64 val);
R_API const char *r_reg_get_type(int idx); R_API const char *r_reg_get_type(int idx);

View File

@ -406,3 +406,13 @@ R_API RRegItem *r_reg_next_diff(RReg *reg, int type, const ut8* buf, int buflen,
} }
return NULL; return NULL;
} }
R_API RRegSet *r_reg_regset_get(RReg *r, int type) {
RRegSet *rs;
if (type<0 || type>=R_REG_TYPE_LAST)
return NULL;
rs = &r->regset[type];
if (rs->arena)
return rs;
return NULL;
}

View File

@ -225,6 +225,16 @@ r2.cmd = function (c, cb) {
} }
} }
r2.cmdj = function (c, cb) {
r2.cmd (c, function(x) {
try {
cb (JSON.parse(x));
} catch(e) {
cb (null);
}
});
}
r2.alive = function (cb) { r2.alive = function (cb) {
r2.cmd ("b", function (o) { r2.cmd ("b", function (o) {
var ret = false; var ret = false;