From 726f45b33d7f87e197517ec20d79a3bbcade7791 Mon Sep 17 00:00:00 2001 From: farmdve Date: Tue, 10 Nov 2015 00:49:01 +0200 Subject: [PATCH] Attempting to set some bits in the Unicorn EFLAGS doesn't work. When attempting to set all flags except trap flag, the EFLAGS value should be 0x00244ED7, I've tested this on Windows and here https://ideone.com/WQAvk1 which is presumably Linux. Unicorn however has the value 0x00000ED7, bits 11-21 are not set. Bit 21 is the ID bit indicating whether or not CPUID is available. --- tests/regress/Makefile | 1 + tests/regress/eflags_noset.c | 106 +++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 tests/regress/eflags_noset.c diff --git a/tests/regress/Makefile b/tests/regress/Makefile index 8e57d10f..d056e4d6 100644 --- a/tests/regress/Makefile +++ b/tests/regress/Makefile @@ -14,6 +14,7 @@ TESTS += mem_exec TESTS += mips_kseg0_1 TESTS += eflags_nosync TESTS += 00opcode_uc_crash +TESTS += eflags_noset all: $(TESTS) diff --git a/tests/regress/eflags_noset.c b/tests/regress/eflags_noset.c new file mode 100644 index 00000000..4255bec5 --- /dev/null +++ b/tests/regress/eflags_noset.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include + +#include + +#define X86_CODE32 "\x9C\x68\xFF\xFE\xFF\xFF\x9D\x9C\x58\x9D" // pushf; push ffffffeff; popf; pushf; pop eax; popf +#define ADDRESS 0x1000000 +#define PAGE_8K (1 << 13) +#define PAGE_4K (1 << 12) +#define TARGET_PAGE_MASK ~(PAGE_4K - 1) +#define TARGET_PAGE_PREPARE(addr) (((addr) + PAGE_4K - 1) & TARGET_PAGE_MASK) +#define TARGET_PAGE_ALIGN(addr) (addr - (TARGET_PAGE_PREPARE(addr) - addr) & TARGET_PAGE_MASK) + +unsigned int realEflags() +{ + unsigned int val = 0; + unsigned int i = 0xFFFFFEFF; //attempt to set ALL bits except trap flag. + + __asm__("pushf\n\t" + "push %0\n\t" + "popf\n\t" + "pushf\n\t" + "pop %0\n\t" + "popf" + : "=r"(val) + : "r"(i) + : "%0"); + + printf("Real system eflags: 0x%08X\n", val); + + return val; +} + +static void VM_exec() +{ + uc_engine *uc; + uc_err err; + unsigned int r_eax, eflags, r_esp, realflags = 0; + + r_eax = 0; + r_esp = ADDRESS+0x100; //some safe distance from main code. + eflags = 0x00000206; + + // 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), 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_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); + + // 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_EFLAGS, &eflags); + + uc_close(uc); + + printf(">>> Emulation done. Below is the CPU context\n"); + printf(">>> EAX = 0x%08X\n", r_eax); + printf(">>> EFLAGS = 0x%08X\n", eflags); + + realflags = realEflags(); + + assert(r_eax == realflags); + + puts("Unicorn EFLAGS match expected system eflags"); +} + + +int main(int argc, char *argv[]) +{ + VM_exec(); + return 0; +}