From d6e643ceb8c8de633bdbf5be433fb5d8611669e6 Mon Sep 17 00:00:00 2001 From: Tim Strazzere Date: Tue, 25 Aug 2015 15:22:56 -0700 Subject: [PATCH 1/7] Update dependant libraries for OSX --- COMPILE.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/COMPILE.TXT b/COMPILE.TXT index 6e646547..57c2a629 100644 --- a/COMPILE.TXT +++ b/COMPILE.TXT @@ -7,10 +7,10 @@ Linux, *BSD & Solaris. We also show steps to cross-compile for Microsoft Windows Unicorn requires few dependent packages as followings -- For Mac OS X, "pkg-config" is needed. - Brew users can install "pkg-config" with: +- For Mac OS X, "pkg-config" and "glib" are needed. + Brew users can install "pkg-config" and "glib" with: - $ brew install pkg-config + $ brew install pkg-config glib - For Linux, glib2-dev is needed. Ubuntu/Debian users can install this with: From 22b549a4db464dcb4dc2a7b9f5795a6797fa259a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 26 Aug 2015 09:25:29 +0800 Subject: [PATCH 2/7] x86: add sample for 16bit mode --- bindings/python/sample_x86.py | 33 +++++++++++++++++++ samples/sample_all.sh | 2 ++ samples/sample_x86.c | 61 +++++++++++++++++++++++++++++++++-- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/bindings/python/sample_x86.py b/bindings/python/sample_x86.py index 8f8f361b..24b82450 100755 --- a/bindings/python/sample_x86.py +++ b/bindings/python/sample_x86.py @@ -13,6 +13,7 @@ X86_CODE32_MEM_WRITE = b"\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov [0xaaaaaaaa], e X86_CODE64 = b"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" X86_CODE32_INOUT = b"\x41\xE4\x3F\x4a\xE6\x46\x43" # INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx X86_CODE64_SYSCALL = '\x0f\x05' # SYSCALL +X86_CODE16 = '\x00\x00' # add byte ptr [bx + si], al # memory address where emulation starts ADDRESS = 0x1000000 @@ -437,6 +438,36 @@ def test_x86_64_syscall(): print("ERROR: %s" % e) +def test_x86_16(): + print("Emulate x86 16-bit code") + try: + # Initialize emulator in X86-16bit mode + mu = Uc(UC_ARCH_X86, UC_MODE_16) + + # map 8KB memory for this emulation + mu.mem_map(0, 8 * 1024) + + # set CPU registers + mu.reg_write(UC_X86_REG_EAX, 7) + mu.reg_write(UC_X86_REG_EBX, 5) + mu.reg_write(UC_X86_REG_ESI, 6) + + # write machine code to be emulated to memory + mu.mem_write(0, X86_CODE16) + + # emulate machine code in infinite time + mu.emu_start(0, len(X86_CODE16)) + + # now print out some registers + print(">>> Emulation done. Below is the CPU context") + + tmp = mu.mem_read(11, 1) + print("[0x%x] = 0x%x" %(11, tmp[0])) + + except UcError as e: + print("ERROR: %s" % e) + + if __name__ == '__main__': test_i386() print("=" * 20) @@ -451,3 +482,5 @@ if __name__ == '__main__': test_x86_64() print("=" * 20) test_x86_64_syscall() + print("=" * 20) + test_x86_16() diff --git a/samples/sample_all.sh b/samples/sample_all.sh index 7182a75d..e4ff7d48 100755 --- a/samples/sample_all.sh +++ b/samples/sample_all.sh @@ -15,6 +15,8 @@ if test -e $DIR/sample_x86; then $DIR/sample_x86 -32 echo "==========================" $DIR/sample_x86 -64 + echo "==========================" + $DIR/sample_x86 -16 fi if test -e $DIR/sample_arm; then echo "==========================" diff --git a/samples/sample_x86.c b/samples/sample_x86.c index b62e829e..b0dec117 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -24,7 +24,8 @@ //#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash //#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" -#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" //\xc3" +#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" +#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al // memory address where emulation starts #define ADDRESS 0x1000000 @@ -672,6 +673,58 @@ static void test_x86_64(void) uc_close(&handle); } +static void test_x86_16(void) +{ + uch handle; + uc_err err; + uint8_t tmp; + + int32_t eax = 7; + int32_t ebx = 5; + int32_t esi = 6; + + printf("Emulate x86 16-bit code\n"); + + // Initialize emulator in X86-16bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_16, &handle); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + // map 8KB memory for this emulation + uc_mem_map(handle, 0, 8 * 1024); + + // write machine code to be emulated to memory + if (uc_mem_write(handle, 0, (uint8_t *)X86_CODE16, sizeof(X86_CODE64) - 1)) { + printf("Failed to write emulation code to memory, quit!\n"); + return; + } + + // initialize machine registers + uc_reg_write(handle, UC_X86_REG_EAX, &eax); + uc_reg_write(handle, UC_X86_REG_EBX, &ebx); + uc_reg_write(handle, UC_X86_REG_ESI, &esi); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(handle, 0, sizeof(X86_CODE16) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + // read from memory + if (!uc_mem_read(handle, 11, &tmp, 1)) + printf(">>> Read 1 bytes from [0x%x] = 0x%x\n", 11, tmp); + else + printf(">>> Failed to read 1 bytes from [0x%x]\n", 11); + + uc_close(&handle); +} int main(int argc, char **argv, char **envp) { if (argc == 2) { @@ -689,6 +742,10 @@ int main(int argc, char **argv, char **envp) test_x86_64(); } + if (!strcmp(argv[1], "-16")) { + test_x86_16(); + } + // test memleak if (!strcmp(argv[1], "-0")) { while(1) { @@ -697,7 +754,7 @@ int main(int argc, char **argv, char **envp) } } } else { - printf("Syntax: %s <-32|-64>\n", argv[0]); + printf("Syntax: %s <-16|-32|-64>\n", argv[0]); } return 0; From cc5d28e112e011bd905205ee73ec3a6ecfff7f1e Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 26 Aug 2015 09:39:09 +0800 Subject: [PATCH 3/7] mips: fix issue #39 --- qemu/target-mips/translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index bc517d3e..4dbad582 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -19169,9 +19169,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, int num_insns; int max_insns; int insn_bytes; - int is_slot; + int is_slot = 0; TCGContext *tcg_ctx = env->uc->tcg_ctx; - TCGArg *save_opparam_ptr; + TCGArg *save_opparam_ptr = NULL; if (search_pc) qemu_log("search pc %d\n", search_pc); From 91c9c89650d1c4d3482f1e0d7faaf8e0bdb90a92 Mon Sep 17 00:00:00 2001 From: mothran Date: Tue, 25 Aug 2015 18:48:12 -0700 Subject: [PATCH 4/7] added regression test for fstcw not writing to memory --- regress/fpu_mem_write.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 regress/fpu_mem_write.py diff --git a/regress/fpu_mem_write.py b/regress/fpu_mem_write.py new file mode 100644 index 00000000..730914a6 --- /dev/null +++ b/regress/fpu_mem_write.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +from unicorn import * +from unicorn.x86_const import * + +ESP = 0x2000 +PAGE_SIZE = 1 * 1024 * 1024 + +# fstcw [esp] +# pop ecx +CODE = b'\x9B\xD9\x3C\x24\x59' + +def mem_reader(addr, size): + tmp = mu.mem_read(addr, size) + + for i in tmp: + print(" 0x%x" % i), + print("") + +def hook_mem_write(uc, access, address, size, value, user_data): + print("mem WRITE: 0x%x, data size = %u, data value = 0x%x" % (address, size, value)) + return True + +mu = Uc(UC_ARCH_X86, UC_MODE_32) +mu.mem_map(0, PAGE_SIZE) +mu.mem_write(0, CODE) +mu.reg_write(UC_X86_REG_ESP, ESP) +mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_write) + +mu.emu_start(0x0, 0, 0, 2) +esp = mu.reg_read(UC_X86_REG_ESP) +print("value at ESP [0x%X]: " % esp) +mem_reader(esp, 10) \ No newline at end of file From 2174ab61e467da27dcafa14c3070cae60775d807 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 26 Aug 2015 09:54:51 +0800 Subject: [PATCH 5/7] chmod +x regress/memmap_segfault2.py --- regress/memmap_segfault2.py | 2 ++ 1 file changed, 2 insertions(+) mode change 100644 => 100755 regress/memmap_segfault2.py diff --git a/regress/memmap_segfault2.py b/regress/memmap_segfault2.py old mode 100644 new mode 100755 index 39dd9a64..1c077ac6 --- a/regress/memmap_segfault2.py +++ b/regress/memmap_segfault2.py @@ -1,3 +1,5 @@ +#!/usr/bin/python + from unicorn import * uc = Uc(UC_ARCH_X86, UC_MODE_32) uc.mem_map(0x0000, 0x2000) From e1b8bc2ed0542fa4fdf8ad0bb586814c45030ade Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 26 Aug 2015 10:02:05 +0800 Subject: [PATCH 6/7] chmod +x regress/fpu_mem_write.py --- regress/fpu_mem_write.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 regress/fpu_mem_write.py diff --git a/regress/fpu_mem_write.py b/regress/fpu_mem_write.py old mode 100644 new mode 100755 From 70cdbf8c69330461f808d6ce010e53ee0c3571b9 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 26 Aug 2015 11:29:14 +0800 Subject: [PATCH 7/7] uc_mem_map(): enforce address & size to be aligned to 4KB. this fixes bunch of regress tests in regress/ --- include/unicorn/unicorn.h | 6 +++--- uc.c | 17 +++++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index a3293920..66de81eb 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -390,9 +390,9 @@ uc_err uc_hook_del(uch handle, uch *h2); @handle: handle returned by uc_open() @address: starting address of the new memory region to be mapped in. - This address will be round down to 8KB boundary - @size: size of the new memory region to be mapped in. This will be round up to - the next 8KB boundary. + This address must be aligned to 4KB, or this will return with UC_ERR_MAP error. + @size: size of the new memory region to be mapped in. + This size must be multiple of 4KB, or this will return with UC_ERR_MAP error. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). diff --git a/uc.c b/uc.c index 65179095..5a798f57 100644 --- a/uc.c +++ b/uc.c @@ -535,7 +535,6 @@ UNICORN_EXPORT uc_err uc_mem_map(uch handle, uint64_t address, size_t size) { struct uc_struct* uc = (struct uc_struct *)handle; - size_t s; if (handle == 0) // invalid handle @@ -545,11 +544,17 @@ uc_err uc_mem_map(uch handle, uint64_t address, size_t size) // invalid memory mapping return UC_ERR_MAP; - // align to 8KB boundary - map_begin[map_count] = address & (~ (8*1024 - 1)); - s = (size + 8*1024 - 1) & (~ (8*1024 - 1)); - map_end[map_count] = s + map_begin[map_count]; - uc->memory_map(uc, map_begin[map_count], s); + // address must be aligned to 4KB + if ((address & (4*1024 - 1)) != 0) + return UC_ERR_MAP; + + // size must be multiple of 4KB + if ((size & (4*1024 - 1)) != 0) + return UC_ERR_MAP; + + map_begin[map_count] = address; + map_end[map_count] = size + map_begin[map_count]; + uc->memory_map(uc, map_begin[map_count], size); map_count++; return UC_ERR_OK;