diff --git a/binr/rabin2/rabin2.c b/binr/rabin2/rabin2.c index 8ffada3a28..26b8782aa3 100644 --- a/binr/rabin2/rabin2.c +++ b/binr/rabin2/rabin2.c @@ -98,6 +98,12 @@ static int rabin_show_help(int v) { " -zzz dump raw strings to stdout (for huge files)\n" " -Z guess size of binary program\n" ); + if (v) { + printf ("Environment:\n" + " 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"); + } return 1; } @@ -377,6 +383,7 @@ int main(int argc, char **argv) { const char *op = NULL; const char *chksum = NULL; const char *forcebin = NULL; + char *tmp; RCoreBinFilter filter; RCore core; RCoreFile *cf = NULL; @@ -397,10 +404,17 @@ int main(int argc, char **argv) { r_lib_opendir (l, homeplugindir); r_lib_opendir (l, R2_LIBDIR"/radare2/"R2_VERSION); - char *maxstrbuf = r_sys_getenv ("RABIN2_MAXSTRBUF"); - if (maxstrbuf) { - r_config_set (core.config, "bin.maxstrbuf", maxstrbuf); - free(maxstrbuf); + if ((tmp = r_sys_getenv ("RABIN2_MAXSTRBUF"))) { + r_config_set (core.config, "bin.maxstrbuf", tmp); + free (tmp); + } + if ((tmp = r_sys_getenv ("RABIN2_STRFILTER"))) { + r_config_set (core.config, "bin.strfilter", tmp); + free (tmp); + } + if ((tmp = r_sys_getenv ("RABIN2_STRPURGE"))) { + r_config_set (core.config, "bin.strpurge", tmp); + free (tmp); } #define is_active(x) (action&x) diff --git a/libr/core/bin.c b/libr/core/bin.c index d1b22f2e5b..15c05d55a2 100644 --- a/libr/core/bin.c +++ b/libr/core/bin.c @@ -130,6 +130,89 @@ R_API RBinFile * r_core_bin_cur(RCore *core) { return binfile; } +static bool string_filter(RCore *core, const char *str) { + int i; + /* pointer/rawdata detection */ + if (core->bin->strpurge) { + ut8 bo[0x100]; + int up = 0; + int lo = 0; + int ot = 0; + int di = 0; + int ln = 0; + int sp = 0; + int nm = 0; + for (i = 0; i<0x100; i++) { + bo[i] = 0; + } + for (i = 0; str[i]; i++) { + if (str[i]>='0' && str[i]<='9') + nm++; + else if (str[i]>='a' && str[i]<='z') + lo++; + else if (str[i]>='A' && str[i]<='Z') + up++; + else ot++; + if (str[i]=='\\') ot++; + if (str[i]==' ') sp++; + bo[(ut8)str[i]] = 1; + ln++; + } + for (i = 0; i<0x100; i++) { + if (bo[i]) + di++; + } + if (ln>2 && str[0] != '_') { + if (ln<10) return false; + if (ot >= (nm+up+lo)) + return false; + if (lo <3) + return false; + } + } + + switch (core->bin->strfilter) { + case 'a': // only alphanumeric - plain ascii + for (i = 0; str[i]; i++) { + char ch = str[i]; + if (ch<0 || !IS_PRINTABLE (ch)) + return false; + } + break; + case 'e': // emails + if (str && *str) { + if (!strstr (str+1, "@")) + return false; + if (!strstr (str+1, ".")) + return false; + } else return false; + break; + case 'f': // format-string + if (str && *str) { + if (!strstr (str+1, "%")) + return false; + } else return false; + break; + case 'u': // URLs + if (!strstr (str, "://")) + return false; + break; + case 'p': // path + if (str[0] != '/') + return false; + break; + case '8': // utf8 + for (i = 0; str[i]; i++) { + char ch = str[i]; + if (ch<0) + return true; + } + return false; + break; + } + return true; +} + static int bin_strings(RCore *r, int mode, int va) { char *q, str[R_FLAG_NAME_SIZE]; RBinSection *section; @@ -171,9 +254,12 @@ static int bin_strings(RCore *r, int mode, int va) { } r_list_foreach (list, iter, string) { const char *section_name, *type_string; - ut64 paddr = string->paddr; - ut64 vaddr = r_bin_get_vaddr (bin, paddr, string->vaddr); - ut64 addr = va ? vaddr : paddr; + ut64 paddr, vaddr, addr; + if (!string_filter (r, string->string)) + continue; + paddr = string->paddr; + vaddr = r_bin_get_vaddr (bin, paddr, string->vaddr); + addr = va ? vaddr : paddr; if (string->length < minstr) continue; if (maxstr && string->length > maxstr) continue; diff --git a/libr/core/config.c b/libr/core/config.c index 4844f6a262..1f9f6773f8 100644 --- a/libr/core/config.c +++ b/libr/core/config.c @@ -392,6 +392,31 @@ static int cb_binfilter(void *user, void *data) { return true; } +static int cb_strpurge(void *user, void *data) { + RCore *core = (RCore*) user; + RConfigNode *node = (RConfigNode*) data; + core->bin->strpurge = node->i_value; + return true; +} + +static int cb_strfilter(void *user, void *data) { + RCore *core = (RCore*) user; + RConfigNode *node = (RConfigNode*) data; + if (node->value[0] == '?') { + eprintf ("Valid values for bin.strfilter:\n"); + eprintf ("a only alphanumeric printable\n"); + eprintf ("8 only strings with utf8 chars\n"); + eprintf ("p file/directory paths\n"); + eprintf ("e email-like addresses\n"); + eprintf ("u urls\n"); + eprintf ("f format-strings\n"); + return false; + } else { + core->bin->strfilter = node->value[0]; + } + return true; +} + static int cb_binforce(void *user, void *data) { RCore *core = (RCore*) user; RConfigNode *node = (RConfigNode*) data; @@ -1255,6 +1280,8 @@ R_API int r_core_config_init(RCore *core) { SETPREF("asm.demangle", "true", "Show demangled symbols in disasm"); SETPREF("asm.describe", "false", "Show opcode description"); SETPREF("asm.marks", "true", "Show marks before the disassembly"); + SETCB("bin.strpurge", "false", &cb_strpurge, "Try to purge false positive strings"); + SETCB("bin.strfilter", "", &cb_strfilter, "Filter strings (?:help, a:scii, e:mail, p:ath, u:rl, 8:utf8)"); SETCB("bin.filter", "true", &cb_binfilter, "Filter symbol names to fix dupped names"); SETCB("bin.force", "", &cb_binforce, "Force that rbin plugin"); SETPREF("bin.lang", "", "Language for bin.demangle"); @@ -1266,7 +1293,7 @@ R_API int r_core_config_init(RCore *core) { SETPREF("bin.dwarf", "true", "Load dwarf information on startup if available"); SETICB("bin.minstr", 0, &cb_binminstr, "Minimum string length for r_bin"); SETICB("bin.maxstr", 0, &cb_binmaxstr, "Maximum string length for r_bin"); - SETICB("bin.maxstrbuf", 1024*1024*2, & cb_binmaxstrbuf, "Maximum size of range to load strings from"); + SETICB("bin.maxstrbuf", 1024*1024*10, & cb_binmaxstrbuf, "Maximum size of range to load strings from"); SETCB("bin.rawstr", "false", &cb_rawstr, "Load strings from raw binaries"); SETPREF("bin.strings", "true", "Load strings from rbin on startup"); SETPREF("bin.classes", "true", "Load classes from rbin on startup"); diff --git a/libr/include/r_bin.h b/libr/include/r_bin.h index aa2b7ecb7b..6e1d69509d 100644 --- a/libr/include/r_bin.h +++ b/libr/include/r_bin.h @@ -188,7 +188,9 @@ typedef struct r_bin_t { RIOBind iob; char *force; int is_debugger; - int filter; + int filter; // symbol filtering + char strfilter; // string filtering + int strpurge; // purge false positive strings } RBin; typedef int (*FREE_XTR)(void *xtr_obj); diff --git a/man/rabin2.1 b/man/rabin2.1 index 5fbc470755..28ec003c9d 100644 --- a/man/rabin2.1 +++ b/man/rabin2.1 @@ -1,4 +1,4 @@ -.Dd Jan 10, 2015 +.Dd Oct 13, 2015 .Dt RABIN2 1 .Sh NAME .Nm RABIN2 @@ -103,6 +103,10 @@ Shows strings from raw bins .Sh ENVIRONMENT .Pp RABIN2_MAXSTRBUF same as r2 -e bin.maxstrbuf for rabin2 +.Pp +RABIN2_STRFILTER same as r2 -e bin.strfilter for rabin2 +.Pp +RABIN2_STRPURGE same as r2 -e bin.strpurge for rabin2 .Sh EXAMPLES .Pp List symbols of a program