Implement x86 anal.jmp.retpoline switch tables (spectre/meltdown) ##anal (#16391)
This commit is contained in:
parent
dc790f5250
commit
eaa46ca936
|
@ -360,6 +360,43 @@ static void fcn_takeover_block_recursive(RAnalFunction *fcn, RAnalBlock *start_b
|
|||
r_anal_block_recurse (start_block, fcn_takeover_block_recursive_cb, fcn);
|
||||
}
|
||||
|
||||
static const char *retpoline_reg(RAnal *anal, ut64 addr) {
|
||||
RFlagItem *flag = anal->flag_get (anal->flb.f, addr);
|
||||
if (flag) {
|
||||
const char *token = "x86_indirect_thunk_";
|
||||
const char *thunk = strstr (flag->name, token);
|
||||
if (thunk) {
|
||||
return thunk + strlen (token);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// TODO: implement following code analysis check for stripped binaries:
|
||||
// 1) op(addr).type == CALL
|
||||
// 2) call_dest = op(addr).addr
|
||||
// 3) op(call_dest).type == STORE
|
||||
// 4) op(call_dest + op(call_dest).size).type == RET
|
||||
[0x00000a65]> pid 6
|
||||
0x00000a65 sym.__x86_indirect_thunk_rax:
|
||||
0x00000a65 .------- e807000000 call 0xa71
|
||||
0x00000a6a | f390 pause
|
||||
0x00000a6c | 0faee8 lfence
|
||||
0x00000a6f | ebf9 jmp 0xa6a
|
||||
0x00000a71 `----> 48890424 mov qword [rsp], rax
|
||||
0x00000a75 c3 ret
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void analyze_retpoline(RAnal *anal, RAnalOp *op) {
|
||||
if (anal->opt.retpoline) {
|
||||
const char *rr = retpoline_reg (anal, op->jump);
|
||||
if (rr) {
|
||||
op->type = R_ANAL_OP_TYPE_RJMP;
|
||||
op->reg = rr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int depth) {
|
||||
const int continue_after_jump = anal->opt.afterjmp;
|
||||
const int addrbytes = anal->iob.io ? anal->iob.io->addrbytes : 1;
|
||||
|
@ -677,6 +714,7 @@ repeat:
|
|||
// swapped parameters wtf
|
||||
r_anal_xrefs_set (anal, op.addr, op.ptr, R_ANAL_REF_TYPE_DATA);
|
||||
}
|
||||
analyze_retpoline (anal, &op);
|
||||
switch (op.type & R_ANAL_OP_TYPE_MASK) {
|
||||
case R_ANAL_OP_TYPE_CMOV:
|
||||
case R_ANAL_OP_TYPE_MOV:
|
||||
|
|
|
@ -212,6 +212,12 @@ static bool cb_debug_hitinfo(void *user, void *data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool cb_anal_jmpretpoline(void *user, void *data) {
|
||||
RCore *core = (RCore*) user;
|
||||
RConfigNode *node = (RConfigNode*) data;
|
||||
core->anal->opt.retpoline = node->i_value;
|
||||
return true;
|
||||
}
|
||||
static bool cb_anal_jmptailcall(void *user, void *data) {
|
||||
RCore *core = (RCore*) user;
|
||||
RConfigNode *node = (RConfigNode*) data;
|
||||
|
@ -2869,6 +2875,7 @@ R_API int r_core_config_init(RCore *core) {
|
|||
"anal.fcn", "anal.bb",
|
||||
NULL);
|
||||
SETI ("anal.timeout", 0, "Stop analyzing after a couple of seconds");
|
||||
SETCB ("anal.jmp.retpoline", "true", &cb_anal_jmpretpoline, "Analyze retpolines, may be slower if not needed");
|
||||
SETICB ("anal.jmp.tailcall", 0, &cb_anal_jmptailcall, "Consume a branch as a call if delta is big");
|
||||
|
||||
SETCB ("anal.armthumb", "false", &cb_analarmthumb, "aae computes arm/thumb changes (lot of false positives ahead)");
|
||||
|
|
|
@ -1696,7 +1696,7 @@ static int __runMain(RMainCallback cb, const char *arg) {
|
|||
char *a = r_str_trim_dup (arg);
|
||||
int argc = 0;
|
||||
char **args = r_str_argv (a, &argc);
|
||||
int res = cb (argc, args);
|
||||
int res = cb (argc, (const char **)args);
|
||||
free (args);
|
||||
free (a);
|
||||
return res;
|
||||
|
|
|
@ -1607,7 +1607,7 @@ static int cmd_open(void *data, const char *input) {
|
|||
char *uri = r_str_newf ("malloc://%d", len);
|
||||
ut8 *data = calloc (len, 1);
|
||||
r_io_read_at (core->io, core->offset, data, len);
|
||||
if (file = r_core_file_open (core, uri, R_PERM_RWX, 0)) {
|
||||
if ((file = r_core_file_open (core, uri, R_PERM_RWX, 0))) {
|
||||
fd = file->fd;
|
||||
core->num->value = fd;
|
||||
r_core_bin_load (core, uri, 0);
|
||||
|
|
|
@ -581,6 +581,7 @@ typedef struct r_anal_options_t {
|
|||
bool endsize; // chop function size which is known to be buggy but goodie too
|
||||
bool delay;
|
||||
int tailcall;
|
||||
bool retpoline;
|
||||
} RAnalOptions;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -3410,3 +3410,31 @@ e asm.bits=64
|
|||
ar=
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=x86_64 retpoline jmptbl
|
||||
FILE=../bins/elf/retpoline
|
||||
EXPECT=<<EOF
|
||||
3:
|
||||
2:
|
||||
1:
|
||||
0:
|
||||
4:
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
s 0x780
|
||||
af
|
||||
pdr~- case[2]
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=x86_64 retpoline disabled jmptbl
|
||||
FILE=../bins/elf/retpoline
|
||||
EXPECT=<<EOF
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
e anal.jmp.retpoline = false
|
||||
s 0x780
|
||||
af
|
||||
pdr~- case[2]
|
||||
EOF
|
||||
RUN
|
||||
|
|
Loading…
Reference in New Issue