From 1dcd1273fbcc0f5864259b966e5aa6d4b155786d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Felipe=20Melchor?= Date: Tue, 15 Nov 2016 19:34:22 +0100 Subject: [PATCH] Fix oob write in disasm.c myregwrite There was a dangling pointer in esil pointing to RDisasmState WRITE of size 1 at 0x620000000a88 thread T0 #0 0x103fab3dc in myregwrite disasm.c:2793 #1 0x1049544b9 in r_anal_esil_reg_write esil.c:545 #2 0x1049621e4 in esil_subeq esil.c:1418 #3 0x1049570e0 in runword esil.c:2365 #4 0x104955bcf in r_anal_esil_parse esil.c:2466 #5 0x103f417e4 in r_core_anal_esil anal.c:3145 #6 0x103df14e0 in cmd_anal_all .cmd_anal.c:4600 #7 0x103d6c610 in cmd_anal .cmd_anal.c:4829 #8 0x103f1ee25 in r_cmd_call cmd_api.c:213 #9 0x103dd7afc in r_core_cmd_subst_i cmd.c:1960 #10 0x103d66007 in r_core_cmd_subst cmd.c:1311 #11 0x103d5fd0b in r_core_cmd cmd.c:2477 #12 0x103d3910c in r_core_prompt_exec core.c:1687 #13 0x103c9b1de in main radare2.c:1021 #14 0x7fff9339b5ac in start (libdyld.dylib+0x35ac) --- libr/anal/esil.c | 6 +++-- libr/core/disasm.c | 56 ++++++++++++++++------------------------------ libr/core/visual.c | 8 +++++-- 3 files changed, 29 insertions(+), 41 deletions(-) diff --git a/libr/anal/esil.c b/libr/anal/esil.c index d33f533b01..7bbf27d086 100644 --- a/libr/anal/esil.c +++ b/libr/anal/esil.c @@ -2372,8 +2372,9 @@ static int runword(RAnalEsil *esil, const char *word) { // run action if (op) { if (esil->cb.hook_command) { - if (esil->cb.hook_command (esil, word)) + if (esil->cb.hook_command (esil, word)) { return 1; // XXX cannot return != 1 + } } return op (esil); } @@ -2503,8 +2504,9 @@ repeat: } word[wordi] = 0; if (*word) { - if (!runword (esil, word)) + if (!runword (esil, word)) { return 0; + } switch (evalWord (esil, ostr, &str)) { case 0: goto loop; case 1: return 0; diff --git a/libr/core/disasm.c b/libr/core/disasm.c index ae0cf5cf9d..647c5e157f 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -574,7 +574,7 @@ static void ds_free(RDisasmState *ds) { free (ds->osl); free (ds->sl); free (ds->_tabsbuf); - free (ds); + R_FREE (ds); } static void ds_set_pre(RDisasmState *ds, const char * str) { @@ -2830,44 +2830,19 @@ static int mymemwrite1(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) { static int myregwrite(RAnalEsil *esil, const char *name, ut64 *val) { char str[64], *msg = NULL; ut32 *n32 = (ut32*)str; - RDisasmState *ds = esil->user; - + RDisasmState *ds = NULL; + if (!esil) { + return 0; + } + ds = esil->user; if (ds) { ds->esil_likely = true; if (!ds->show_slow) { return 0; } } - memset (str, 0, sizeof (str)); if (*val != 0LL) { -#if 0 - RFlagItem *fi = r_flag_get_i (esil->anal->flb.f, val); - if (fi) { - strncpy (str, fi->name, sizeof (str)-1); - } - if (!str[0]) { - (void)r_io_read_at (esil->anal->iob.io, val, (ut8*)str, sizeof (str)-1); - str[sizeof (str)-1] = 0; - if (*str && r_str_is_printable (str)) { - // do nothing - msg = r_str_newf ("\"%s\"", str); - } else { - str[0] = 0; - if (*n32 == 0) { - // msg = strdup ("NULL"); - } else if (*n32 == UT32_MAX) { - /* nothing */ - } else { - if (ds && !ds->show_emu_str) { - msg = r_str_newf ("-> 0x%x", *n32); - } - } - } - } else { - msg = r_str_newf ("%s", str); - } -#endif (void)r_io_read_at (esil->anal->iob.io, *val, (ut8*)str, sizeof (str)-1); str[sizeof (str)-1] = 0; if (*str && r_str_is_printable (str)) { @@ -2890,13 +2865,15 @@ static int myregwrite(RAnalEsil *esil, const char *name, ut64 *val) { msg = r_str_concatf (msg, " %s", fi->name); } } - if (ds && ds->show_emu_str) { - if (msg && *msg) { - r_cons_printf (" ; %s", msg); + if (ds) { + if (ds->show_emu_str) { + if (msg && *msg) { + r_cons_printf (" ; %s", msg); + } + } else { + r_cons_printf (" ; %s=0x%"PFMT64x" %s", name, *val, msg? msg: ""); } - } else { - r_cons_printf (" ; %s=0x%"PFMT64x" %s", name, *val, msg? msg: ""); - } + } free (msg); return 0; } @@ -2930,6 +2907,7 @@ static void ds_print_esil_anal_init(RDisasmState *ds) { } static void ds_print_esil_anal_fini(RDisasmState *ds) { + RCore *core = ds->core; if (ds->show_emu && ds->esil_regstate) { RCore* core = ds->core; core->anal->last_disasm_reg = r_reg_arena_peek (core->anal->reg); @@ -2938,6 +2916,10 @@ static void ds_print_esil_anal_fini(RDisasmState *ds) { r_reg_setv (core->anal->reg, pc, ds->esil_old_pc); R_FREE (ds->esil_regstate); } + if (core && core->anal && core->anal->esil) { + //make sure to remove reference to ds to avoid UAF + core->anal->esil->user = NULL; + } } static void ds_print_bbline(RDisasmState *ds) { diff --git a/libr/core/visual.c b/libr/core/visual.c index a4678efdc2..acad70da01 100644 --- a/libr/core/visual.c +++ b/libr/core/visual.c @@ -2225,10 +2225,14 @@ static void visual_refresh(RCore *core) { r_cons_gotoxy (0, 0); r_core_visual_title (core, color); vi = r_config_get (core->config, "cmd.vprompt"); - if (vi) r_core_cmd (core, vi, 0); + if (vi) { + r_core_cmd (core, vi, 0); + } } else { vi = r_config_get (core->config, "cmd.vprompt"); - if (vi) r_core_cmd (core, vi, 0); + if (vi) { + r_core_cmd (core, vi, 0); + } r_core_visual_title (core, color); }