固件模拟

什么是固件模拟?

固件模拟是通过一些模拟器实现的在x86等其他架构电脑环境中运行物联网设备固件的方式。

**主要的模拟架构:**主流的物联网设备固件的架构是arm和mips。

**模拟方式:**单应用模拟和系统模拟

主流的模拟器:

  • qemu:目前使用最多的模拟器,支持用户态模拟和系统态的模拟
  • qiling:只支持单应用模拟,但是由于qiling是模拟框架,所以更加灵活

安装方式:pip3 install qiling

官方文档https://docs.qiling.io/en/latest

qiling介绍

基本流程

  1. 基本代码编写
1
2
3
4
5
6
7
8
from qiling import Qiling

if __name__ = '__main__':
argv = r'./bin/httpd'.split()
rootfs = r'./'

ql = Qiling(argv,rootfs)
ql.run()
  1. 问题定位

一般有时候会出现错误信息,不同的固件错误信息不一样,要找到错误信息进行,定位问题所在

  1. 修改代码

根据问题所在修改代码,添加一些函数等

qemu指令介绍

QEMU (Quick Emulator) 是一款强大的开源虚拟化软件,它能够模拟多种硬件环境,让用户可以在一台物理计算机上运行不同的操作系统。 QEMU 的功能主要通过命令行指令来调用,这些指令参数丰富,可以实现灵活的虚拟机配置和管理。

QEMU 主要包含两大组件:

  • qemu-system-*: 这是一个完整的虚拟机模拟器,可以模拟一个完整的计算机系统,包括处理器和各种外围设备,从而可以运行未经修改的操作系统。 例如,qemu-system-x86_64 用于模拟 x86_64 架构的计算机系统。
  • qemu-img: 这是一个磁盘镜像管理工具,用于创建、转换和修改不同格式的虚拟磁盘镜像文件。

固件模拟场景下的 QEMU 指令

在固件模拟中,我们的目标通常是让一个为特定硬件(如路由器、摄像头)编译的固 সেনারা(Firmware)在 QEMU 模拟的环境中运行起来。这通常比运行一个标准的桌面操作系统要复杂,因为固件与硬件高度耦合。

核心指令:qemu-system-

这里的 指的是固件所针对的处理器架构,常见于物联网设备的是 arm 和 mips。

常用且关键的选项:

  • -M : 指定要模拟的单板计算机(Machine)。这是固件模拟中最关键的参数之一。因为固件是为特定硬件板卡编译的,你需要告诉 QEMU 模拟一个尽可能接近真实设备的硬件环境。
    • 如何找到合适的 machine? 你可以使用 qemu-system-arm -M ? 来查看所有支持的 ARM 单板。有时需要选择一个通用板卡(如 vexpress-a9 或 versatilepb),或者社区已经为特定设备(如 raspi2 树莓派)创建了模型。
    • 示例: -M vexpress-a9
  • -kernel : 指定要加载的内核镜像文件。在固件模拟中,这通常是从固件包里解压出来的 Linux 内核文件(例如 zImage, uImage)。.
  • -initrd : 指定初始内存文件系统 (Initial RAM File System)。这通常是固件解压后的根文件系统,包含了所有必要的程序和库文件。
  • -append “console=ttyAMA0 root=/dev/ram rdinit=/sbin/init”: 向内核传递启动参数。这是另一个至关重要的步骤。
    • console=ttyAMA0: 指定内核的控制台输出设备。你需要根据你选择的 -M 参数来确定正确的串口设备名称。
    • root=/dev/ram: 告诉内核根文件系统在内存中。
    • rdinit=/sbin/init: 指定启动后在根文件系统中执行的第一个进程。
  • -nographic: 禁用图形界面,并将虚拟机的串口输出重定向到当前的终端。这对于调试和查看固件的启动日志至关重要。
  • -drive file=<disk.img>,format=raw,if=sd: 加载一个完整的磁盘镜像作为 SD 卡。有些固件不是以内核+内存文件系统的方式启动,而是直接从一个完整的磁盘镜像启动。

一个典型的固件模拟启动命令示例:

Generated bash

1
2
3
4
5
6
qemu-system-arm \
-M vexpress-a9 \
-kernel uImage \
-initrd rootfs.img.gz \
-append "root=/dev/ram rdinit=/bin/sh console=ttyAMA0" \
-nographic

Use code with caution.Bash

这个命令尝试在一个通用的 vexpress-a9 板卡上,加载 uImage 内核和 rootfs.img.gz 文件系统,并将启动后的 shell 重定向到当前终端。

附录

核心指令:qemu-system-*

这是启动和管理虚拟机的核心指令。其基本用法如下:
qemu-system-x86_64 [options] [disk_image]

其中 [options] 是一系列用于配置虚拟机资源的参数,而 [disk_image] 是虚拟机的磁盘镜像文件。

常用参数选项:

  • -m [size]: 设置虚拟机的内存大小。例如 -m 512M 表示分配 512MB 内存给虚拟机。
  • -cpu [model]: 指定模拟的 CPU 型号。可以使用 -cpu ? 来查询当前 QEMU 版本支持的 CPU 型号。
  • -hda [file]: 将指定文件作为虚拟机的第一个 IDE 硬盘。
  • -cdrom [file]: 将指定文件作为虚拟机的光驱镜像。
  • -boot [order=drives]: 设置虚拟机的启动顺序。例如,-boot order=dc 表示优先从光驱 (d) 启动,其次是硬盘 (c)。
  • -net nic: 为虚拟机创建一个网卡。
  • -net user: 使用用户模式网络,这是一种简单方便的网络配置方式,无需管理员权限。
  • -vnc :[display]: 启用 VNC 显示,允许通过 VNC 客户端远程连接到虚拟机的图形界面。
  • -nographic: 禁用图形界面,让虚拟机在当前终端以命令行方式启动。
  • -s: 启动 GDB 调试服务器。
  • -S: 在启动时暂停虚拟机,等待调试器连接。
  • -enable-kvm: 启用 KVM (Kernel-based Virtual Machine),利用硬件虚拟化技术来提升虚拟机性能。

