一、概述

本章节介绍的是windows环境下unicorn框架和capstone框架的使用。

二、工具

Visual stdio 2019

Cmake

Git

三、构建步骤

1、clone unicorn和capstone框架的源码。(注意clone的分支为最新版本,不是master)

​git clone https://github.com/unicorn-engine/unicorn.gitgit clone https://github.com/capstone-engine/capstone.git​

2、编译unicorn

(1) 使用git bash或者cmd进入unicorn目录,执行下面几条命令

    mkdir buildcd buildcmake .. -G "Visual Studio 16 2019" -A "x64" -DCMAKE_BUILD_TYPE=Release

(2)接着在build目录下会生成一个unicorn.sln文件,使用visual stdio 2019打开,编译输出。在build目录下会生成unicorn.lib,在build/debug目录下会生成许多文件,只需要unicorn.dll即可。

3、编译capstone

(1)使用visual stdio 2019打开capstone/msvc目录下的capstone.sln文件,编译之后在capstone\msvc\x64\Debug目录下会生成capstone.dll和capstone.lib文件。

4、创建模拟器项目

使用visual stdio 2019创建一个新项目,然后导入上面两步骤生成的文件,再将上述框架中

capstone和unicorn头文件(在include目录下)放入工程根目录中。

5、实现代码

下面是模拟x86架构64位程序代码片段,其中test_00007FF6B9541000.bin是.text段的内存dump文件,test_00000039AB52A000.bin为.stack段内存dump,test_00007FF6B9549000.bin为.rdata段内存dump,test_00007FF6B954C000.bin为.data段内存dump,test_00007FF6B9531000.bin为.textbss段内存dump。


