Jump tables #1: direct jump

This commit is contained in:
Dima Turchenkov 2015-11-20 11:33:48 +03:00 committed by pancake
parent 02643892fe
commit 5d4001cf13
4 changed files with 32 additions and 3 deletions

View File

@ -19,6 +19,9 @@
// 256KB max function size
#define MAX_FCN_SIZE (1024*256)
#define MAX_JMPTBL_SIZE 1000
#define MAX_JMPTBL_JMP 10000
#define DB a->sdb_fcns
#define EXISTS(x,y...) snprintf (key, sizeof(key)-1,x,##y),sdb_exists(DB,key)
#define SETKEY(x,y...) snprintf (key, sizeof (key)-1, x,##y);
@ -601,6 +604,25 @@ repeat:
#endif
break;
case R_ANAL_OP_TYPE_UJMP:
// switch statement
if (op.ptr != UT64_MAX && anal->opt.jmptbl) {
ut8 *jmptbl = malloc(MAX_JMPTBL_SIZE);
ut64 offs, sz = anal->bits >> 3;
anal->iob.read_at (anal->iob.io, op.ptr, jmptbl, MAX_JMPTBL_SIZE);
for (offs = 0; offs < MAX_JMPTBL_SIZE; offs += sz) {
ut64 jmpptr = 0;
r_mem_copyendian ((ut8*)&jmpptr, jmptbl + offs, sz, !anal->big_endian);
if (anal->limit) {
if (jmpptr < anal->limit->from || jmpptr > anal->limit->to)
break;
}
if (jmpptr < addr + idx - MAX_JMPTBL_JMP ||
jmpptr > addr + idx + MAX_JMPTBL_JMP)
break;
recurseAt (jmpptr);
}
free(jmptbl);
}
if (continue_after_jump)
break;
/* fallthru */

View File

@ -1000,15 +1000,13 @@ SETL/SETNGE
break;
case X86_OP_MEM:
op->type = R_ANAL_OP_TYPE_UJMP;
op->ptr = INSOP(0).mem.disp;
if (INSOP(0).mem.base == X86_REG_RIP) {
op->ptr = INSOP(0).mem.disp;
op->ptr += addr + insn->size;
op->refptr = 8;
} else {
cs_x86_op in = INSOP(0);
if (in.mem.index == 0 && in.mem.base == 0 && in.mem.scale == 1) {
op->type = R_ANAL_OP_TYPE_UJMP;
op->ptr = in.mem.disp;
if (a->decode) {
esilprintf (op, "0x%"PFMT64x",[],%s,=", op->ptr, pc);
}

View File

@ -1233,6 +1233,12 @@ static int cb_anal_limits(void *user, RConfigNode *node) {
return 1;
}
static int cb_anal_jmptbl(void *user, void *data) {
RCore *core = (RCore*) user;
RConfigNode *node = (RConfigNode*) data;
core->anal->opt.jmptbl = node->i_value;
return true;
}
#define SLURP_LIMIT (10*1024*1024)
R_API int r_core_config_init(RCore *core) {
@ -1273,6 +1279,8 @@ R_API int r_core_config_init(RCore *core) {
SETI("anal.ptrdepth", 3, "Maximum number of nested pointers to follow in analysis");
SETICB("anal.maxreflines", 0, &cb_analmaxrefs, "Maximum number of reflines to be analyzed and displayed in asm.lines with pd");
SETCB("anal.jmptbl", "false", &cb_anal_jmptbl, "Analyze jump tables in switch statements");
SETPREF("esil.prestep", "true", "Step before esil evaluation in `de` commands");
SETCB("esil.debug", "false", &cb_esildebug, "Show ESIL debug info");
SETICB("esil.gotolimit", core->anal->esil_goto_limit, &cb_gotolimit, "Maximum number of gotos per ESIL expression");

View File

@ -573,6 +573,7 @@ typedef struct r_anal_options_t {
int bbsplit;
int noncode;
int nopskip; // skip nops at the beginning of functions
int jmptbl; // analyze jump tables
} RAnalOptions;
typedef struct r_anal_t {