mirror of
https://github.com/radareorg/radare2.git
synced 2024-10-09 20:04:49 +00:00
Make rop dissassemble back from the end gadgets
- Remove some exta dissassembly steps too - Fix up some rop search stuff - constify is_end_gadget - Comment the rop stuff - Remove constant 60 - Rename rop config stuff
This commit is contained in:
parent
e45a8a3a0b
commit
a5828dfed1
@ -494,6 +494,29 @@ static ut64 findprevopsz(RCore *core, ut64 addr, ut8 *buf) {
|
||||
return UT64_MAX;
|
||||
}
|
||||
|
||||
static boolt is_end_gadget(const RAnalOp aop, const ut8 crop) {
|
||||
switch(aop.type) {
|
||||
case R_ANAL_OP_TYPE_TRAP:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
case R_ANAL_OP_TYPE_UCALL:
|
||||
case R_ANAL_OP_TYPE_UJMP:
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
return R_TRUE;
|
||||
}
|
||||
if (crop) { //if conditional jumps, calls and returns should be used for the gadget-search too
|
||||
switch (aop.type) {
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
case R_ANAL_OP_TYPE_UCJMP:
|
||||
case R_ANAL_OP_TYPE_CCALL:
|
||||
case R_ANAL_OP_TYPE_UCCALL:
|
||||
case R_ANAL_OP_TYPE_CRET: //i'm a condret
|
||||
return R_TRUE;
|
||||
}
|
||||
}
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
//TODO: follow unconditional jumps
|
||||
static RList* construct_rop_gadget(RCore *core, ut64 addr, ut8 *buf, int idx, const char* grep, int regex, RList* rx_list) {
|
||||
RAnalOp aop;
|
||||
@ -502,8 +525,8 @@ static RList* construct_rop_gadget(RCore *core, ut64 addr, ut8 *buf, int idx, co
|
||||
RCoreAsmHit *hit = NULL;
|
||||
RList *hitlist = r_core_asm_hit_list_new ();
|
||||
ut8 nb_instr = 0;
|
||||
const ut8 max_instr = r_config_get_i (core->config, "search.roplen");
|
||||
const ut8 crop = r_config_get_i (core->config, "search.conditionalrop"); //decide if cjmp, cret, and ccall should be used too for the gadget-search
|
||||
const ut8 max_instr = r_config_get_i (core->config, "rop.len");
|
||||
const ut8 crop = r_config_get_i (core->config, "rop.conditional"); //decide if cjmp, cret, and ccall should be used too for the gadget-search
|
||||
boolt valid = 0;
|
||||
int grep_find;
|
||||
int search_hit;
|
||||
@ -558,26 +581,9 @@ static RList* construct_rop_gadget(RCore *core, ut64 addr, ut8 *buf, int idx, co
|
||||
if (regex) rx = r_list_get_n(rx_list, count++);
|
||||
}
|
||||
|
||||
switch (aop.type) { // end of the gadget
|
||||
case R_ANAL_OP_TYPE_TRAP:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
case R_ANAL_OP_TYPE_UCALL:
|
||||
case R_ANAL_OP_TYPE_UJMP:
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
valid = R_TRUE;
|
||||
goto ret;
|
||||
}
|
||||
if (crop) { //if conditional jumps, calls and returns should be used for the gadget-search too
|
||||
switch (aop.type) {
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
case R_ANAL_OP_TYPE_UCJMP:
|
||||
case R_ANAL_OP_TYPE_CCALL:
|
||||
case R_ANAL_OP_TYPE_UCCALL:
|
||||
case R_ANAL_OP_TYPE_CRET: //i'm a condret
|
||||
valid = R_TRUE;
|
||||
goto ret;
|
||||
}
|
||||
if (is_end_gadget (aop, crop)) {
|
||||
valid = R_TRUE;
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
nb_instr++;
|
||||
@ -594,7 +600,6 @@ static int r_core_search_rop(RCore *core, ut64 from, ut64 to, int opt, const cha
|
||||
int i=0, end=0, mode=0, increment=1, ret;
|
||||
int delta = 0;
|
||||
RAsmOp asmop;
|
||||
RAnalOp aop;
|
||||
ut8 *buf;
|
||||
RIOMap *map;
|
||||
RList* hitlist;
|
||||
@ -607,8 +612,11 @@ static int r_core_search_rop(RCore *core, ut64 from, ut64 to, int opt, const cha
|
||||
const char *smode = r_config_get (core->config, "search.in");
|
||||
const char *arch = r_config_get (core->config, "asm.arch");
|
||||
RList/*<RRegex>*/ *rx_list = NULL;
|
||||
RList/*<int>*/ *end_list = NULL;
|
||||
RRegex* rx = NULL;
|
||||
char* tok, *gregexp = NULL;
|
||||
const ut8 crop = r_config_get_i (core->config, "rop.conditional"); //decide if cjmp, cret, and ccall should be used too for the gadget-search
|
||||
const ut8 max_instr = r_config_get_i (core->config, "rop.len");
|
||||
|
||||
if (!strcmp (arch, "mips")) // MIPS has no jump-in-the-middle
|
||||
increment = 4;
|
||||
@ -659,6 +667,7 @@ static int r_core_search_rop(RCore *core, ut64 from, ut64 to, int opt, const cha
|
||||
r_cons_printf ("[");
|
||||
|
||||
r_list_foreach (list, itermap, map) {
|
||||
end_list = r_list_newf(free);
|
||||
|
||||
from = map->from;
|
||||
to = map->to;
|
||||
@ -677,85 +686,123 @@ static int r_core_search_rop(RCore *core, ut64 from, ut64 to, int opt, const cha
|
||||
if (!buf) {
|
||||
free (gregexp);
|
||||
r_list_free (rx_list);
|
||||
r_list_free(end_list);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i < delta - 32; i+=increment) {
|
||||
if (i >= end) { // read by chunk of 4k
|
||||
r_core_read_at (core, from+i, buf+i, R_MIN ((delta-i), 4096));
|
||||
end = i + 2048;
|
||||
// Find the end gadgets.
|
||||
for (i = 0; i < delta; i += increment) {
|
||||
RAnalOp end_gadget;
|
||||
// Disassemble one.
|
||||
if (r_anal_op(core->anal, &end_gadget, from+i, buf+i, delta-i) <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (r_anal_op (core->anal, &aop, from+i, buf+i, delta-i) > 0) {
|
||||
r_asm_set_pc (core->assembler, from+i);
|
||||
/// XXX isnt the analop alrady disassembling?
|
||||
ret = r_asm_disassemble (core->assembler, &asmop, buf+i, delta-i);
|
||||
if (!ret)
|
||||
continue;
|
||||
hitlist = construct_rop_gadget (core, from+i, buf,
|
||||
i, grep, regexp, rx_list);
|
||||
if (!hitlist)
|
||||
continue;
|
||||
|
||||
if (json) { // json
|
||||
unsigned int size = 0;
|
||||
|
||||
//Handle comma between gadgets
|
||||
if (json_first == 0)
|
||||
r_cons_strcat (",");
|
||||
else
|
||||
json_first = 0;
|
||||
|
||||
r_cons_printf("{\"opcodes\":[");
|
||||
r_list_foreach (hitlist, iter, hit) {
|
||||
r_core_read_at (core, hit->addr, buf, hit->len);
|
||||
r_asm_set_pc (core->assembler, hit->addr);
|
||||
r_asm_disassemble (core->assembler, &asmop, buf, hit->len);
|
||||
r_anal_op (core->anal, &analop, hit->addr, buf, hit->len);
|
||||
size += hit->len;
|
||||
r_cons_printf ("{\"offset\":%"PFMT64d",\"size\":%d,\"opcode\":\"%s\",\"type\":\"%s\"}%s",
|
||||
hit->addr, hit->len, asmop.buf_asm,
|
||||
r_anal_optype_to_string (analop.type), iter->n?",":"");
|
||||
}
|
||||
r_cons_printf ("],\"retaddr\":%"PFMT64d",\"size\":%d}", hit->addr, size);
|
||||
} else {
|
||||
const char *otype;
|
||||
char *buf_asm, *buf_hex;
|
||||
|
||||
// The two loops are distinct for performance reason
|
||||
if (mode == 'l') {
|
||||
hit = r_list_get_top (hitlist);
|
||||
r_cons_printf ("0x%08"PFMT64x" 0x%08"PFMT64x":",
|
||||
from+i, hit->addr);
|
||||
r_list_foreach (hitlist, iter, hit) {
|
||||
r_core_read_at (core, hit->addr, buf, hit->len);
|
||||
r_asm_set_pc (core->assembler, hit->addr);
|
||||
r_asm_disassemble (core->assembler, &asmop, buf, hit->len);
|
||||
buf_asm = r_print_colorize_opcode (asmop.buf_asm,
|
||||
core->cons->pal.reg, core->cons->pal.num);
|
||||
r_cons_printf (" %s%s;", buf_asm, Color_RESET);
|
||||
free (buf_asm);
|
||||
}
|
||||
if (is_end_gadget(end_gadget, crop)) {
|
||||
r_list_append(end_list, &i);
|
||||
}
|
||||
// Right now we have a list of all of the end/stop gadgets.
|
||||
// We can just construct gadgets from a little bit before them.
|
||||
}
|
||||
// If we have no end gadgets, just skip all of this search nonsense.
|
||||
if (r_list_length(end_list) > 0) {
|
||||
int next, idx = 0;
|
||||
// Get the depth of rop search, should just be max_instr
|
||||
// instructions, x86 and friends are weird length instructions, so
|
||||
// we'll just assume 15 byte instructions.
|
||||
int ropdepth = increment == 1 ? max_instr * 15 /* wow, x86 is long */ : max_instr * increment;
|
||||
int* next_ptr = r_list_get_n(end_list, idx);
|
||||
next = *next_ptr;
|
||||
// Start at just before the first end gadget.
|
||||
for (i = next - ropdepth; i < (delta - 15 /* max insn size */); i+=increment) {
|
||||
if (i >= next) {
|
||||
// We've exhausted the first end-gadget section,
|
||||
// move to the next one.
|
||||
++idx;
|
||||
if (r_list_get_n(end_list, idx)) {
|
||||
next_ptr = r_list_get_n(end_list, idx);
|
||||
next = *next_ptr;
|
||||
i = next - ropdepth;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= end) { // read by chunk of 4k
|
||||
r_core_read_at (core, from+i, buf+i, R_MIN ((delta-i), 4096));
|
||||
end = i + 2048;
|
||||
}
|
||||
ret = r_asm_disassemble (core->assembler, &asmop, buf+i, delta-i);
|
||||
if (ret) {
|
||||
r_asm_set_pc (core->assembler, from+i);
|
||||
hitlist = construct_rop_gadget (core, from+i, buf,
|
||||
i, grep, regexp, rx_list);
|
||||
if (!hitlist)
|
||||
continue;
|
||||
|
||||
if (json) { // json
|
||||
unsigned int size = 0;
|
||||
|
||||
//Handle comma between gadgets
|
||||
if (json_first == 0)
|
||||
r_cons_strcat (",");
|
||||
else
|
||||
json_first = 0;
|
||||
|
||||
r_cons_printf("{\"opcodes\":[");
|
||||
r_list_foreach (hitlist, iter, hit) {
|
||||
r_core_read_at (core, hit->addr, buf, hit->len);
|
||||
r_asm_set_pc (core->assembler, hit->addr);
|
||||
r_asm_disassemble (core->assembler, &asmop, buf, hit->len);
|
||||
buf_asm = r_print_colorize_opcode (asmop.buf_asm,
|
||||
core->cons->pal.reg, core->cons->pal.num);
|
||||
buf_hex = r_print_colorize_opcode (asmop.buf_hex,
|
||||
core->cons->pal.reg, core->cons->pal.num);
|
||||
otype = r_print_color_op_type (core->print, analop.type);
|
||||
r_cons_printf (" 0x%08"PFMT64x" %s%16s %s%s\n",
|
||||
hit->addr, otype, buf_hex, buf_asm, Color_RESET);
|
||||
free (buf_asm);
|
||||
free (buf_hex);
|
||||
r_anal_op (core->anal, &analop, hit->addr, buf, hit->len);
|
||||
size += hit->len;
|
||||
r_cons_printf ("{\"offset\":%"PFMT64d",\"size\":%d,\"opcode\":\"%s\",\"type\":\"%s\"}%s",
|
||||
hit->addr, hit->len, asmop.buf_asm,
|
||||
r_anal_optype_to_string (analop.type), iter->n?",":"");
|
||||
}
|
||||
r_cons_printf ("],\"retaddr\":%"PFMT64d",\"size\":%d}", hit->addr, size);
|
||||
} else {
|
||||
const char *otype;
|
||||
char *buf_asm, *buf_hex;
|
||||
|
||||
// The two loops are distinct for performance reason
|
||||
if (mode == 'l') {
|
||||
// Print gadgets in a 'linear manner', each sequence
|
||||
// on one line.
|
||||
hit = r_list_get_top (hitlist);
|
||||
r_cons_printf ("0x%08"PFMT64x" 0x%08"PFMT64x":",
|
||||
from+i, hit->addr);
|
||||
r_list_foreach (hitlist, iter, hit) {
|
||||
r_core_read_at (core, hit->addr, buf, hit->len);
|
||||
r_asm_set_pc (core->assembler, hit->addr);
|
||||
r_asm_disassemble (core->assembler, &asmop, buf, hit->len);
|
||||
buf_asm = r_print_colorize_opcode (asmop.buf_asm,
|
||||
core->cons->pal.reg, core->cons->pal.num);
|
||||
r_cons_printf (" %s%s;", buf_asm, Color_RESET);
|
||||
free (buf_asm);
|
||||
}
|
||||
} else {
|
||||
// Print gadgets with new instruction on a new line.
|
||||
r_list_foreach (hitlist, iter, hit) {
|
||||
r_core_read_at (core, hit->addr, buf, hit->len);
|
||||
r_asm_set_pc (core->assembler, hit->addr);
|
||||
r_asm_disassemble (core->assembler, &asmop, buf, hit->len);
|
||||
buf_asm = r_print_colorize_opcode (asmop.buf_asm,
|
||||
core->cons->pal.reg, core->cons->pal.num);
|
||||
buf_hex = r_print_colorize_opcode (asmop.buf_hex,
|
||||
core->cons->pal.reg, core->cons->pal.num);
|
||||
otype = r_print_color_op_type (core->print, analop.type);
|
||||
r_cons_printf (" 0x%08"PFMT64x" %s%16s %s%s\n",
|
||||
hit->addr, otype, buf_hex, buf_asm, Color_RESET);
|
||||
free (buf_asm);
|
||||
free (buf_hex);
|
||||
}
|
||||
}
|
||||
r_cons_newline ();
|
||||
}
|
||||
r_cons_newline ();
|
||||
}
|
||||
}
|
||||
}
|
||||
free (buf);
|
||||
r_list_free(end_list);
|
||||
}
|
||||
|
||||
if (json)
|
||||
@ -768,6 +815,7 @@ static int r_core_search_rop(RCore *core, ut64 from, ut64 to, int opt, const cha
|
||||
}
|
||||
|
||||
r_list_free (rx_list);
|
||||
r_list_free (end_list);
|
||||
free (gregexp);
|
||||
|
||||
return R_TRUE;
|
||||
|
@ -1158,10 +1158,12 @@ R_API int r_core_config_init(RCore *core) {
|
||||
SETCB("search.in", "file", &cb_searchin, "Specify search boundaries (raw, block, file, section)");
|
||||
SETI("search.kwidx", 0, "Store last search index count");
|
||||
SETPREF("search.prefix", "hit", "Prefix name in search hits label");
|
||||
SETI("search.roplen", 5, "Maximum number of instructions for a ROP Gadget");
|
||||
SETPREF("search.show", "true", "Show search results while found (disable if lot of hits)");
|
||||
SETI("search.to", -1, "Search end address");
|
||||
SETPREF("search.conditionalrop", "false", "Use conditional jump, calls and returns for ropsearch too");
|
||||
|
||||
/* rop */
|
||||
SETI("rop.len", 5, "Maximum number of instructions for a ROP Gadget");
|
||||
SETPREF("rop.conditional", "false", "Use conditional jump, calls and returns for ropsearch too");
|
||||
|
||||
/* io */
|
||||
SETICB("io.enforce", 0, &cb_ioenforce, "Honor IO section permissions for 1=read , 2=write, 0=none");
|
||||
|
Loading…
Reference in New Issue
Block a user