可以参考Lyle的这篇博客以及Firm-AFL的这篇论文
感觉上边的方法比下面的方法更加好理解,而且更加通用。

Lyle的方法

https://blog.lyle.ac.cn/2021/07/09/uemu/
这篇技术文章主要讲了在pc端用模拟器仿真失败的原因,和成功率高的仿真方案。

失败的根本原因

从大的角度看,不同厂商生成的设备,硬件环境、指令集架构、操作系统、网络协议都又不同的标准和实现方法。

模拟器运行固件程序,主要依赖于把待测程序的指令翻译成宿主机的指令,用户态的指令直接翻译即可。但如果用户态进程发出系统调用的命令,CPU就需要切到内核态执行系统调用,控制硬件等系统资源,模拟器得把系统调用转发给宿主机,让宿主机去执行,这个过程中如果构建客户机环境不成功,就仿真失败了。

解决方法就是对系统调用进行分类,再逐个解决。其中,进程管理、文件管理、设备管理这三类系统调用,在被模拟器转发至宿主机系统时,存在这些问题。其他几类系统调用,宿主机基本上可以成功执行。
图片.png

进程管理

有关进程状态转换、获取进程块各种信息、进程申请释放内存的系统调用。
客户机上的用户态程序fork一个新程序时,模拟器把系统调用转发到异架构的宿主机上执行,宿主机直接按本机的进程加载方式加载程序,这个程序无法执行。
这篇文章的解决方法是,当执行新程序的系统调用转发到Linux宿主机上时,通过Linux内核的一个功能binfmt_misc,识别fork或者exec出来的程序的架构,再次传递回模拟器执行该程序。

文件管理

完成创建删除、打开关闭、读写、设置文件属性等功能的系统调用。
固件提取时,文件系统可能不完整。

设备管理

I/O设备管理,申请释放设备的使用权,对设备进行操作。
宿主机缺失路由器的网络设备、I/O设备,不支持相关的系统调用。
图片.png

提高成功率的仿真方案

ptrace()控制系统调用

Playing with ptrace的译文
https://blog.csdn.net/ixidof/article/details/7673568
https://blog.csdn.net/weixin_30814319/article/details/96528600
ptrace()是Unix的一个系统调用,可以在用户层拦截和修改系统调用。
这个更详细

  1. #include <sys/ptrace.h>
  2. long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
  3. ptrace有四个参数:
  4. 1). enum __ptrace_request request:指示了ptrace要执行的命令。
  5. 2). pid_t pid: 指示ptrace要跟踪的进程。
  6. 3). void *addr: 指示要监控的内存地址。
  7. 4). void *data: 存放读取出的或者要写入的数据。

binfmt_misc传递异架构程序

文件系统重建

定制内核以模拟硬件

Firm-AFL中的方法

https://mp.weixin.qq.com/s/-s5GGA70vcHAVfyz1QeBtQ](https://mp.weixin.qq.com/s/-s5GGA70vcHAVfyz1QeBtQ