Add visual search and enhace search output
- e search.show = true # by default - add keyword type (string, binary) - visual search only works in cursor mode
This commit is contained in:
parent
e43a1f921d
commit
afbda180d5
4
Makefile
4
Makefile
|
@ -22,6 +22,10 @@ plugins.cfg:
|
|||
gitpush:
|
||||
sh mk/gitpush.sh
|
||||
|
||||
.PHONY: todo
|
||||
todo:
|
||||
grep -re TODO:0.9.2 libr binr
|
||||
|
||||
libr:
|
||||
cd libr && ${MAKE} all
|
||||
|
||||
|
|
19
TODO
19
TODO
|
@ -5,13 +5,30 @@
|
|||
|
||||
------8<-------------------8<--------------------8<-----------------8<----------
|
||||
|
||||
* add 'mov al, cl' for x86.nz
|
||||
* fix ragg2
|
||||
|
||||
====[[ 0.9.1 ]]====
|
||||
* Analysis
|
||||
- assume there's a function at the end of each function
|
||||
* Allow to seek to branch N like in visual, but from cmdline
|
||||
* Colorize multiple ranges of chars in hexdump
|
||||
* List functions
|
||||
- calculate and show ciclomatic complexity
|
||||
* Searching for asm opcodes does not increase the hit count?
|
||||
* insert assembly in visual should be more userfriendly (keep unwritten bytes)
|
||||
* Search in io.va=true must be fixed
|
||||
- search.infile=true (ignore va and offset)
|
||||
* Source debugging or gtfo
|
||||
- integration with rabin2 -d
|
||||
* get cparse ftw
|
||||
* show analized functions in 'aa' -> discuss
|
||||
* show search hits.. if string, if hexdump...
|
||||
if (search.view) {
|
||||
if (is_string) pf z
|
||||
}
|
||||
* timeout for code analysis (check timestamp)
|
||||
* io_next must work properly
|
||||
- r_io must read in 512 or 4096 aligned blocks (get next section?)
|
||||
|
||||
Discuss
|
||||
Add $EDITOR alias for file open(read/write) -
|
||||
|
|
|
@ -26,7 +26,7 @@ RAsmPlugin r_asm_plugin_dcpu16 = {
|
|||
.name = "dcpu16",
|
||||
.arch = "dpcu",
|
||||
.bits = (int[]){ 16, 0 },
|
||||
.desc = "DCPU16 disassembly plugin",
|
||||
.desc = "DCPU16 assembler/disassembler",
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.disassemble = &disassemble,
|
||||
|
|
|
@ -73,7 +73,7 @@ static int cmd_print(void *data, const char *input) {
|
|||
return R_FALSE;
|
||||
}
|
||||
|
||||
if (input[0] && input[1] == 'f') {
|
||||
if (input[0] && input[0]!='Z' && input[1] == 'f') {
|
||||
RAnalFunction *f = r_anal_fcn_find (core->anal, core->offset,
|
||||
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
||||
if (f) len = f->size;
|
||||
|
@ -431,7 +431,11 @@ return 0;
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
eprintf ("TODO:0.9.2: pz (ascii and zero-terminated string)\n");
|
||||
break;
|
||||
case 'Z':
|
||||
// TODO:0.9.2 zoom.byte changes does not take any effect
|
||||
if (input[1]=='?') {
|
||||
r_cons_printf (
|
||||
"Usage: pZ [len]\n"
|
||||
|
@ -460,7 +464,7 @@ return 0;
|
|||
to = r_io_size (core->io);
|
||||
from = r_config_get_i (core->config, "zoom.from");
|
||||
to = r_config_get_i (core->config, "zoom.to");
|
||||
if (input[1] != '\0' && input[1] != ' ') {
|
||||
if (input[1] && input[1] != ' ') {
|
||||
oldzoom = strdup (r_config_get (core->config, "zoom.byte"));
|
||||
if (!r_config_set (core->config, "zoom.byte", input+1)) {
|
||||
eprintf ("Invalid zoom.byte mode (%s)\n", input+1);
|
||||
|
@ -501,6 +505,7 @@ return 0;
|
|||
" pu [len] print N url encoded bytes\n"
|
||||
" pU [len] print N wide url encoded bytes\n"
|
||||
" px [len] hexdump of N bytes\n"
|
||||
" pz [len] print zero terminated ascii string\n"
|
||||
" pZ [len] print zoom view (see pZ? for help)\n");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
static int preludecnt = 0;
|
||||
static int searchflags = 0;
|
||||
static int searchshow = 0;
|
||||
static const char *cmdhit = NULL;
|
||||
static const char *searchprefix = NULL;
|
||||
static unsigned int searchcount = 0;
|
||||
|
@ -80,12 +81,51 @@ static int __cb_hit(RSearchKeyword *kw, void *user, ut64 addr) {
|
|||
return R_FALSE;
|
||||
}
|
||||
}
|
||||
if (searchshow) {
|
||||
int len, i;
|
||||
ut8 buf[64];
|
||||
char str[128], *p;
|
||||
switch (kw->type) {
|
||||
case R_SEARCH_KEYWORD_TYPE_STRING:
|
||||
len = sizeof (str);
|
||||
r_io_read_at (core->io, addr, str+1, len-2);
|
||||
*str = '"';
|
||||
r_str_filter_zeroline (str, len);
|
||||
strcpy (str+strlen (str), "\"");
|
||||
break;
|
||||
default:
|
||||
len = kw->keyword_length + 8; // 8 byte context
|
||||
if (len>=sizeof (str)) len = sizeof (str)-1;
|
||||
r_io_read_at (core->io, addr, buf, sizeof (buf));
|
||||
for (i=0, p=str; i<len; i++) {
|
||||
sprintf (p, "%02x", buf[i]);
|
||||
p += 2;
|
||||
if (i == kw->keyword_length)
|
||||
*p++ = ' ';
|
||||
}
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
r_cons_printf ("0x%08"PFMT64x" %s%d_%d %s\n",
|
||||
addr, searchprefix, kw->kwidx, kw->count, str);
|
||||
} else {
|
||||
if (searchflags) {
|
||||
r_cons_printf ("%s%d_%d\n", searchprefix, kw->kwidx, kw->count);
|
||||
} else {
|
||||
r_cons_printf ("f %s%d_%d %d 0x%08"PFMT64x"\n", searchprefix,
|
||||
kw->kwidx, kw->count, kw->keyword_length, addr);
|
||||
}
|
||||
}
|
||||
if (searchflags) {
|
||||
r_cons_printf ("%s%d_%d\n", searchprefix, kw->kwidx, kw->count);
|
||||
char flag[64];
|
||||
snprintf (flag, sizeof (flag), "%s%d_%d", searchprefix, kw->kwidx, kw->count);
|
||||
r_flag_set (core->flags, flag, addr, kw->keyword_length, 1);
|
||||
#if 0
|
||||
// TODO: use r_flag_set ()
|
||||
r_core_cmdf (core, "f %s%d_%d %d 0x%08"PFMT64x"\n", searchprefix,
|
||||
kw->kwidx, kw->count, kw->keyword_length, addr);
|
||||
} else r_cons_printf ("f %s%d_%d %d 0x%08"PFMT64x"\n", searchprefix,
|
||||
kw->kwidx, kw->count, kw->keyword_length, addr);
|
||||
#endif
|
||||
}
|
||||
if (!strnull (cmdhit)) {
|
||||
ut64 here = core->offset;
|
||||
r_core_seek (core, addr, R_FALSE);
|
||||
|
@ -118,6 +158,7 @@ static int cmd_search(void *data, const char *input) {
|
|||
ut16 n16;
|
||||
ut8 *buf;
|
||||
|
||||
searchshow = r_config_get_i (core->config, "search.show");
|
||||
mode = r_config_get (core->config, "search.in");
|
||||
if (!strcmp (mode, "block")) {
|
||||
from = core->offset;
|
||||
|
@ -319,6 +360,7 @@ static int cmd_search(void *data, const char *input) {
|
|||
RSearchKeyword *skw;
|
||||
skw = r_search_keyword_new ((const ut8*)inp, len, NULL, 0, NULL);
|
||||
skw->icase = ignorecase;
|
||||
skw->type = R_SEARCH_KEYWORD_TYPE_STRING;
|
||||
r_search_kw_add (core->search, skw);
|
||||
}
|
||||
r_search_begin (core->search);
|
||||
|
|
|
@ -584,6 +584,8 @@ R_API int r_core_config_init(RCore *core) {
|
|||
r_config_desc (cfg, "search.in", "Specify search boundaries (raw, block, file, section)");
|
||||
r_config_set_i (cfg, "search.kwidx", 0);
|
||||
r_config_desc (cfg, "search.kwidx", "Store last search index count");
|
||||
r_config_set (cfg, "search.show", "true");
|
||||
r_config_desc (cfg, "search.show", "Show search results while found (disable if lot of hits)");
|
||||
r_config_set (cfg, "search.flags", "true");
|
||||
r_config_desc (cfg, "search.flags", "If enabled all search results are flagged, else just printed r2 commands");
|
||||
r_config_set_i (cfg, "search.count", 0);
|
||||
|
|
|
@ -151,6 +151,40 @@ void setcursor (RCore *core, int cur) {
|
|||
core->print->col = curset? 1: 0;
|
||||
}
|
||||
|
||||
// TODO: integrate in '/' command with search.inblock ?
|
||||
static void visual_search (RCore *core) {
|
||||
ut8 *p;
|
||||
int len, d=cursor;
|
||||
char str[128], buf[258];
|
||||
|
||||
r_line_set_prompt ("search byte/string in block: ");
|
||||
r_cons_fgets (str, sizeof (str), 0, NULL);
|
||||
len = r_hex_str2bin (str, buf);
|
||||
if (*str=='"') {
|
||||
char *e = strncpy (buf, str+1, sizeof (buf)-1);
|
||||
if (e) { --e; if (*e=='"') *e=0; }
|
||||
len = strlen (buf);
|
||||
} else
|
||||
if (len<1) {
|
||||
strncpy (buf, str, sizeof (buf)-1);
|
||||
len = strlen (str);
|
||||
}
|
||||
p = r_mem_mem (core->block+d, core->blocksize-d, buf, len);
|
||||
if (p) {
|
||||
cursor = (int)(size_t)(p-core->block);
|
||||
if (len>1) {
|
||||
ocursor = cursor+len-1;
|
||||
} else ocursor = -1;
|
||||
r_cons_show_cursor (R_TRUE);
|
||||
eprintf ("FOUND IN %d\n", cursor);
|
||||
r_cons_any_key ();
|
||||
} else {
|
||||
eprintf ("Cannot find bytes\n");
|
||||
r_cons_any_key ();
|
||||
r_cons_clear00 ();
|
||||
}
|
||||
}
|
||||
|
||||
R_API int r_core_visual_cmd(RCore *core, int ch) {
|
||||
RAsmOp op;
|
||||
char buf[4096];
|
||||
|
@ -544,8 +578,12 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
|
|||
}
|
||||
break;
|
||||
case '/':
|
||||
if (!autoblocksize)
|
||||
r_core_block_size (core, core->blocksize-cols);
|
||||
if (curset) {
|
||||
visual_search (core);
|
||||
} else {
|
||||
if (!autoblocksize)
|
||||
r_core_block_size (core, core->blocksize-cols);
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
if (!autoblocksize)
|
||||
|
@ -662,6 +700,7 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
|
|||
" mK/'K mark/go to Key (any key)\n"
|
||||
" M show mount points\n"
|
||||
" _ enter hud mode\n"
|
||||
" / in cursor mode search in current block\n"
|
||||
" :cmd run radare command\n"
|
||||
" ;[-]cmt add/remove comment\n"
|
||||
" . seek to program counter\n"
|
||||
|
|
|
@ -19,6 +19,9 @@ enum {
|
|||
|
||||
#define R_SEARCH_DISTANCE_MAX 10
|
||||
|
||||
#define R_SEARCH_KEYWORD_TYPE_BINARY 'i'
|
||||
#define R_SEARCH_KEYWORD_TYPE_STRING 's'
|
||||
|
||||
typedef struct r_search_keyword_t {
|
||||
char keyword[128];
|
||||
char binmask[128];
|
||||
|
@ -32,7 +35,7 @@ typedef struct r_search_keyword_t {
|
|||
int count;
|
||||
int kwidx;
|
||||
int icase; // ignore case
|
||||
RList *list;
|
||||
int type;
|
||||
} RSearchKeyword;
|
||||
|
||||
typedef struct r_search_hit_t {
|
||||
|
|
|
@ -318,6 +318,7 @@ R_API int r_name_filter(char *name, int len);
|
|||
R_API void r_base64_encode(ut8 *bout, const ut8 *bin, int len);
|
||||
R_API int r_base64_decode(ut8 *bout, const ut8 *bin, int len);
|
||||
/* strings */
|
||||
R_API void r_str_filter_zeroline(char *str, int len);
|
||||
R_API int r_str_write (int fd, const char *b);
|
||||
R_API void r_str_ncpy(char *dst, const char *src, int n);
|
||||
R_API void r_str_sanitize(char *c);
|
||||
|
|
|
@ -9,6 +9,7 @@ R_API RSearchKeyword* r_search_keyword_new(const ut8 *kw, int kwlen, const ut8 *
|
|||
if (bm == NULL)
|
||||
bm = (const ut8*) "";
|
||||
if ((k = R_NEW (RSearchKeyword))) {
|
||||
k->type = R_SEARCH_KEYWORD_TYPE_BINARY;
|
||||
k->icase = 0;
|
||||
memcpy (k->keyword, kw, kwlen);
|
||||
k->keyword_length = kwlen;
|
||||
|
@ -40,7 +41,10 @@ R_API RSearchKeyword* r_search_keyword_new_str(const char *kw, const char *bmhex
|
|||
}
|
||||
}
|
||||
ks = r_search_keyword_new ((ut8 *)kw, strlen (kw), bm, bmlen, data);
|
||||
if (ks) ks->icase = icase;
|
||||
if (ks) {
|
||||
ks->icase = icase;
|
||||
ks->type = R_SEARCH_KEYWORD_TYPE_STRING;
|
||||
}
|
||||
free (bm);
|
||||
return ks;
|
||||
}
|
||||
|
|
|
@ -724,6 +724,18 @@ R_API int r_str_ansi_filter(char *str, int len) {
|
|||
return j;
|
||||
}
|
||||
|
||||
R_API void r_str_filter_zeroline(char *str, int len) {
|
||||
int i;
|
||||
for (i=0; str[i] && i<len; i++) {
|
||||
// TODO: honor newlines?
|
||||
if (str[i]=='\n' || str[i]=='\r')
|
||||
break;
|
||||
if (!IS_PRINTABLE (str[i]))
|
||||
break;
|
||||
}
|
||||
str[i] = 0;
|
||||
}
|
||||
|
||||
R_API void r_str_filter(char *str, int len) {
|
||||
int i;
|
||||
for (i=0; i<len; i++)
|
||||
|
|
Loading…
Reference in New Issue