磁盘管理工具:qemu-img

qemu-img 是一个功能强大的磁盘镜像管理工具,支持多种虚拟磁盘格式,包括 raw、qcow2、vmdk、vdi 等。

常用命令:

  • create: 创建一个新的虚拟磁盘镜像文件。
    • 用法: qemu-img create [-f fmt] filename [size]
    • 示例: qemu-img create -f qcow2 my_disk.qcow2 10G 创建一个 10GB 大小的 qcow2 格式镜像文件。 qcow2 是 QEMU 目前使用最广泛的镜像格式。
  • convert: 转换虚拟磁盘镜像的格式。
    • 用法: qemu-img convert [-f src_fmt] -O dst_fmt src_image dst_image
    • 示例: qemu-img convert -O qcow2 rhel7.img rhel7-a.qcow2 将 raw 格式的镜像转换为 qcow2 格式。
  • info: 显示虚拟磁盘镜像文件的信息。
    • 用法: qemu-img info filename
    • 示例: qemu-img info my_disk.qcow2 会显示镜像的格式、虚拟大小、实际占用磁盘空间等信息。
  • resize: 调整虚拟磁盘镜像文件的大小。
    • 用法: qemu-img resize filename [+|-]size
    • 示例: qemu-img resize my_disk.qcow2 +2G 将镜像文件增加 2GB。 需要注意的是,增加或减少镜像文件大小后,还需要在客户机操作系统内部进行相应的分区和文件系统调整才能生效。
  • snapshot: 管理虚拟机的快照。
    • 用法: qemu-img snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename
    • 选项: -l 列出快照,-c 创建快照,-d 删除快照,-a 应用快照。

支持的镜像格式简介:

  • raw: 原始的磁盘镜像格式,简单且易于移植。
  • qcow2: QEMU 的原生格式,支持写时复制、稀疏文件、加密和压缩等高级功能,是目前最常用的格式。
  • vmdk: 兼容 VMware 的镜像文件格式。
  • vdi: 兼容 VirtualBox 的镜像文件格式。

通过灵活运用 qemu-system-*qemu-img 的各种命令和参数,用户可以高效地创建、配置和管理虚拟机,满足不同的开发、测试和虚拟化需求。

系统内核编译

Buildroot

Buildroot 可以通过交叉编译生成嵌入式 Linux 系统,提供选择的库有 glibc、uClibc、musl,支持的架构包括 arm、mips、PowerPC 等主流架构。

1
curl -O https://buildroot.org/downloads/Vagrantfile; vagrant up

如何使用

实操一下

第一步安装,直接去官网下载就行,其中这个vargant来这里下载

第二步安装解压后cd configs,关于这个configs目录介绍:

configs 目录是 Buildroot 的官方模板库。你的工作流程永远是:

  1. 从 configs 目录中选择一个最合适的 _defconfig 文件作为起点。
  2. 使用 make _defconfig 命令将其应用为项目当前的 .config 文件。
  3. 使用 make menuconfig 进行个性化定制。
  4. 使用 make 进行编译。

第三步构建.config

第四步make menuconfig设定好后就可以make了

你正在 Windows Subsystem for Linux (WSL) 环境下工作。WSL 为了方便,默认会将你 Windows 系统的 PATH 环境变量自动追加到 Linux 的 PATH 中。

问题就出在这里。你的 Windows PATH 中包含了大量 Buildroot 编译脚本无法处理的条目:

  1. 包含空格的路径:这是最主要的问题。
  • /mnt/c/Program Files/Eclipse Adoptium/…
  • /mnt/c/Program Files (x86)/Windows Kits/…
  • /mnt/d/Web/Microsoft VS Code/bin
  1. 包含非英文字符(非 ASCII)的路径:这也是一个致命问题。
  • /mnt/d/虚拟机/vmware/bin/
  • /mnt/d/杂物/vivo 套件/pcsuite/

Buildroot 的检查脚本非常严格,当它在 PATH 变量中看到这些空格或特殊字符时,就会认为 PATH “不干净”,并立即报错退出。

解决方案

你有两种解决方案,一种是临时的(推荐,快速解决当前问题),一种是永久的(更彻底)。

方案一:临时指定一个“干净”的 PATH (推荐)

这是解决当前编译问题的最快、最直接的方法。我们可以在执行 make 命令时,临时为它指定一个只包含标准 Linux 路径的、干净的 PATH 变量。

请在你的 buildroot-2025.02.4/ 目录下,执行下面这行命令:

Generated bash

1
>PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin make

Use code with caution.Bash

命令解释:

  • PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:这部分会在执行 make 命令之前,临时将 PATH 环境变量设置为一个只包含最核心、最标准、最安全的 Linux 路径的集合。
  • make:紧跟在后面的 make 命令就会使用这个临时的、干净的 PATH 来执行。

这个修改只会对这一条命令生效,不会影响你终端后续的其他命令,非常安全。

执行后,Buildroot 的环境检查应该就能通过,并正式开始编译了。


进入./output/images文件夹下有rootfs.ext2(系统文件)和zImage(这个解压一些就是内核)

创建一个tmp空目录,目的挂载文件系统,命令mount rootfs.ext2 tmp

取消挂载umount tmp