Implement bin.debase64 and RABIN2_DEBASE64 in RBin for r2 and rabin2

This commit is contained in:
pancake 2016-11-18 13:28:50 +01:00
parent 09594bdde9
commit 28c7ec564a
7 changed files with 95 additions and 25 deletions

View File

@ -89,6 +89,7 @@ static int rabin_show_help(int v) {
" RABIN2_MAXSTRBUF: e bin.maxstrbuf # specify maximum buffer size\n"
" RABIN2_STRFILTER: e bin.strfilter # r2 -qe bin.strfilter=? -c '' --\n"
" RABIN2_STRPURGE: e bin.strpurge # try to purge false positives\n"
" RABIN2_DEBASE64: e bin.debase64 # Try to debase64 all strings\n"
" RABIN2_DMNGLRCMD: e bin.demanglercmd # try to purge false positives\n"
" RABIN2_PREFIX: e bin.prefix # prefix symbols/sections/relocs with a specific string\n");
}
@ -579,6 +580,10 @@ int main(int argc, char **argv) {
r_config_set (core.config, "bin.strpurge", tmp);
free (tmp);
}
if ((tmp = r_sys_getenv ("RABIN2_DEBASE64"))) {
r_config_set (core.config, "bin.debase64", tmp);
free (tmp);
}
#define is_active(x) (action & x)
#define set_action(x) actions++; action |= x

View File

