From 213e4c9ca82c215f29a5ccd908e6369d9bb2c408 Mon Sep 17 00:00:00 2001 From: pancake Date: Mon, 14 Jan 2019 01:09:30 +0100 Subject: [PATCH] Initial implementation of the visual ROP browser ##visual --- libr/core/core.c | 2 + libr/core/rtr.c | 3 + libr/core/visual.c | 4 + libr/core/vmenus.c | 221 ++++++++++++++++++++++++++++++++++++++++++ libr/include/r_core.h | 20 ++-- 5 files changed, 241 insertions(+), 9 deletions(-) diff --git a/libr/core/core.c b/libr/core/core.c index 70d025fffd..cd944ffcc9 100644 --- a/libr/core/core.c +++ b/libr/core/core.c @@ -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); diff --git a/libr/core/rtr.c b/libr/core/rtr.c index b95a5085f7..7d7e1c70b7 100644 --- a/libr/core/rtr.c +++ b/libr/core/rtr.c @@ -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; diff --git a/libr/core/visual.c b/libr/core/visual.c index 638aae6574..a4cc0a0579 100644 --- a/libr/core/visual.c +++ b/libr/core/visual.c @@ -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; diff --git a/libr/core/vmenus.c b/libr/core/vmenus.c index 2f4a9d20eb..60e3ff9236 100644 --- a/libr/core/vmenus.c +++ b/libr/core/vmenus.c @@ -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; diff --git a/libr/include/r_core.h b/libr/include/r_core.h index 1cfbc4067b..7ec0446dcd 100644 --- a/libr/include/r_core.h +++ b/libr/include/r_core.h @@ -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);