Adding INSN hook checks for x86 (#833)

* adding INSN hook checking for x86

* tabs to spaces

* need to return bool not uc_err

* fixed conditional after switching to bool
This commit is contained in:
bulaza 2017-05-13 13:16:17 -04:00 committed by Nguyen Anh Quynh
parent 4b50ca5cec
commit 4b9efdc986
3 changed files with 25 additions and 1 deletions

View file

@ -78,6 +78,9 @@ typedef bool (*uc_args_int_t)(int intno);
// some architecture redirect virtual memory to physical memory like Mips // some architecture redirect virtual memory to physical memory like Mips
typedef uint64_t (*uc_mem_redirect_t)(uint64_t address); typedef uint64_t (*uc_mem_redirect_t)(uint64_t address);
// validate if Unicorn supports hooking a given instruction
typedef bool(*uc_insn_hook_validate)(uint32_t insn_enum);
struct hook { struct hook {
int type; // UC_HOOK_* int type; // UC_HOOK_*
int insn; // instruction for HOOK_INSN int insn; // instruction for HOOK_INSN
@ -169,6 +172,8 @@ struct uc_struct {
// TODO: remove current_cpu, as it's a flag for something else ("cpu running"?) // TODO: remove current_cpu, as it's a flag for something else ("cpu running"?)
CPUState *cpu, *current_cpu; CPUState *cpu, *current_cpu;
uc_insn_hook_validate insn_hook_validate;
MemoryRegion *system_memory; // qemu/exec.c MemoryRegion *system_memory; // qemu/exec.c
MemoryRegion io_mem_rom; // qemu/exec.c MemoryRegion io_mem_rom; // qemu/exec.c
MemoryRegion io_mem_notdirty; // qemu/exec.c MemoryRegion io_mem_notdirty; // qemu/exec.c

View file

@ -171,7 +171,7 @@ static int x86_msr_read(struct uc_struct *uc, uc_x86_msr *msr)
helper_rdmsr(env); helper_rdmsr(env);
msr->value = ((uint32_t)env->regs[R_EAX]) | msr->value = ((uint32_t)env->regs[R_EAX]) |
((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
env->regs[R_EAX] = eax; env->regs[R_EAX] = eax;
env->regs[R_ECX] = ecx; env->regs[R_ECX] = ecx;
@ -1335,6 +1335,17 @@ static bool x86_stop_interrupt(int intno)
void pc_machine_init(struct uc_struct *uc); void pc_machine_init(struct uc_struct *uc);
static bool x86_insn_hook_validate(uint32_t insn_enum)
{
//for x86 we can only hook IN, OUT, and SYSCALL
if (insn_enum != UC_X86_INS_IN
&& insn_enum != UC_X86_INS_OUT
&& insn_enum != UC_X86_INS_SYSCALL) {
return false;
}
return true;
}
DEFAULT_VISIBILITY DEFAULT_VISIBILITY
void x86_uc_init(struct uc_struct* uc) void x86_uc_init(struct uc_struct* uc)
{ {
@ -1350,6 +1361,7 @@ void x86_uc_init(struct uc_struct* uc)
uc->release = x86_release; uc->release = x86_release;
uc->set_pc = x86_set_pc; uc->set_pc = x86_set_pc;
uc->stop_interrupt = x86_stop_interrupt; uc->stop_interrupt = x86_stop_interrupt;
uc->insn_hook_validate = x86_insn_hook_validate;
uc_common_init(uc); uc_common_init(uc);
} }

7
uc.c
View file

@ -1036,6 +1036,13 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
hook->insn = va_arg(valist, int); hook->insn = va_arg(valist, int);
va_end(valist); va_end(valist);
if (uc->insn_hook_validate) {
if (! uc->insn_hook_validate(hook->insn)) {
free(hook);
return UC_ERR_HOOK;
}
}
if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) { if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) {
free(hook); free(hook);
return UC_ERR_NOMEM; return UC_ERR_NOMEM;