diff --git a/.gitignore b/.gitignore index e8723101..3952c8e5 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,7 @@ mips_branch_likely_issue test_mem_map_ptr test_mem_high rw_hookstack +hook_extrainvoke ################# diff --git a/tests/regress/Makefile b/tests/regress/Makefile index e5bde71f..8bb1d844 100644 --- a/tests/regress/Makefile +++ b/tests/regress/Makefile @@ -34,6 +34,7 @@ TESTS += rw_hookstack TESTS += threaded_emu_start TESTS += emu_stop_in_hook_overrun TESTS += mips_branch_likely_issue +TESTS += hook_extrainvoke all: $(TESTS) diff --git a/tests/regress/hook_extrainvoke.c b/tests/regress/hook_extrainvoke.c new file mode 100644 index 00000000..5f74e4d7 --- /dev/null +++ b/tests/regress/hook_extrainvoke.c @@ -0,0 +1,94 @@ +#include +#include +#include + +#include + +#define X86_CODE32 "\xf3\xab" // rep stosd dword ptr es:[edi], eax -> Fill (E)CX doublewords at ES:[(E)DI] with EAX +#define ADDRESS 0x1000000 +#define ECX_OPS 2 +static long unsigned int hook_called = 0; + +void hook_ins(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + hook_called++; + printf("hook called\n"); +} + +static void VM_exec() +{ + uc_engine *uc; + uc_err err; + uc_hook trace; + unsigned int r_eax, eflags, r_esp, r_edi, r_ecx; + + r_eax = 0xbaadbabe; + r_esp = ADDRESS+0x20; + r_edi = ADDRESS+0x300; //some safe distance from main code. + eflags = 0x00000206; + r_ecx = ECX_OPS; + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if(err) + { + printf("Failed on uc_open() with error returned: %s\n", uc_strerror(err)); + return; + } + + err = uc_mem_map(uc, ADDRESS, (2 * 1024 * 1024), UC_PROT_ALL); + if(err != UC_ERR_OK) + { + printf("Failed to map memory %s\n", uc_strerror(err)); + return; + } + + // write machine code to be emulated to memory + err = uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1); + if(err != UC_ERR_OK) + { + printf("Failed to write emulation code to memory, quit!: %s(len %lu)\n", uc_strerror(err), (unsigned long)sizeof(X86_CODE32) - 1); + return; + } + + // initialize machine registers + uc_reg_write(uc, UC_X86_REG_EAX, &r_eax); + uc_reg_write(uc, UC_X86_REG_EDI, &r_edi); + uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); + uc_reg_write(uc, UC_X86_REG_ESP, &r_esp); //make stack pointer point to already mapped memory so we don't need to hook. + uc_reg_write(uc, UC_X86_REG_EFLAGS, &eflags); + + uc_hook_add(uc, &trace, UC_HOOK_CODE, (void *)hook_ins, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time + err = uc_emu_start(uc, ADDRESS, ADDRESS + (sizeof(X86_CODE32) - 1), 0, 0); + if(err) + { + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + + uc_close(uc); + return; + } + + uc_reg_read(uc, UC_X86_REG_EAX, &r_eax); + uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); + uc_reg_read(uc, UC_X86_REG_EDI, &r_edi); + uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags); + + uc_close(uc); + + printf("\n>>> Emulation done. Below is the CPU context\n"); + printf(">>> EAX = 0x%08X\n", r_eax); + printf(">>> ECX = 0x%08X\n", r_ecx); + printf(">>> EDI = 0x%08X\n", r_edi); + printf(">>> EFLAGS = 0x%08X\n", eflags); + + printf("\nHook called %lu times. Test %s\n", hook_called, (hook_called == ECX_OPS ? "PASSED!!" : "FAILED!!!")); + +} + +int main(int argc, char *argv[]) +{ + VM_exec(); + return 0; +}