Fuzz前置技能-unicorn模拟执行

  • 以下为C调用unicorn框架测试代码

    #include<stdio.h> #include<unicorn/unicorn.h> #include<string.h> #define ADDRESS 0x1000000 #define X86_CODE32 "\x41\x4a\x66\x0f\xef\xc1" // INC ecx; DEC edx; PXOR xmm0, xmm1 // 在终端中输出起始地址和硬编码大小 static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); } // hook 回调函数,用于监视程序运行时的变化 static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { int eflags; printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags); //获取寄存器值放入eflags变量中 printf(">>> --- EFLAGS is 0x%x\n", eflags); // Uncomment below code to stop the emulation using uc_emu_stop() // if (address == 0x1000009) // uc_emu_stop(uc); } static void test_i386(void) { uc_engine *uc; uc_err err; uint32_t tmp; uc_hook trace1, trace2; int r_ecx = 0x1234; // ECX 寄存器 int r_edx = 0x7890; // EDX 寄存器 // XMM0 、 XMM1 寄存器, 数组分别为低64位和高64位 uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607}; uint64_t r_xmm1[2] = {0x8090a0b0c0d0e0f0, 0x0010203040506070}; printf("Emulate i386 code\n"); // 初始化x86环境 err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err) { printf("Failed on uc_open() with error returned: %u\n", err); return; } // 为模拟执行代码申请 2MB 内存 uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // 向目标地址写入opcode if (uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } // 初始化寄存器ECX、EDX、XMM0、XMM1 uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); uc_reg_write(uc, UC_X86_REG_XMM0, &r_xmm0); uc_reg_write(uc, UC_X86_REG_XMM1, &r_xmm1); // 在函数内插桩,成功时会调用回调函数 uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // 每当代码执行时调用回调函数 uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // 模拟执行 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)); } // 最后输出一些模拟执行完成后寄存器的值 printf(">>> Emulation done. Below is the CPU context\n"); uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); uc_reg_read(uc, UC_X86_REG_XMM0, &r_xmm0); printf(">>> ECX = 0x%x\n", r_ecx); printf(">>> EDX = 0x%x\n", r_edx); printf(">>> XMM0 = 0x%.16"PRIx64"%.16"PRIx64"\n", r_xmm0[1], r_xmm0[0]); // 读取内存中的内容 if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp))) printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, tmp); else printf(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS); // 最后需要关闭,否则会导致内存泄露 uc_close(uc); } int main(){ test_i386(); return 0; } 

    编辑Makefile进行编译:

    LDFLAGS += $(shell pkg-config --libs glib-2.0) -lpthread -lm -lunicorn all: test2 %: %.c $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ 

    上面的Makefile等同于命令:

    cc test2.c -L/usr/local/Cellar/glib/2.70.1/lib -L/usr/local/opt/gettext/lib -lglib-2.0 -lintl -lpthread -lm -lunicorn -o test2 

    运行结果如下:

    Emulate i386 code >>> Tracing basic block at 0x1000000, block size = 0x6 >>> Tracing instruction at 0x1000000, instruction size = 0x1 >>> --- EFLAGS is 0x0 >>> Tracing instruction at 0x1000001, instruction size = 0x1 >>> --- EFLAGS is 0x4 >>> Tracing instruction at 0x1000002, instruction size = 0x4 >>> --- EFLAGS is 0x10 >>> Emulation done. Below is the CPU context >>> ECX = 0x1235 >>> EDX = 0x788f >>> XMM0 = 0x00112233445566778899aabbccddeeff >>> Read 4 bytes from [0x1000000] = 0xf664a41 
  • 本网页由快兔兔AI采集器生成,目的为演示采集效果,若侵权请及时联系删除。

    原文链接:https://www.cnblogs.com/unr4v31/p/15590901.html

    更多内容