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.'
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

View File

@ -82,13 +82,28 @@ static int is_bin(const ut8 *buf, int size) {
// XXX: optimize by removing all strlens here
R_API char *r_anal_data_to_string (RAnalData *d) {
int i, idx, mallocsz = 256;
ut32 n32 = (ut32)d->ptr;
char *line = malloc (mallocsz);
int i, len, idx, mallocsz = 1024;
ut32 n32;
char *line;
if (!d) return NULL;
line = malloc (mallocsz);
snprintf (line, mallocsz, "0x%08"PFMT64x" ", d->addr);
for (i=0, idx = strlen (line); i<d->len; i++) {
snprintf (line+idx, mallocsz-idx, "%02x", d->buf[i]);
n32 = (ut32)d->ptr;
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;
msz -= 2;
}
strcat (line, " ");
idx += 2;
@ -117,6 +132,12 @@ R_API char *r_anal_data_to_string (RAnalData *d) {
case R_ANAL_DATA_TYPE_HEADER:
strcat (line, "header");
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:
strcat (line, "unknown");
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->type = type;
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;
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 word = R_MIN (8, bits/8);
if (size<4)
return NULL;
if (size >= word && is_invalid (buf, word))
return r_anal_data_new (addr, R_ANAL_DATA_TYPE_INVALID,
-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))
return r_anal_data_new (addr, R_ANAL_DATA_TYPE_NULL,
0, buf, word);
-1, buf, word);
if (is_bin (buf, size))
return r_anal_data_new (addr, R_ANAL_DATA_TYPE_HEADER, -1,
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;
for (i = j = 0; i<len; j++) {
data = r_anal_data (a, addr+i, buf+i, len-i);
if (data == NULL) continue;
if (data == NULL) {
i+= word;
continue;
}
switch (data->type) {
case R_ANAL_DATA_TYPE_INVALID:
inv++;
@ -238,7 +296,9 @@ R_API const char *r_anal_data_kind (RAnal *a, ut64 addr, const ut8 *buf, int len
i += word;
break;
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++;
break;
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)) {
/* Bad sh_link ! */
if(bin->shdr[i].sh_link >= bin->ehdr.e_shnum)
if (bin->shdr[i].sh_link >= bin->ehdr.e_shnum)
continue;
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);
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
perror ("malloc (syms)");
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);
}
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) {
int use_getopt = 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;
int i, j;
count = R_MIN (count, len);
//if (addr != core->offset) {
buf = malloc (len);
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);
r_cons_printf ("%s\n", str);
switch (d->type) {
case R_ANAL_DATA_TYPE_POINTER:
r_cons_printf ("`- ");
dstaddr = r_mem_get_num (buf+i, word, !endi);
if (depth>0)
r_core_anal_data (core, dstaddr, 1, depth-1);
i += word;
break;
case R_ANAL_DATA_TYPE_STRING:
i += strlen ((const char*)buf+i)+1;
break;
default:
if (d) {
switch (d->type) {
case R_ANAL_DATA_TYPE_POINTER:
r_cons_printf ("`- ");
dstaddr = r_mem_get_num (buf+i, word, !endi);
if (depth>0)
r_core_anal_data (core, dstaddr, 1, depth-1);
i += word;
break;
case R_ANAL_DATA_TYPE_STRING:
buf[len] = 0;
i += strlen ((const char*)buf+i)+1;
break;
default:
if (d->len>3) i += d->len;
else i+= word;
}
} else {
i += word;
}
free (str);

View File

@ -779,6 +779,18 @@ void cmd_anal_reg(RCore *core, const char *str) {
use_color = NULL;
}
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':
r_reg_arena_zero (core->anal->reg);
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) {
const char *ptr;
RCore *core = (RCore *)data;
@ -1061,6 +1124,22 @@ static int cmd_anal(void *data, const char *input) {
free (buf);
} else eprintf ("Usage: ab [hexpair-bytes]\n");
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':
cmd_anal_reg (core, input+1);
break;
@ -1769,7 +1848,7 @@ static int cmd_anal(void *data, const char *input) {
case '\0':
{
//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;
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)",
"drc", " [name]", "Related to conditional flag 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",
"dro", "", "Show previous (old) values of registers",
"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);
}
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':
{ // WORK IN PROGRESS // DEBUG COMMAND
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",
"\nConfiguration:", "", "",
"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.from = 0", "start address",
"e", " search.to = 0", "end address",

View File

@ -58,15 +58,27 @@ typedef struct r_anal_meta_item_t {
enum {
R_ANAL_DATA_TYPE_NULL = 0,
R_ANAL_DATA_TYPE_STRING = 1,
R_ANAL_DATA_TYPE_WIDE_STRING = 2,
R_ANAL_DATA_TYPE_POINTER = 3,
R_ANAL_DATA_TYPE_NUMBER = 4,
R_ANAL_DATA_TYPE_INVALID = 5,
R_ANAL_DATA_TYPE_HEADER = 6,
R_ANAL_DATA_TYPE_UNKNOWN = 7,
R_ANAL_DATA_TYPE_UNKNOWN = 1,
R_ANAL_DATA_TYPE_STRING = 2,
R_ANAL_DATA_TYPE_WIDE_STRING = 3,
R_ANAL_DATA_TYPE_POINTER = 4,
R_ANAL_DATA_TYPE_NUMBER = 5,
R_ANAL_DATA_TYPE_INVALID = 6,
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) |
* ( RANAL_VAR_TYPE_SIGNED & RANAL_VAR_TYPE_SIGN_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 */
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_hint_list (RAnal *a, int mode);
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 size;
ut64 vsize;
int rwx;
int rwx; // rename to perm? like in rdebug? what about rbin?
int id;
/* */
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(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_setv(RReg *reg, const char *name, ut64 val);
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;
}
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.cmd ("b", function (o) {
var ret = false;