unicorn模拟执行初探
unicorn模拟执行初探
参考博客:
[[翻译]Unicorn引擎教程]: https://bbs.kanxue.com/thread-224330.htm#msg_header_h3_2
[unicorn模拟执行初探]: https://eps1l0h.github.io/2023/01/18/unicorn%E5%88%9D%E6%8E%A2/
[[Android 原创] 汇编与反汇编神器Unicorn]: https://www.52pojie.cn/thread-1026209-1-1.html
什么是unicorn?
Unicorn是一个轻量级,多平台,多架构的CPU模拟器框架,基于qemu开发,它可以代替CPU模拟代码的执行,就比如说我们需要调试某个程序,常见的调试器需要配置可执行文件需要的环境并且还需要考虑一些恶意代码导致的安全问题,但是通过unicorn我们就可以单纯的模拟代码的执行(甚至可以指定从某个地址开始执行)而不需要考虑这些问题。
Unicorn的优点(也是基于qemu而开发的):
- 支持多种架构: Arm, Arm64 (Armv8), M68K, Mips, Sparc, & X86 (include X86_64).
- Unicorn 为多种语言提供编程接口比如C/C++、Python、Java 等语言。Unicorn的DLL 可以被更多的语言调用,比如易语言、Delphi,前途无量。
- 对Windows和nix系统(已确认包含Mac OSX, Linux, BSD & Solaris)的原生支持
- 具有平台独立且简洁易于使用的API
- 使用JIT编译技术, 性能表现优异
快速入门:
虚拟内存
Unicorn 采用虚拟内存机制,使得虚拟CPU的内存与真实CPU的内存隔离。Unicorn 使用如下API来操作内存:
1 | uc_mem_map |
这三个 API 都与内存操作有关:
1 | uc_mem_map:这个 API 用于映射内存。当你需要在 Unicorn 中模拟一个程序时,可以使用 uc_mem_map 将一块内存映射到指定的地址。注意,这里的地址和大小都需要与 0x1000 对齐,也就是 0x1000 的整数倍。如果不满足对齐要求,会报 UC_ERR_ARG 异常123。 |
Hook 机制
Unicorn的Hook机制为编程控制虚拟CPU提供了便利。
Unicorn 支持多种不同类型的Hook。
大致可以分为(hook_add第一参数,Unicorn常量):
指令执行类
1 | UC_HOOK_INTR |
这几个 API 都与 Unicorn 模拟器中的钩子(hook)有关:
1 | UC_HOOK_INTR:这个 API 用于钩住特定的指令,但只支持非常少的指令。具体来说,它用于在模拟执行过程中拦截某个特定的指令。这个功能在调试和分析代码时非常有用。 |
内存访问类
1 | UC_HOOK_MEM_READ |
1 | UC_HOOK_MEM_READ:这个 API 用于在模拟器执行期间钩住内存读取操作。当模拟执行到读取内存的指令时,可以使用这个钩子来执行自定义的操作。这对于跟踪内存访问、分析代码执行流程等非常有帮助。 |
异常处理类
1 | UC_HOOK_MEM_READ_UNMAPPED |
1 | UC_HOOK_MEM_READ_UNMAPPED:这个 API 用于在模拟器执行期间钩住对未映射内存的读取操作。当模拟执行到一个未映射的内存地址时,可以使用这个钩子来处理内存读取操作。例如,如果程序试图读取一个未映射的内存地址,可以在这里添加自定义的逻辑。 |
注意:调用hook_add函数可添加一个Hook。Unicorn的Hook是链式的,而不是传统Hook的覆盖式,也就是说,可以同时添加多个同类型的Hook,Unicorn会依次调用每一个handler。hook callback 是有作用范围的(见hook_add begin参数)。