Initial implementation of the visual ROP browser ##visual

This commit is contained in:
pancake 2019-01-14 01:09:30 +01:00
parent 91496b9e10
commit 213e4c9ca8
5 changed files with 241 additions and 9 deletions

View File

@ -2279,6 +2279,7 @@ R_API bool r_core_init(RCore *core) {
core->http_up = false;
ZERO_FILL (core->root_cmd_descriptor);
core->print = r_print_new ();
core->ropchain = r_list_newf ((RListFree)free);
r_core_bind (core, &(core->print->coreb));
core->print->user = core;
core->print->num = core->num;
@ -2488,6 +2489,7 @@ R_API RCore *r_core_fini(RCore *c) {
/* TODO: it leaks as shit */
//update_sdb (c);
// avoid double free
r_list_free (c->ropchain);
r_core_free_autocomplete (c);
r_event_free (c->ev);
R_FREE (c->cmdlog);

View File

@ -436,6 +436,9 @@ static int r_core_rtr_http_run(RCore *core, int launch, int browse, const char *
}
return false;
}
if (!path) {
return false;
}
char *arg = strchr (path, ' ');
if (arg) {
path = arg + 1;

View File

@ -1871,6 +1871,7 @@ R_API void r_core_visual_browse(RCore *core) {
" m maps\n"
" p pids/threads\n"
" q quit\n"
" r rop gadgets\n"
" s symbols\n"
" t types\n"
" T themes\n"
@ -1888,6 +1889,9 @@ R_API void r_core_visual_browse(RCore *core) {
case 'g':
r_core_visual_view_graph (core);
break;
case 'r':
r_core_visual_view_rop (core);
break;
case 'f':
r_core_visual_trackflags (core);
break;

View File

@ -1286,6 +1286,227 @@ R_API int r_core_visual_view_graph(RCore *core) {
return false;
}
static void print_rop(void *_core, void *_item, bool selected) {
char *line = _item;
r_cons_printf ("%c %s\n", selected?'>':' ', line);
}
R_API int r_core_visual_view_rop(RCore *core) {
RListIter *iter;
const int rows = 7;
int cur = 0;
r_line_set_prompt ("rop regexp: ");
const char *line = r_line_readline ();
int scr_h, scr_w = r_cons_get_size (&scr_h);
if (!line || !*line) {
return false;
}
RList *chain = r_list_newf (free);
// maybe store in RCore, so we can save it in project and use it outside visual
eprintf ("Searching ROP gadgets...\n");
char *ropstr = r_core_cmd_strf (core, "\"/Rl %s\"", line);
RList *rops = r_str_split_list (ropstr, "\n");
int delta = 0;
ut64 addr = UT64_MAX;
char *cursearch = strdup (line);
while (true) {
r_cons_clear00 ();
r_cons_printf ("[0x%08"PFMT64x"]-[visual-r2rop] %s\n", addr + delta, cursearch);
// compute chain
RStrBuf *sb = r_strbuf_new ("");
char *msg;
r_list_foreach (chain, iter, msg) {
if (core->assembler->bits == 64) {
ut64 n = r_num_get (NULL, msg);
n = r_read_be64 (&n);
r_strbuf_appendf (sb, "%016"PFMT64x, n);
} else {
ut32 n = r_num_get (NULL, msg);
n = r_read_be32 (&n);
r_strbuf_appendf (sb, "%08x", n);
}
}
char *chainstr = r_strbuf_drain (sb);
char *curline = r_str_dup (NULL, r_str_trim_ro (widget_list (core, rops, rows, cur, print_rop)));
if (curline) {
char *sp = strchr (curline, ' ');
if (sp) {
*sp = 0;
addr = r_num_math (NULL, curline);
*sp = ' ';
}
if (addr != UT64_MAX) {
r_cons_printf ("Current Gadget:\n");
ut64 n = r_num_get (NULL, curline);
char *cmt = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, n);
// get comment
char *output = r_core_cmd_strf (core, "pd 10 @ 0x%08"PFMT64x"\n", addr + delta);
char *out = r_str_newf ("%s ; %s", output, cmt);
r_cons_strcat_at (out, 0, 11, scr_w, 10);
free (out);
free (output);
}
}
int count = 0;
r_cons_gotoxy (0, 22);
r_cons_printf ("ROPChain:\n");
if (chainstr) {
r_cons_printf ("%s\n", chainstr);
}
r_list_foreach (chain, iter, msg) {
int extra = strlen (chainstr) / scr_w;
r_cons_gotoxy (0, extra + 24 + count);
r_cons_strcat (msg);
count ++;
}
R_FREE (chainstr);
r_cons_flush ();
int ch = r_cons_readchar ();
if (ch == -1 || ch == 4) {
free (curline);
free (cursearch);
r_list_free (chain);
return false;
}
#define NEWTYPE(x,y) r_mem_dup (&(y), sizeof (x));
ch = r_cons_arrow_to_hjkl (ch); // get ESC+char, return 'hjkl' char
switch (ch) {
case 127:
free (r_list_pop (chain));
break;
case '?':
r_cons_clear00 ();
r_cons_printf ("[r2rop-visual] Help\n"
" jk - select next/prev rop gadget\n"
" hl - increase/decrease delta offset in disasm\n"
" \\n - enter key or dot will add the current offset into the chain\n"
" i - enter a number to be pushed into the chain\n"
" ; - add comment in current offset\n"
" <- - backspace - delete last gadget from the chain\n"
" y - yank current rop chain into the clipboard (y?)\n"
" r - run /R again\n"
" ? - show this help message\n"
);
r_cons_flush ();
r_cons_any_key (NULL);
break;
case ':': // TODO: move this into a separate helper function
{
char cmd[1024];
r_cons_show_cursor (true);
r_cons_set_raw (0);
cmd[0] = '\0';
r_line_set_prompt (":> ");
if (r_cons_fgets (cmd, sizeof (cmd)-1, 0, NULL) < 0) {
cmd[0] = '\0';
}
r_core_cmd (core, cmd, 1);
r_cons_set_raw (1);
r_cons_show_cursor (false);
if (cmd[0]) {
r_cons_any_key (NULL);
}
r_cons_clear ();
}
break;
case 'y':
break;
case 'r':
{
r_line_set_prompt ("rop regexp: ");
const char *line = r_line_readline ();
if (line && *line) {
free (cursearch);
cursearch = strdup (line);
}
}
break;
case '/':
r_core_cmd0 (core, "?i highlight;e scr.highlight=`yp`");
break;
case 'i':
{
r_line_set_prompt ("insert value: ");
const char *line = r_line_readline ();
if (line && *line) {
ut64 n = r_num_math (core->num, line);
r_list_push (chain, r_str_newf ("0x%08"PFMT64x, n));
}
}
break;
case ';':
{
r_line_set_prompt ("comment: ");
const char *line = r_line_readline ();
if (line && *line) {
// XXX code injection bug here
r_core_cmdf (core, "CC %s @ 0x%08"PFMT64x, line, addr + delta);
}
}
break;
case '.':
case '\n':
case '\r':
if (curline && *curline) {
char *line = r_core_cmd_strf (core, "pi 4 @ 0x%08"PFMT64x, addr + delta);
r_str_replace_char (line, '\n', ';');
r_list_push (chain, r_str_newf ("0x%08"PFMT64x" %s", addr + delta, line));
free (line);
}
break;
case 'h':
delta--;
break;
case 'l':
delta++;
break;
case 'J':
cur+=10;
delta = 0;
break;
case 'K':
delta = 0;
if (cur > 10) {
cur-=10;
} else {
cur = 0;
}
break;
case '0':
delta = 0;
cur = 0;
break;
case 'j':
delta = 0;
cur++;
break;
case 'k':
delta = 0;
if (cur > 0) {
cur--;
} else {
cur = 0;
}
break;
case 'q':
r_list_free (chain);
free (curline);
free (cursearch);
return true;
}
free (curline);
}
r_list_free (chain);
free (cursearch);
return false;
}
R_API int r_core_visual_trackflags(RCore *core) {
const char *fs = NULL, *fs2 = NULL;
int hit, i, j, ch;

View File

@ -298,6 +298,7 @@ typedef struct r_core_t {
RList *gadgets;
bool scr_gadgets;
bool log_events; // core.c:cb_event_handler : log actions from events if cfg.log.events is set
RList *ropchain;
} RCore;
R_API int r_core_bind(RCore *core, RCoreBind *bnd);
@ -677,16 +678,17 @@ R_API int r_core_rtr_http(RCore *core, int launch, int browse, const char *path)
R_API int r_core_rtr_http_stop(RCore *u);
R_API int r_core_rtr_gdb(RCore *core, int launch, const char *path);
R_API void r_core_visual_config (RCore *core);
R_API void r_core_visual_mounts (RCore *core);
R_API void r_core_visual_anal (RCore *core, const char *input);
R_API void r_core_seek_next (RCore *core, const char *type);
R_API void r_core_seek_previous (RCore *core, const char *type);
R_API void r_core_visual_define (RCore *core, const char *arg, int distance);
R_API int r_core_visual_trackflags (RCore *core);
R_API void r_core_visual_config(RCore *core);
R_API void r_core_visual_mounts(RCore *core);
R_API void r_core_visual_anal(RCore *core, const char *input);
R_API void r_core_seek_next(RCore *core, const char *type);
R_API void r_core_seek_previous(RCore *core, const char *type);
R_API void r_core_visual_define(RCore *core, const char *arg, int distance);
R_API int r_core_visual_trackflags(RCore *core);
R_API int r_core_visual_view_graph(RCore *core);
R_API int r_core_visual_comments (RCore *core);
R_API int r_core_visual_prompt (RCore *core);
R_API int r_core_visual_view_rop(RCore *core);
R_API int r_core_visual_comments(RCore *core);
R_API int r_core_visual_prompt(RCore *core);
R_API bool r_core_visual_esil (RCore *core);
R_API int r_core_search_preludes(RCore *core);
R_API int r_core_search_prelude(RCore *core, ut64 from, ut64 to, const ut8 *buf, int blen, const ut8 *mask, int mlen);