csh g_x64_cs_handle = NULL;
cs_insn* g_x64_cs_insn = NULL;
size_t g_x64_cs_count = 0;     // how many instruction that this capstone API disassembly successfully
cs_err  g_x64_cs_err = CS_ERR_OK;uc_engine* g_x64_uc = NULL;
uc_err g_x64_uc_err = UC_ERR_OK;       //  error number that unicorn emulate instructionDWORD64    g_x64_instruction_count = 0;REG_X86 g_x64_reg = { 0 };    // init register//#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00"VOID x64_init_registers()
{g_x64_reg.reg.r_rax = 0x00007FF6B9541230;g_x64_reg.reg.r_rcx =   0x00000039AB77F000;g_x64_reg.reg.r_rdx =   0x00007FF6B9541230;g_x64_reg.reg.r_rbx =   0x0000000000000000;g_x64_reg.reg.r_rsp =   0x00000039AB52FDB8;g_x64_reg.reg.r_rbp =   0x0000000000000000l;g_x64_reg.reg.r_rsi =   0x0000000000000000;g_x64_reg.reg.r_rdi =   0x0000000000000000;g_x64_reg.reg.r_rip =   0x00007FF6B9542330;g_x64_reg.reg.r_rflag = 0x0000000000000246;g_x64_reg.reg.r_r8 =    0x00000039AB77F000;g_x64_reg.reg.r_r9 =    0x00007FF6B9541230;g_x64_reg.reg.r_r10 =   0x00007FFFBD807C90;g_x64_reg.reg.r_r11 =   0x0000000000000000l;g_x64_reg.reg.r_r12 =   0x0000000000000000l;g_x64_reg.reg.r_r13 =   0x0000000000000000l;g_x64_reg.reg.r_r14 =   0x0000000000000000l;g_x64_reg.reg.r_r15 =   0x0000000000000000l;}x64_FileInformation fileinfo[] =
{//    BaseAddress                 FileSize                       Path                      allocate buffer address(PVOID)0x00007FF6B9541000        ,   0x8000      ,   L".\\x64_binary\\test_00007FF6B9541000.bin"   ,       NULL    , //.text(PVOID)0x00000039AB52A000      ,   0x6000      ,   L".\\x64_binary\\test_00000039AB52A000.bin"   ,       NULL    , //.stack(PVOID)0x00007FF6B9549000     ,   0x3000      ,   L".\\x64_binary\\test_00007FF6B9549000.bin"   ,       NULL    , //.rdata(PVOID)0x00007FF6B954C000     ,   0x1000      ,   L".\\x64_binary\\test_00007FF6B954C000.bin"   ,       NULL    , //.data(PVOID)0x00007FF6B9531000      ,   0x10000     ,   L".\\x64_binary\\test_00007FF6B9531000.bin"   ,       NULL    , //.textbss};VOID x64_emulate()
{g_x64_cs_err = cs_open(CS_ARCH_X86, CS_MODE_64, &g_x64_cs_handle);g_x64_uc_err = uc_open(UC_ARCH_X86, UC_MODE_64, &g_x64_uc);if (g_x64_cs_err || g_x64_uc_err){printf("ERROR: Failed to initialize engine!\n");return;}cs_option(g_x64_cs_handle, CS_OPT_DETAIL, CS_OPT_ON);for (ULONG i = 0; i < sizeof(fileinfo) / sizeof(fileinfo[0]); i++){FILE* pFile = NULL;fileinfo[i].buffer = (PVOID)malloc(fileinfo[i].FileSize);if (!fileinfo[i].buffer){printf("Allocate mem fail!\n");return;}pFile = _wfopen(fileinfo[i].FileName, L"rb");if (!pFile){printf("open file error code : <%d>\n", GetLastError());return;}fread(fileinfo[i].buffer, fileinfo[i].FileSize, 1, pFile);if (pFile)fclose(pFile);g_x64_uc_err = uc_mem_map(g_x64_uc, (DWORD64)fileinfo[i].BaseAddress, fileinfo[i].FileSize, UC_PROT_ALL);if (g_x64_uc_err){printf("uc mem map error!Error Code:<%d>\n", g_x64_uc_err);return;}g_x64_uc_err = uc_mem_write(g_x64_uc, (DWORD64)fileinfo[i].BaseAddress, fileinfo[i].buffer, fileinfo[i].FileSize);if (g_x64_uc_err){printf("uc mem write error!Error Code:<%d>\n", g_x64_uc_err);return;}}x64_init_registers();x64_write_uc_registers();BYTE Code[32] = { 0 };do{uc_mem_read(g_x64_uc, g_x64_reg.reg.r_rip, Code, sizeof(Code));g_x64_cs_count = cs_disasm(g_x64_cs_handle, Code, sizeof(Code), g_x64_reg.reg.r_rip, 1, &g_x64_cs_insn);if (!g_x64_cs_count)break;g_x64_uc_err = uc_emu_start(g_x64_uc, g_x64_reg.reg.r_rip, 0xffffffffffffffff, 0, 1);x64_read_uc_registers();x64_print_uc_registers();x64_print_uc_stack(g_x64_reg.reg.r_rsp);cs_free(g_x64_cs_insn, 1);if (g_x64_uc_err){printf("uc_emu_start error!Error Code:<%d>\n", g_x64_uc_err);break;}g_x64_instruction_count++;} while (g_x64_cs_count);cs_close(&g_x64_cs_handle);uc_close(g_x64_uc);}VOID x64_read_uc_registers()
{uc_reg_read(g_x64_uc, UC_X86_REG_RAX, &g_x64_reg.reg.r_rax);uc_reg_read(g_x64_uc, UC_X86_REG_RCX, &g_x64_reg.reg.r_rcx);uc_reg_read(g_x64_uc, UC_X86_REG_RDX, &g_x64_reg.reg.r_rdx);uc_reg_read(g_x64_uc, UC_X86_REG_RBX, &g_x64_reg.reg.r_rbx);uc_reg_read(g_x64_uc, UC_X86_REG_RSP, &g_x64_reg.reg.r_rsp);uc_reg_read(g_x64_uc, UC_X86_REG_RBP, &g_x64_reg.reg.r_rbp);uc_reg_read(g_x64_uc, UC_X86_REG_RSI, &g_x64_reg.reg.r_rsi);uc_reg_read(g_x64_uc, UC_X86_REG_RDI, &g_x64_reg.reg.r_rdi);uc_reg_read(g_x64_uc, UC_X86_REG_RIP, &g_x64_reg.reg.r_rip);uc_reg_read(g_x64_uc, UC_X86_REG_RFLAGS, &g_x64_reg.reg.r_rflag);uc_reg_read(g_x64_uc, UC_X86_REG_R8, &g_x64_reg.reg.r_r8);uc_reg_read(g_x64_uc, UC_X86_REG_R9, &g_x64_reg.reg.r_r9);uc_reg_read(g_x64_uc, UC_X86_REG_R10, &g_x64_reg.reg.r_r10);uc_reg_read(g_x64_uc, UC_X86_REG_R11, &g_x64_reg.reg.r_r11);uc_reg_read(g_x64_uc, UC_X86_REG_R12, &g_x64_reg.reg.r_r12);uc_reg_read(g_x64_uc, UC_X86_REG_R13, &g_x64_reg.reg.r_r13);uc_reg_read(g_x64_uc, UC_X86_REG_R14, &g_x64_reg.reg.r_r14);uc_reg_read(g_x64_uc, UC_X86_REG_R15, &g_x64_reg.reg.r_r15);}VOID x64_write_uc_registers()
{uc_reg_write(g_x64_uc, UC_X86_REG_RAX, &g_x64_reg.reg.r_rax);uc_reg_write(g_x64_uc, UC_X86_REG_RCX, &g_x64_reg.reg.r_rcx);uc_reg_write(g_x64_uc, UC_X86_REG_RDX, &g_x64_reg.reg.r_rdx);uc_reg_write(g_x64_uc, UC_X86_REG_RBX, &g_x64_reg.reg.r_rbx);uc_reg_write(g_x64_uc, UC_X86_REG_RSP, &g_x64_reg.reg.r_rsp);uc_reg_write(g_x64_uc, UC_X86_REG_RBP, &g_x64_reg.reg.r_rbp);uc_reg_write(g_x64_uc, UC_X86_REG_RSI, &g_x64_reg.reg.r_rsi);uc_reg_write(g_x64_uc, UC_X86_REG_RDI, &g_x64_reg.reg.r_rdi);uc_reg_write(g_x64_uc, UC_X86_REG_RIP, &g_x64_reg.reg.r_rip);uc_reg_write(g_x64_uc, UC_X86_REG_RFLAGS, &g_x64_reg.reg.r_rflag);uc_reg_write(g_x64_uc, UC_X86_REG_R8, &g_x64_reg.reg.r_r8);uc_reg_write(g_x64_uc, UC_X86_REG_R9, &g_x64_reg.reg.r_r9);uc_reg_write(g_x64_uc, UC_X86_REG_R10, &g_x64_reg.reg.r_r10);uc_reg_write(g_x64_uc, UC_X86_REG_R11, &g_x64_reg.reg.r_r11);uc_reg_write(g_x64_uc, UC_X86_REG_R12, &g_x64_reg.reg.r_r12);uc_reg_write(g_x64_uc, UC_X86_REG_R13, &g_x64_reg.reg.r_r13);uc_reg_write(g_x64_uc, UC_X86_REG_R14, &g_x64_reg.reg.r_r14);uc_reg_write(g_x64_uc, UC_X86_REG_R15, &g_x64_reg.reg.r_r15);}VOID   x64_print_uc_registers()
{printf("\n>--- --- --- %lld --- --- ---<\n", g_x64_instruction_count);printf("%#16llx:\t%s\t%s\n",g_x64_cs_insn[0].address,g_x64_cs_insn[0].mnemonic,g_x64_cs_insn[0].op_str);printf("rax=0x%16llx\n", g_x64_reg.reg.r_rax);printf("rcx=0x%16llx\n", g_x64_reg.reg.r_rcx);printf("rdx=0x%16llx\n", g_x64_reg.reg.r_rdx);printf("rbx=0x%16llx\n", g_x64_reg.reg.r_rbx);printf("rsp=0x%16llx\n", g_x64_reg.reg.r_rsp);printf("rbp=0x%16llx\n", g_x64_reg.reg.r_rbp);printf("rsi=0x%16llx\n", g_x64_reg.reg.r_rsi);printf("rdi=0x%16llx\n", g_x64_reg.reg.r_rdi);printf("rip=0x%16llx\n", g_x64_reg.reg.r_rip);printf("rfl=0x%16llx\n", g_x64_reg.reg.r_rflag);printf("r8 =0x%16llx\n", g_x64_reg.reg.r_r8);printf("r9 =0x%16llx\n", g_x64_reg.reg.r_r9);printf("r10=0x%16llx\n", g_x64_reg.reg.r_r10);printf("r11=0x%16llx\n", g_x64_reg.reg.r_r11);printf("r12=0x%16llx\n", g_x64_reg.reg.r_r12);printf("r13=0x%16llx\n", g_x64_reg.reg.r_r13);printf("r14=0x%16llx\n", g_x64_reg.reg.r_r14);printf("r15=0x%16llx\n", g_x64_reg.reg.r_r15);}VOID x64_print_uc_stack(DWORD64 rsp)
{DWORD64    val = 0;for (ULONG i = 5; i > 0; i--){uc_mem_read(g_x64_uc, (DWORD64)(rsp - i * 8), &val, sizeof(DWORD64));printf("\t|%16llx|\n", val);}uc_mem_read(g_x64_uc, (DWORD64)rsp, &val, sizeof(DWORD64));printf("===>    |%16llx|\n", val);for (ULONG i = 1; i < 5; i++){uc_mem_read(g_x64_uc, (DWORD64)(rsp + i * 8), &val, sizeof(DWORD64));printf("\t|%16llx|\n", val);}
}

上述代码是模拟x86_64程序,这个cpu模拟器框架还支持arm,aarch64,mips,risc-v

risc-v 64等汇编模拟。后续还会给出模拟risc-v 64程序的步骤。

学习过程中还有很多不足,还望朋友们指正!

构建一个CPU模拟器相关推荐

  1. AI:2023年6月9日北京智源大会演讲分享之基础模型前沿技术论坛—《工程化打造AI中的CPU》、《构建一个AI系统:在LLM上应用带有RLHF来推进定制》、《多模态预训练的进展回顾与展望》、《扩展大

    AI:2023年6月9日北京智源大会演讲分享之基础模型前沿技术论坛-<工程化打造AI中的CPU>.<构建一个AI系统:在LLM上应用带有RLHF来推进定制>.<多模态预训 ...

  2. 基于五阶段流水线的RISC-V CPU模拟器实现

    RISC-V是源自Berkeley的开源体系结构和指令集标准.这个模拟器实现的是RISC-V Specification 2.2中所规定RV64I指令集,基于标准的五阶段流水线,并且实现了分支预测模块 ...

  3. 基于PyTorch,如何构建一个简单的神经网络

    本文为 PyTorch 官方教程中:如何构建神经网络.基于 PyTorch 专门构建神经网络的子模块 torch.nn 构建一个简单的神经网络. 完整教程运行 codelab→ https://ope ...

  4. 从零构建一个简单的 Python 框架

    为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点: 你有一个新奇的想法,觉得将会取代其他的框架 你想要获得一些名气 你遇到的问题很独特,以至于现有的框架不太合适 你对 web 框架是如何 ...

  5. 构建一个分布式操作系统的简单方案—答陈硕的“分布式系统中的进程标识”一文...

    对分布式系统中的进程标识"一文的疑问 刚才看到陈硕先生的一篇blog:"分布式系统中的进程标识",地址:http://www.cnblogs.com/Solstice/a ...

  6. 转载:谢谢原作者:块设备驱动实战基础篇一 (170行代码构建一个逻辑块设备驱动)

    1   内核块设备驱动基础学习与实战 1.1 设备驱动IO架构初探 操作系统是如何将数据读到缓冲区的,发生了什么?我们带着这样的问题,粗略走一下read调用系统过程,希望这个初探,可以唤起大家研究操作 ...

  7. pip install pygame_使用 Python 和 Pygame 模块构建一个游戏框架!

    这系列的第一篇通过创建一个简单的骰子游戏来探究 Python.现在是来从零制作你自己的游戏的时间. 在我的这系列的第一篇文章 中, 我已经讲解如何使用 Python 创建一个简单的.基于文本的骰子游戏 ...

  8. pygame为游戏添加背景_万能的Python和Pygame模块构建一个游戏框架

    通过创建一个简单的骰子游戏来探究 Python.现在是来从零制作你自己的游戏的时间. 在我的这系列的第一篇文章中, 我已经讲解如何使用 Python 创建一个简单的.基于文本的骰子游戏.这次,我将展示 ...

  9. python pygame模块怎么写游戏_使用 Python 和 Pygame 模块构建一个游戏框架

    这系列的第一篇通过创建一个简单的骰子游戏来探究 Python.现在是来从零制作你自己的游戏的时间. 在我的这系列的第一篇文章 中, 我已经讲解如何使用 Python 创建一个简单的.基于文本的骰子游戏 ...

最新文章

  1. POJ 2516 Minimum Cost 最小费用流
  2. spring_通过Spring Boot了解H2 InMemory数据库
  3. 江苏省计算机学会科学技术奖,孙国梓
  4. Codeforces Round #632 (Div. 2) E. Road to 1600 构造好题
  5. centOs 7.2*64 ECS nginx安装教程
  6. 基于JAVA+SpringBoot+Mybatis+MYSQL的在线购物商城系统
  7. 【翻译】五步快速使用LINQPad尝鲜StreamInsight
  8. git 查看修改明细_git查看某个文件的修改历史
  9. eclipse插件:OpenExplorer快速打开文件目录
  10. Word 利用 VBA 批量设置图片格式
  11. SD内存卡格式化后如何数据恢复教程
  12. 如何选购计算机的硬盘,教你如何选配电脑—硬盘篇
  13. 【科大讯飞Face】
  14. 2014年全国专业技术人员计算机应用能力考试大纲,2014年全国专业技术人员计算机应用能力考试 Excel2003...
  15. nginx+uwsgi+django1.9+mysql+python2.7部署到CentOS6.5
  16. 数据库实体间关联关系:一对一、一对多、多对多
  17. 屏幕录像机(bb flashback pro 4)pjb v4.1.21
  18. 存储卡 android文件夹,安卓系统下SD卡文件夹功能介绍
  19. web网站的注销功能实现
  20. 应用“真心话大冒险”项目总结

热门文章

  1. Python Console报错:Cannot start process, the working directory does not exist
  2. 斗鱼上市,腾讯坐“快”观“虎斗”
  3. Android错误之(Android 6.0)Unable to add window android.view.ViewRootImpl$W@d4521e8 -- permission denied
  4. 数据中台:FastData云原生数据智能平台
  5. 四级英语——段落匹配(20分钟)
  6. linux重置定时关机,Linux 定时关机与重新启动
  7. java corba实例,OpenORB开发CORBA的实例介绍
  8. Excel如何隔列填充字体颜色
  9. Android UCV 同时打开多路摄像头
  10. C语言switch中break的作用,C语言switch中break语句的作用