@ -66,6 +66,37 @@ static int r_bin_file_object_add(RBinFile *binfile, RBinObject *o);
static void binobj_set_baddr(RBinObject *o, ut64 baddr);
static ut64 binobj_a2b(RBinObject *o, ut64 addr);
static void filterStrings (RBin *bin, RList *strings) {
RBinString *ptr;
RListIter *iter;
r_list_foreach (strings, iter, ptr) {
char *dec = (char *)r_base64_decode_dyn (ptr->string, -1);
if (dec) {
char *s = ptr->string;
do {
char *dec2 = (char *)r_base64_decode_dyn (s, -1);
if (!dec2) {
break;
}
if (!r_str_is_printable (dec2)) {
free (dec2);
break;
}
free (dec);
s = dec = dec2;
} while (true);
if (r_str_is_printable (dec) && strlen (dec) > 3) {
free (ptr->string);
ptr->string = dec;
ptr->type = R_STRING_TYPE_BASE64;
// eprintf ("--> 0x%08"PFMT64x" %s\n", ptr->vaddr, ptr->string);
} else {
free (dec);
}
}
}
}
R_API void r_bin_iobind(RBin *bin, RIO *io) {
r_io_bind (io, &bin->iob);
}
@ -94,6 +125,16 @@ R_API RBinXtrData *r_bin_xtrdata_new(RBuffer *buf, ut64 offset, ut64 size, ut32
return NULL;
}
R_API const char *r_bin_string_type (int type) {
switch (type) {
case 'a': return "ascii";
case 'u': return "utf8";
case 'w': return "wide";
case 'b': return "base64";
}
return "ascii"; // XXX
}
R_API void r_bin_xtrdata_free(void /*RBinXtrData*/ *data_) {
RBinXtrData *data = data_;
if (data) {
@ -131,13 +172,6 @@ R_API int r_bin_file_cur_set_plugin(RBinFile *binfile, RBinPlugin *plugin) {
return false;
}
enum {
R_STRING_TYPE_DETECT = '?',
R_STRING_TYPE_ASCII = 'a',
R_STRING_TYPE_UTF8 = 'u',
R_STRING_TYPE_WIDE = 'w',
};
#define R_STRING_SCAN_BUFFER_SIZE 2048
static int string_scan_range(RList *list, const ut8 *buf, int min, const ut64 from, const ut64 to, int type) {
@ -148,7 +182,6 @@ static int string_scan_range(RList *list, const ut8 *buf, int min, const ut64 fr
if (type == -1) {
type = R_STRING_TYPE_DETECT;
}
if (!buf || !min) {
return -1;
}
@ -592,13 +625,17 @@ static int r_bin_object_set_items(RBinFile *binfile, RBinObject *o) {
} else {
o->strings = get_strings (binfile, minlen, 0);
}
if (bin->debase64) {
filterStrings (bin, o->strings);
}
REBASE_PADDR (o, o->strings, RBinString);
}
if (bin->filter_rules & R_BIN_REQ_CLASSES) {
if (cp->classes) {
o->classes = cp->classes (binfile);
if (bin->filter)
if (bin->filter) {
r_bin_filter_classes (o->classes);
}
}
}
if (cp->lines) {
@ -666,13 +703,16 @@ R_API int r_bin_reload(RBin *bin, RIODesc *desc, ut64 baseaddr) {
ut8 *buf_bytes = NULL;
ut64 len_bytes = UT64_MAX, sz = UT64_MAX;
if (!io) return false;
if (!desc || !io) return false;
if (!io) {
return false;
}
if (!desc || !io) {
return false;
}
bf = r_bin_file_find_by_name (bin, desc->name);
if (!bf) return false;
if (!bf) {
return false;
}
the_obj_list = bf->objs;
bf->objs = r_list_newf ((RListFree)r_bin_object_free);
// invalidate current object reference
@ -686,7 +726,9 @@ R_API int r_bin_reload(RBin *bin, RIODesc *desc, ut64 baseaddr) {
// load the bin-properly. Many of the plugins require all content and are not
// stream based loaders
RIODesc *tdesc = iob->desc_open (io, desc->name, desc->flags, R_IO_READ);
if (!tdesc) return false;
if (!tdesc) {
return false;
}
sz = iob->desc_size (io, tdesc);
if (sz == UT64_MAX) {
iob->desc_close (io, tdesc);
@ -697,10 +739,8 @@ R_API int r_bin_reload(RBin *bin, RIODesc *desc, ut64 baseaddr) {
} else if (sz == UT64_MAX || sz > (64 * 1024 * 1024)) { // too big, probably wrong
eprintf ("Too big\n");
return false;
} else {
buf_bytes = iob->desc_read (io, desc, &len_bytes);
}
buf_bytes = iob->desc_read (io, desc, &len_bytes);
if (!buf_bytes) {
sz = 0;
buf_bytes = iob->desc_read (io, desc, &sz);
@ -720,7 +760,8 @@ R_API int r_bin_reload(RBin *bin, RIODesc *desc, ut64 baseaddr) {
RBinObject *old_o;
r_list_foreach (the_obj_list, iter, old_o) {
// XXX - naive. do we need a way to prevent multiple "anys" from being opened?
res = r_bin_load_io_at_offset_as (bin, desc, baseaddr, old_o->loadaddr, 0, old_o->boffset, old_o->plugin->name);
res = r_bin_load_io_at_offset_as (bin, desc, baseaddr,
old_o->loadaddr, 0, old_o->boffset, old_o->plugin->name);
}
}
bf->o = r_list_get_n (bf->objs, 0);
@ -1495,8 +1536,9 @@ R_API RBinSection *r_bin_get_section_at(RBinObject *o, ut64 off, int va) {
from = va? binobj_a2b (o, section->vaddr): section->paddr;
to = va? (binobj_a2b (o, section->vaddr) + section->vsize) :
(section->paddr + section->size);
if (off >= from && off < to)
if (off >= from && off < to) {
return section;
}
}
}
return NULL;
@ -1525,6 +1567,9 @@ R_API RList *r_bin_reset_strings(RBin *bin) {
} else {
o->strings = get_strings (a, bin->minstrlen, 0);
}
if (bin->debase64) {
filterStrings (bin, o->strings);
}
return o->strings;
}

View File

@ -397,13 +397,13 @@ static RList *strings(RBinFile *arch) {
len = dex_read_uleb128 (buf);
if (len > 1 && len < R_BIN_SIZEOF_STRINGS) {
ptr->string = malloc (len + 1);
ptr->string = calloc (len + 1, 1);
if (!ptr->string) {
goto out_error;
}
off = bin->strings[i] + dex_uleb128_len (buf);
if (off > bin->size || off + len > bin->size) {
free (ptr->string);
R_FREE (ptr->string);
goto out_error;
}
r_buf_read_at (bin->b, off, (ut8*)ptr->string, len);

View File

@ -326,7 +326,7 @@ static void _print_strings(RCore *r, RList *list, int mode, int va) {
section = r_bin_get_section_at (r_bin_cur_object (bin), paddr, 0);
section_name = section ? section->name : "unknown";
type_string = string->type == 'w' ? "wide" : "ascii";
type_string = r_bin_string_type (string->type);
if (IS_MODE_SET (mode)) {
char *f_name, *str;
if (r_cons_singleton()->breaked) {

View File

@ -1360,6 +1360,13 @@ static int cb_rawstr(void *user, void *data) {
return true;
}
static int cb_debase64(void *user, void *data) {
RCore *core = (RCore *) user;
RConfigNode *node = (RConfigNode *) data;
core->bin->debase64 = node->i_value;
return true;
}
static int cb_binstrings(void *user, void *data) {
const ut32 req = R_BIN_REQ_STRINGS;
RCore *core = (RCore *) user;
@ -1801,6 +1808,7 @@ R_API int r_core_config_init(RCore *core) {
SETCB("bin.prefix", NULL, &cb_binprefix, "Prefix all symbols/sections/relocs with a specific string");
SETCB("bin.rawstr", "false", &cb_rawstr, "Load strings from raw binaries");
SETCB("bin.strings", "true", &cb_binstrings, "Load strings from rbin on startup");
SETCB("bin.debase64", "false", &cb_debase64, "Try to debase64 all strings");
SETPREF("bin.classes", "true", "Load classes from rbin on startup");
SETPREF("bin.mergeflags", "true", "Merge symbols with the same name into the same flag");

View File

@ -86,6 +86,14 @@ enum {
R_BIN_NM_ANY = -1,
};
enum {
R_STRING_TYPE_DETECT = '?',
R_STRING_TYPE_ASCII = 'a',
R_STRING_TYPE_UTF8 = 'u',
R_STRING_TYPE_WIDE = 'w',
R_STRING_TYPE_BASE64 = 'b',
};
enum {
R_BIN_CLASS_PRIVATE,
R_BIN_CLASS_PUBLIC,
@ -214,6 +222,7 @@ typedef struct r_bin_t {
int narch;
void *user;
/* preconfigured values */
int debase64;
int minstrlen;
int maxstrlen;
ut64 maxstrbuf;
@ -415,7 +424,7 @@ typedef struct r_bin_string_t {
ut32 ordinal;
ut32 size; // size of buffer containing the string in bytes
ut32 length; // length of string in chars
char type; // Ascii Wide cp850 utf8 ...
char type; // Ascii Wide cp850 utf8 base64 ...
} RBinString;
typedef struct r_bin_field_t {
@ -570,6 +579,7 @@ R_API RBinFile * r_bin_file_find_by_name_n (RBin * bin, const char * name, int i
R_API int r_bin_file_set_cur_binfile (RBin * bin, RBinFile *bf);
R_API RBinPlugin * r_bin_file_cur_plugin (RBinFile *binfile);
R_API void r_bin_force_plugin (RBin *bin, const char *pname);
R_API const char *r_bin_string_type (int type);
/* dbginfo.c */
R_API int r_bin_addr2line(RBin *bin, ut64 addr, char *file, int len, int *line);

View File

@ -133,6 +133,8 @@ RABIN2_DEMANGLE demangle symbols
.Pp
RABIN2_MAXSTRBUF same as r2 -e bin.maxstrbuf for rabin2
.Pp
RABIN2_DEBASE64 try to decode all strings as base64 if possible
.Pp
RABIN2_STRFILTER same as r2 -e bin.strfilter for rabin2
.Pp
RABIN2_STRPURGE same as r2 -e bin.strpurge for rabin2