Honor anal.strings in aav ##anal

This commit is contained in:
pancake 2019-08-29 16:47:18 +02:00
parent 09ad4c68a9
commit 3dd08def00
4 changed files with 186 additions and 169 deletions

View File

@ -1148,7 +1148,7 @@ static int sh_set_reg_profile(RAnal* anal) {
static int archinfo(RAnal *anal, int q) {
if (q == R_ANAL_ARCHINFO_ALIGN) {
return 4;
// return 4;
}
return 2; /* :) */
}

View File

@ -27,7 +27,6 @@ enum {
R2_ARCH_ARM64
} R2Arch;
static void add_string_ref(RCore *core, ut64 xref_to);
static int cmpfcn(const void *_a, const void *_b);
static void loganal(ut64 from, ut64 to, int depth) {
@ -121,10 +120,13 @@ static RCore *mycore = NULL;
// XXX: copypaste from anal/data.c
#define MINLEN 1
static int is_string(const ut8 *buf, int size, int *len) {
int i;
int i, fakeLen = 0;
if (size < 1) {
return 0;
}
if (!len) {
len = &fakeLen;
}
if (size > 3 && buf[0] && !buf[1] && buf[2] && !buf[3]) {
*len = 1; // XXX: TODO: Measure wide string length
return 2; // is wide
@ -4486,10 +4488,34 @@ R_API void r_core_anal_fcn_merge(RCore *core, ut64 addr, ut64 addr2) {
}
}
R_API void r_core_anal_auto_merge(RCore *core, ut64 addr) {
/* TODO: implement me */
static bool esil_anal_stop = false;
static void cccb(void *u) {
esil_anal_stop = true;
eprintf ("^C\n");
}
static void add_string_ref(RCore *core, ut64 xref_from, ut64 xref_to) {
int len = 0;
if (xref_to == UT64_MAX || !xref_to) {
return;
}
if (!xref_from || xref_from == UT64_MAX) {
xref_from = core->anal->esil->address;
}
char *str_flagname = is_string_at (core, xref_to, &len);
if (str_flagname) {
r_anal_xrefs_set (core->anal, xref_from, xref_to, R_ANAL_REF_TYPE_DATA);
r_name_filter (str_flagname, -1);
char *flagname = sdb_fmt ("str.%s", str_flagname);
r_flag_space_push (core->flags, R_FLAGS_FS_STRINGS);
r_flag_set (core->flags, flagname, xref_to, len);
r_flag_space_pop (core->flags);
r_meta_add (core->anal, 's', xref_to, xref_to + len, str_flagname);
free (str_flagname);
}
}
static bool myvalid(RIO *io, ut64 addr) {
if (addr < 0x100) {
return false;
@ -4549,7 +4575,7 @@ static int esilbreak_mem_read(RAnalEsil *esil, ut64 addr, ut8 *buf, int len) {
str[0] = 0;
}
str[sizeof (str) - 1] = 0;
add_string_ref (mycore, refptr);
add_string_ref (mycore, esil->address, refptr);
esilbreak_last_data = UT64_MAX;
validRef = true;
}
@ -4563,31 +4589,6 @@ static int esilbreak_mem_read(RAnalEsil *esil, ut64 addr, ut8 *buf, int len) {
return 0; // fallback
}
static bool esil_anal_stop = false;
static void cccb(void *u) {
esil_anal_stop = true;
eprintf ("^C\n");
}
static void add_string_ref(RCore *core, ut64 xref_to) {
int len = 0;
if (xref_to == UT64_MAX || !xref_to) {
return;
}
char *str_flagname = is_string_at (core, xref_to, &len);
if (str_flagname) {
r_anal_xrefs_set (core->anal, core->anal->esil->address, xref_to, R_ANAL_REF_TYPE_DATA);
r_name_filter (str_flagname, -1);
char *flagname = sdb_fmt ("str.%s", str_flagname);
r_flag_space_push (core->flags, R_FLAGS_FS_STRINGS);
r_flag_set (core->flags, flagname, xref_to, len);
r_flag_space_pop (core->flags);
r_meta_add (core->anal, 's', xref_to, xref_to + len, str_flagname);
//r_cons_printf ("Cs %d @ 0x%"PFMT64x"\n", len, xref_to);
free (str_flagname);
}
}
static int esilbreak_reg_write(RAnalEsil *esil, const char *name, ut64 *val) {
if (!esil) {
return 0;
@ -4619,9 +4620,8 @@ static int esilbreak_reg_write(RAnalEsil *esil, const char *name, ut64 *val) {
}
}
if (core->assembler->bits == 32 && strstr (core->assembler->cur->name, "arm")) {
if ((!(at&1)) && r_io_is_valid_offset (anal->iob.io, at, 0)) { // !core->anal->opt.noncode)) {
add_string_ref (anal->coreb.core, at);
// r_anal_xrefs_set (core->anal, esil->address, at, R_ANAL_REF_TYPE_DATA);
if ((!(at & 1)) && r_io_is_valid_offset (anal->iob.io, at, 0)) { // !core->anal->opt.noncode)) {
add_string_ref (anal->coreb.core, esil->address, at);
}
}
return 0;
@ -4959,7 +4959,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
}
}
if (cfg_anal_strings) {
add_string_ref (core, op.ptr);
add_string_ref (core, op.addr, op.ptr);
}
break;
case R_ANAL_OP_TYPE_ADD:
@ -4975,9 +4975,9 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_DATA);
}
}
// if (cfg_anal_strings) {
add_string_ref (core, dst);
// }
if (cfg_anal_strings) {
add_string_ref (core, op.addr, dst);
}
} else if ((core->anal->bits == 32 && core->anal->cur && !strcmp (core->anal->cur->arch, "mips"))) {
ut64 dst = ESIL->cur;
if (!op.src[0] || !op.src[0]->reg || !op.src[0]->reg->name) {
@ -4996,7 +4996,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
if (CHECKREF (dst) || CHECKREF (cur)) {
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_DATA);
if (cfg_anal_strings) {
add_string_ref (core, dst);
add_string_ref (core, op.addr, dst);
}
if ((f = r_core_flag_get_by_spaces (core->flags, dst))) {
r_meta_set_string (core->anal, R_META_TYPE_COMMENT, cur, f->name);
@ -5021,7 +5021,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
if (myvalid (mycore->io, dst)) {
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_DATA);
if (cfg_anal_strings) {
add_string_ref (core, dst);
add_string_ref (core, op.addr, dst);
}
}
}
@ -5030,7 +5030,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
if (myvalid (mycore->io, dst)) {
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_DATA);
if (cfg_anal_strings) {
add_string_ref (core, dst);
add_string_ref (core, op.addr, dst);
}
}
}
@ -5091,6 +5091,150 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
r_reg_arena_pop (core->anal->reg);
}
static bool isValidAddress (RCore *core, ut64 addr) {
// check if address is mapped
RIOMap* map = r_io_map_get (core->io, addr);
if (!map) {
return false;
}
st64 fdsz = (st64)r_io_fd_size (core->io, map->fd);
if (fdsz > 0 && map->delta > fdsz) {
return false;
}
// check if associated file is opened
RIODesc *desc = r_io_desc_get (core->io, map->fd);
if (!desc) {
return false;
}
// check if current map->fd is null://
if (!strncmp (desc->name, "null://", 7)) {
return false;
}
return true;
}
static bool stringAt(RCore *core, ut64 addr) {
ut8 buf[32];
r_io_read_at (core->io, addr - 1, buf, sizeof (buf));
// check if previous byte is a null byte, all strings, except pascal ones should be like this
if (buf[0] != 0) {
return false;
}
return is_string (buf + 1, 31, NULL);
}
R_API int r_core_search_value_in_range(RCore *core, RInterval search_itv, ut64 vmin,
ut64 vmax, int vsize, bool asterisk, inRangeCb cb) {
int i, align = core->search->align, hitctr = 0;
bool vinfun = r_config_get_i (core->config, "anal.vinfun");
bool vinfunr = r_config_get_i (core->config, "anal.vinfunrange");
bool analStrings = r_config_get_i (core->config, "anal.strings");
mycore = core;
ut8 buf[4096];
ut64 v64, value = 0, size;
ut64 from = search_itv.addr, to = r_itv_end (search_itv);
ut32 v32;
ut16 v16;
if (from >= to) {
eprintf ("Error: from must be lower than to\n");
return -1;
}
bool maybeThumb = false;
if (align && core->anal->cur && core->anal->cur->arch) {
if (!strcmp (core->anal->cur->arch, "arm") && core->anal->bits != 64) {
maybeThumb = true;
}
}
if (vmin >= vmax) {
eprintf ("Error: vmin must be lower than vmax\n");
return -1;
}
if (to == UT64_MAX) {
eprintf ("Error: Invalid destination boundary\n");
return -1;
}
r_cons_break_push (NULL, NULL);
while (from < to) {
size = R_MIN (to - from, sizeof (buf));
memset (buf, 0xff, sizeof (buf)); // probably unnecessary
if (r_cons_is_breaked ()) {
goto beach;
}
bool res = r_io_read_at_mapped (core->io, from, buf, size);
if (!res || !memcmp (buf, "\xff\xff\xff\xff", 4) || !memcmp (buf, "\x00\x00\x00\x00", 4)) {
if (!isValidAddress (core, from)) {
ut64 next = r_io_map_next_address (core->io, from);
if (next == UT64_MAX) {
from += sizeof (buf);
} else {
from += (next - from);
}
continue;
}
}
for (i = 0; i <= (size - vsize); i++) {
void *v = (buf + i);
ut64 addr = from + i;
if (r_cons_is_breaked ()) {
goto beach;
}
if (align && (addr) % align) {
continue;
}
int match = false;
int left = size - i;
if (vsize > left) {
break;
}
switch (vsize) {
case 1: value = *(ut8 *)v; match = (buf[i] >= vmin && buf[i] <= vmax); break;
case 2: v16 = *(uut16 *)v; match = (v16 >= vmin && v16 <= vmax); value = v16; break;
case 4: v32 = *(uut32 *)v; match = (v32 >= vmin && v32 <= vmax); value = v32; break;
case 8: v64 = *(uut64 *)v; match = (v64 >= vmin && v64 <= vmax); value = v64; break;
default: eprintf ("Unknown vsize %d\n", vsize); return -1;
}
if (match && !vinfun) {
if (vinfunr) {
if (r_anal_get_fcn_in_bounds (core->anal, addr, R_ANAL_FCN_TYPE_NULL)) {
match = false;
}
} else {
if (r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL)) {
match = false;
}
}
}
if (match && value) {
bool isValidMatch = true;
if (align && (value % align)) {
// ignored .. unless we are analyzing arm/thumb and lower bit is 1
isValidMatch = false;
if (maybeThumb && (value & 1)) {
isValidMatch = true;
}
}
if (isValidMatch) {
cb (core, addr, value, vsize, asterisk, hitctr);
if (analStrings && stringAt (core, addr)) {
add_string_ref (mycore, addr, value);
}
hitctr++;
}
}
}
if (size == to-from) {
break;
}
from += size-vsize+1;
}
beach:
r_cons_break_pop ();
return hitctr;
}
typedef struct {
dict visited;
RList *path;

View File

@ -8319,6 +8319,7 @@ static void cmd_anal_aav(RCore *core, const char *input) {
char *tmp = strdup (analin);
bool asterisk = strchr (input, '*');
bool is_debug = r_config_get_i (core->config, "cfg.debug");
bool analStrings = r_config_get_i (core->config, "anal.strings");
// pre
int archAlign = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
seti ("search.align", archAlign);

View File

@ -3657,134 +3657,6 @@ R_API RBuffer *r_core_syscall (RCore *core, const char *name, const char *args)
return b;
}
static bool isValidAddress (RCore *core, ut64 addr) {
// check if address is mapped
RIOMap* map = r_io_map_get (core->io, addr);
if (!map) {
return false;
}
st64 fdsz = (st64)r_io_fd_size (core->io, map->fd);
if (fdsz > 0 && map->delta > fdsz) {
return false;
}
// check if associated file is opened
RIODesc *desc = r_io_desc_get (core->io, map->fd);
if (!desc) {
return false;
}
// check if current map->fd is null://
if (!strncmp (desc->name, "null://", 7)) {
return false;
}
return true;
}
R_API int r_core_search_value_in_range(RCore *core, RInterval search_itv, ut64 vmin,
ut64 vmax, int vsize, bool asterisk, inRangeCb cb) {
int i, align = core->search->align, hitctr = 0;
bool vinfun = r_config_get_i (core->config, "anal.vinfun");
bool vinfunr = r_config_get_i (core->config, "anal.vinfunrange");
ut8 buf[4096];
ut64 v64, value = 0, size;
ut64 from = search_itv.addr, to = r_itv_end (search_itv);
ut32 v32;
ut16 v16;
if (from >= to) {
eprintf ("Error: from must be lower than to\n");
return -1;
}
bool maybeThumb = false;
if (align && core->anal->cur && core->anal->cur->arch) {
if (!strcmp (core->anal->cur->arch, "arm") && core->anal->bits != 64) {
maybeThumb = true;
}
}
if (vmin >= vmax) {
eprintf ("Error: vmin must be lower than vmax\n");
return -1;
}
if (to == UT64_MAX) {
eprintf ("Error: Invalid destination boundary\n");
return -1;
}
r_cons_break_push (NULL, NULL);
while (from < to) {
size = R_MIN (to - from, sizeof (buf));
memset (buf, 0xff, sizeof (buf)); // probably unnecessary
if (r_cons_is_breaked ()) {
goto beach;
}
bool res = r_io_read_at_mapped (core->io, from, buf, size);
if (!res || !memcmp (buf, "\xff\xff\xff\xff", 4) || !memcmp (buf, "\x00\x00\x00\x00", 4)) {
if (!isValidAddress (core, from)) {
ut64 next = r_io_map_next_address (core->io, from);
if (next == UT64_MAX) {
from += sizeof (buf);
} else {
from += (next - from);
}
continue;
}
}
for (i = 0; i <= (size - vsize); i++) {
void *v = (buf + i);
ut64 addr = from + i;
if (r_cons_is_breaked ()) {
goto beach;
}
if (align && (addr) % align) {
continue;
}
int match = false;
int left = size - i;
if (vsize > left) {
break;
}
switch (vsize) {
case 1: value = *(ut8 *)v; match = (buf[i] >= vmin && buf[i] <= vmax); break;
case 2: v16 = *(uut16 *)v; match = (v16 >= vmin && v16 <= vmax); value = v16; break;
case 4: v32 = *(uut32 *)v; match = (v32 >= vmin && v32 <= vmax); value = v32; break;
case 8: v64 = *(uut64 *)v; match = (v64 >= vmin && v64 <= vmax); value = v64; break;
default: eprintf ("Unknown vsize %d\n", vsize); return -1;
}
if (match && !vinfun) {
if (vinfunr) {
if (r_anal_get_fcn_in_bounds (core->anal, addr, R_ANAL_FCN_TYPE_NULL)) {
match = false;
}
} else {
if (r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL)) {
match = false;
}
}
}
if (match && value) {
bool isValidMatch = true;
if (align && (value % align)) {
// ignored .. unless we are analyzing arm/thumb and lower bit is 1
isValidMatch = false;
if (maybeThumb && (value & 1)) {
isValidMatch = true;
}
}
if (isValidMatch) {
cb (core, addr, value, vsize, asterisk, hitctr);
hitctr++;
}
}
}
if (size == to-from) {
break;
}
from += size-vsize+1;
}
beach:
r_cons_break_pop ();
return hitctr;
}
R_API RCoreAutocomplete *r_core_autocomplete_add(RCoreAutocomplete *parent, const char* cmd, int type, bool lock) {
if (!parent || !cmd || type < 0 || type >= R_CORE_AUTOCMPLT_END) {
return NULL;