环境搭建:QEMU系统模式与用户模式安装、交叉编译工具链配置

说实话,环境搭建这步看着简单,但坑是真不少。我见过太多人卡在这一步,折腾两三天还没跑起来第一个程序。咱们今天就把这事彻底搞定。

先看整体架构,心里有个谱:

异架构Fuzz环境搭建全景图 宿主机(x86_64 / Ubuntu 22.04) 交叉编译工具链:gcc-arm-linux-gnueabihf / aarch64-linux-gnu QEMU 用户模式 qemu-arm / qemu-aarch64 直接运行单文件,适合Fuzz QEMU 系统模式 qemu-system-arm / qemu-system-aarch64 模拟完整系统,适合Pwn ARM 32位 ELF 文件 ARM 64位 完整系统镜像

2.1 QEMU 安装:两种模式,两种用法

QEMU 这东西,说白了就是个硬件模拟器。它有两种工作模式,咱们都得装。

核心区别一句话:用户模式只管跑单个程序,系统模式模拟一整套设备。

用户模式(User Mode)

这种模式最轻量。你拿一个 ARM 编译好的 ELF 文件,直接就能在 x86 机器上跑。不需要启动内核,不需要挂载文件系统。我个人习惯用这个模式做 Fuzz 测试——快,省事。

# 安装 ARM 32位和64位用户模式支持
sudo apt update
sudo apt install qemu-user qemu-user-static

# 验证安装
qemu-arm --version
qemu-aarch64 --version

小技巧:装完以后试试 qemu-arm /bin/ls,如果能列出目录,说明环境通了。我第一次装完就卡在这步——忘了装 binfmt-support,结果系统不认识 ARM 格式。

系统模式(System Mode)

做 Pwn 漏洞利用的时候,我建议用系统模式。为什么?因为很多漏洞需要完整的操作系统环境才能触发——比如内核交互、设备驱动、网络协议栈。用户模式模拟不了这些。

# 安装系统模式支持
sudo apt install qemu-system-arm qemu-system-aarch64

# 验证
qemu-system-arm --version
qemu-system-aarch64 --version

注意:系统模式安装包比较大(约 200MB),因为包含了各种板级支持包。如果你磁盘空间紧张,可以只装需要的架构:sudo apt install qemu-system-arm 就够了。

2.2 交叉编译工具链配置

交叉编译,说白了就是在 x86 机器上编译出 ARM 能跑的代码。这里我踩过不少坑,咱们一步步来。

安装 gcc-arm-linux-gnueabihf

这是 ARM 32 位硬浮点工具链。为什么选 gnueabihf 而不是 gnueabi?因为现在大部分 ARM 设备都支持硬件浮点,性能更好。

# 安装 ARM 32位工具链
sudo apt install gcc-arm-linux-gnueabihf

# 安装 ARM 64位工具链
sudo apt install gcc-aarch64-linux-gnu

# 验证
arm-linux-gnueabihf-gcc --version
aarch64-linux-gnu-gcc --version

验证小实验:写个 hello.c,交叉编译试试:

# hello.c
#include <stdio.h>
int main() {
    printf("Hello from ARM!\n");
    return 0;
}

# 编译
arm-linux-gnueabihf-gcc -o hello_arm hello.c

# 查看文件类型
file hello_arm
# 输出:ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)

工具链对比表

工具链名称 目标架构 浮点支持 适用场景
gcc-arm-linux-gnueabihf ARM 32位 硬件浮点(VFP) 嵌入式设备、IoT Fuzz
gcc-arm-linux-gnueabi ARM 32位 软件浮点 老旧设备兼容
gcc-aarch64-linux-gnu ARM 64位 硬件浮点(NEON) 手机、服务器 Pwn
gcc-riscv64-linux-gnu RISC-V 64位 硬件浮点 新兴架构 Fuzz

我的经验:做 Fuzz 测试时,我一般用 gnueabihf。但如果你遇到段错误或者浮点异常,试试换成 gnueabi——有些老设备确实不支持硬浮点。

2.3 目标系统镜像准备

系统模式需要完整的操作系统镜像。这里我推荐两种方式:

方式一:使用预构建镜像(推荐新手)

从官方仓库下载现成的 Debian/Ubuntu ARM 镜像,省时省力。

# 下载 ARM 32位 Debian 镜像
wget https://people.debian.org/~aurel32/qemu/armhf/debian_wheezy_armhf_standard.qcow2
wget https://people.debian.org/~aurel32/qemu/armhf/initrd.img-3.2.0-4-vexpress
wget https://people.debian.org/~aurel32/qemu/armhf/vmlinuz-3.2.0-4-vexpress

# 启动
qemu-system-arm -M vexpress-a9 \
  -kernel vmlinuz-3.2.0-4-vexpress \
  -initrd initrd.img-3.2.0-4-vexpress \
  -drive file=debian_wheezy_armhf_standard.qcow2,if=sd \
  -append "root=/dev/mmcblk0p2 console=ttyAMA0" \
  -nographic

我曾经踩过的坑:下载的镜像版本和内核版本不匹配,启动时直接 kernel panic。解决办法:统一从同一个源下载,别混搭。另外,-M 参数指定机器类型,vexpress-a9 是最通用的,别乱改。

方式二:自己构建镜像(推荐进阶)

用 debootstrap 从零构建,灵活度高,可以定制软件包。

# 安装 debootstrap
sudo apt install debootstrap

# 构建 ARM 32位根文件系统
sudo debootstrap --arch=armhf --foreign bullseye \
  /mnt/arm-rootfs http://deb.debian.org/debian

# 复制 qemu-arm-static 到根文件系统
sudo cp /usr/bin/qemu-arm-static /mnt/arm-rootfs/usr/bin/

# 进入 chroot 环境完成安装
sudo chroot /mnt/arm-rootfs /debootstrap/debootstrap --second-stage

为什么需要 qemu-arm-static?debootstrap 在宿主机上运行,但安装脚本是 ARM 格式的。qemu-arm-static 充当解释器,让宿主机能执行 ARM 指令。没有这步,debootstrap 会报 "Exec format error"。

2.4 环境验证清单

装完别急着走,跑一遍这个清单,确保万无一失:

  1. 用户模式验证:qemu-arm /bin/true 返回 0
  2. 系统模式验证:能启动到登录提示符
  3. 交叉编译验证:编译的 ARM 程序能在 QEMU 用户模式下运行
  4. 网络连通性:系统模式下 ping 8.8.8.8 通
  5. SSH 连接:能从宿主机 SSH 进 QEMU 虚拟机

我的习惯:每次搭建新环境,我都会写一个自动化脚本,把这 5 步验证跑一遍。省得后面 Fuzz 跑了一天才发现环境有问题,白费功夫。