QEMU在嵌入式逆向分析中的应用
字数 1212 2025-08-22 12:22:36

QEMU在嵌入式逆向分析中的应用

一、用QEMU模拟嵌入式调试环境

1. 安装ARM交叉编译工具链

sudo apt-get install gcc-arm-linux-gnueabi
# 或特定版本
sudo apt-get install gcc-4.9-arm-linux-gnueabi
sudo apt-get install gcc-4.9-arm-linux-gnueabi-base
# 建立软链接
sudo ln -s /usr/bin/arm-linux-gnueabi-gcc-4.9 /usr/bin/arm-linux-gnueabi-gcc

2. 编译Linux内核

生成vexpress开发板config文件:

make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16 vexpress_defconfig

配置内核:

make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16 menuconfig

重要:取消选中System Type > Enable the L2x0 outer cache controller,否则QEMU无法启动

编译内核:

make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16 zImage -j2

生成的内核镜像位于./out_vexpress_3_16/arch/arm/boot/zImage

3. 下载和安装QEMU模拟器

git clone git://git.qemu-project.org/qemu.git
cd qemu
git checkout remotes/origin/stable-2.4 -b stable-2.4

安装依赖:

sudo apt-get install zlib1g-dev libglib2.0-0 libglib2.0-dev libtool libsdl1.2-dev autoconf

配置和编译:

mkdir build
cd build
../qemu/configure --target-list=arm-softmmu --audio-drv-list=
make
make install

查看支持的开发板:

qemu-system-arm -M help

4. 测试QEMU和内核

qemu-system-arm \
  -M vexpress-a9 \
  -m 512M \
  -kernel /path/to/zImage \
  -nographic \
  -append "console=ttyAMA0"

参数说明:

  • -M vexpress-a9:模拟vexpress-a9单板
  • -m 512M:物理内存512M
  • -kernel:内核镜像路径
  • -nographic:不使用图形界面
  • -append:内核启动参数,console=参数值可从生成的.config文件中CONFIG_CONSOLE宏找到

5. 制作根文件系统

(1) 下载、编译和安装BusyBox

配置BusyBox:

make menuconfig

配置选项:

Busybox Settings --->
  Build Options
    [*] Build BusyBox as a static binary (no shared libs)
    (arm-linux-gnueabi-) Cross Compiler prefix

编译安装:

make
make install

(2) 形成根目录结构

使用脚本mkrootfs.sh

#!/bin/bash
sudo rm -rf rootfs
sudo rm -rf tmpfs
sudo rm -f a9rootfs.ext3
sudo mkdir rootfs
sudo cp busybox/_install/* rootfs/ -raf
sudo mkdir -p rootfs/proc/
sudo mkdir -p rootfs/sys/
sudo mkdir -p rootfs/tmp/
sudo mkdir -p rootfs/root/
sudo mkdir -p rootfs/var/
sudo mkdir -p rootfs/mnt/
sudo cp etc rootfs/ -arf
sudo cp -arf /usr/arm-linux-gnueabi/lib rootfs/
sudo rm rootfs/lib/*.a
sudo arm-linux-gnueabi-strip rootfs/lib/*
sudo mkdir -p rootfs/dev/
sudo mknod rootfs/dev/tty1 c 4 1
sudo mknod rootfs/dev/tty2 c 4 2
sudo mknod rootfs/dev/tty3 c 4 3
sudo mknod rootfs/dev/tty4 c 4 4
sudo mknod rootfs/dev/console c 5 1
sudo mknod rootfs/dev/null c 1 3
sudo dd if=/dev/zero of=a9rootfs.ext3 bs=1M count=32
sudo mkfs.ext3 a9rootfs.ext3
sudo mkdir -p tmpfs
sudo mount -t ext3 a9rootfs.ext3 tmpfs/ -o loop
sudo cp -r rootfs/* tmpfs/
sudo umount tmpfs

(3) 系统启动运行

无图形界面:

qemu-system-arm \
  -M vexpress-a9 \
  -m 512M \
  -kernel /path/to/zImage \
  -nographic \
  -append "root=/dev/mmcblk0 console=ttyAMA0" \
  -sd /path/to/a9rootfs.ext3

带图形界面:

qemu-system-arm \
  -M vexpress-a9 \
  -serial stdio \
  -m 512M \
  -kernel /path/to/zImage \
  -append "root=/dev/mmcblk0 console=ttyAMA0 console=tty0" \
  -sd /path/to/a9rootfs.ext3

6. 下载、编译u-boot代码

下载u-boot:

wget http://ftp.denx.de/pub/u-boot/

配置编译:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_ca9x4_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

测试:

qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M

7. 实现用u-boot引导Linux内核

(1) 启动QEMU的网络支持

安装工具:

sudo apt-get install uml-utilities bridge-utils

创建/etc/qemu-ifdown

#!/bin/sh
echo sudo brctl delif br0 $1
sudo brctl delif br0 $1
echo sudo tunctl -d $1
sudo tunctl -d $1
echo brctl show
brctl show

创建/etc/qemu-ifup

#!/bin/sh
echo sudo tunctl -u $(id -un) -t $1
sudo tunctl -u $(id -un) -t $1
echo sudo ifconfig $1 0.0.0.0 promisc up
sudo ifconfig $1 0.0.0.0 promisc up
echo sudo brctl addif br0 $1
sudo brctl addif br0 $1
echo brctl show
brctl show
sudo ifconfig br0 192.168.11.20

(2) 配置u-boot

修改include/configs/vexpress_common.h

/* netmask */
#define CONFIG_IPADDR 192.168.11.5
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 192.168.11.20

/* 修改启动命令 */
#define CONFIG_BOOTCOMMAND "tftp 0x60008000 uImage; setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0'; bootm 0x60008000"

重新编译:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j2

(3) 配置Linux Kernel

编译uImage格式内核:

make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16 LOADADDR=0x60008000 uImage -j2

启动:

qemu-system-arm -M vexpress-a9 \
  -kernel /path/to/u-boot \
  -nographic \
  -m 512M \
  -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
  -sd /path/to/a9rootfs.ext3

8. 用NFS挂载文件系统

(1) 配置u-boot环境变量

setenv bootargs 'root=/dev/nfs rw nfsroot=192.168.11.20:/nfs_rootfs/rootfs init=/linuxrc console=ttyAMA0 ip=192.168.11.5'

(2) 配置内核支持NFS

配置内核:

make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16/ menuconfig

配置选项:

File systems --->
  [*] Network File Systems
    NFS client support
    <*> NFS client support for NFS version 3
    [*] NFS client support for the NFSv3 ACL protocol extension
    [*] Root file system on NFS

重新编译内核:

make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16 LOADADDR=0x60003000 uImage -j2

二、用QEMU辅助动态调试

1. 调试RAW格式ARM程序

示例汇编程序add.S

.text
start:
    mov r0, #5
    mov r1, #4
    add r2, r1, r0
stop:
    b stop

编译链接:

arm-none-eabi-as -o add.o add.s
arm-none-eabi-ld -Ttext=0x0 -o add.elf add.o
arm-none-eabi-objcopy -O binary add.elf add.bin

创建flash镜像并运行:

dd if=/dev/zero of=flash.bin bs=4096 count=4096
dd if=add.bin of=flash.bin bs=4096 conv=notrunc
qemu-system-arm -M connex -pflash flash.bin -nographic -serial /dev/null

查看寄存器状态:

(qemu) info registers

启动GDB调试:

qemu-system-arm -S -M connex -drive file=flash.bin,if=pflash,format=raw -nographic -serial /dev/null
# 在另一个终端
gdb
(gdb) target remote localhost:1234

2. 调试ELF格式ARM程序

(1) 编译示例程序

wget http://ftp.gnu.org/gnu/hello/hello-2.6.tar.gz
tar xzf hello-2.6.tar.gz
cd hello-2.6
./configure --host=arm-none-linux-gnueabi
make

(2) 添加依赖库到文件系统

查看依赖库:

arm-none-linux-gnueabi-readelf hello-2.6/src/hello -a |grep lib

拷贝所需库到busybox文件系统:

cp /path/to/arm-none-linux-gnueabi/libc/lib/ld-linux.so.3 lib/
cp /path/to/arm-none-linux-gnueabi/libc/lib/libgcc_s.so.1 lib/
cp /path/to/arm-none-linux-gnueabi/libc/lib/libc.so.6 lib/
cp /path/to/arm-none-linux-gnueabi/libc/usr/bin/gdbserver usr/bin/
cp hello-2.6/src/hello usr/bin/

(3) 制作initramfs

创建rcS启动脚本:

#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
ifconfig lo up
ifconfig eth0 10.0.2.15 netmask 255.255.255.0
route add default gw 10.0.2.1

制作文件系统:

mkdir -p proc sys dev etc etc/init.d
cp rcS etc/init.d/
chmod +x etc/init.d/rcS
find . | cpio -o --format=newc | gzip > ../rootfs.img.gz

(4) 启动调试

启动QEMU:

qemu-system-arm -M versatilepb -m 128M -kernel /path/to/zImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=/sbin/init" -redir tcp:1234::1234

在目标系统中启动gdbserver:

gdbserver --multi 10.0.2.15:1234

在主机使用GDB连接:

ddd --debugger arm-none-linux-gnueabi-gdb
(gdb) set solib-absolute-prefix nonexistantpath
(gdb) set solib-search-path /path/to/arm-none-linux-gnueabi/libc/lib/
(gdb) file ./hello-2.6/src/hello
(gdb) target extended-remote localhost:1234
(gdb) set remote exec-file /usr/bin/hello
(gdb) break main
(gdb) run

3. 使用QEMU+GDB调试内核

(1) 编译调试版内核

配置内核:

make menuconfig

确保开启:

Kernel hacking
  Kernel debugging
    Compile-time checks and compiler options
      [*] Compile the kernel with debug info
      [*] Provide GDB scripts for kernel debugging

(2) 构建initramfs根文件系统

编译静态版BusyBox:

make menuconfig
# 选择 Build static binary (no shared libs)
make -j 20
make install

创建initramfs结构:

mkdir initramfs
cd initramfs
cp ../_install/* -rf ./
mkdir dev proc sys
sudo cp -a /dev/{null, console, tty, tty1, tty2, tty3, tty4} dev/
rm linuxrc

创建init脚本:

#!/bin/busybox sh
mount -t proc none /proc
mount -t sysfs none /sys
exec /sbin/init

打包initramfs:

find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz

(3) 调试内核

启动内核:

qemu-system-x86_64 -s -kernel /path/to/vmlinux -initrd initramfs.cpio.gz -nographic -append "console=ttyS0"

使用GDB连接:

gdb vmlinux
(gdb) target remote localhost:1234

使用内核GDB辅助脚本:

(gdb) apropos lx
(gdb) lx-cmdline
(gdb) break cmdline_proc_show
QEMU在嵌入式逆向分析中的应用 一、用QEMU模拟嵌入式调试环境 1. 安装ARM交叉编译工具链 2. 编译Linux内核 生成vexpress开发板config文件: 配置内核: 重要 :取消选中 System Type > Enable the L2x0 outer cache controller ,否则QEMU无法启动 编译内核: 生成的内核镜像位于 ./out_vexpress_3_16/arch/arm/boot/zImage 3. 下载和安装QEMU模拟器 安装依赖: 配置和编译: 查看支持的开发板: 4. 测试QEMU和内核 参数说明: -M vexpress-a9 :模拟vexpress-a9单板 -m 512M :物理内存512M -kernel :内核镜像路径 -nographic :不使用图形界面 -append :内核启动参数, console= 参数值可从生成的.config文件中 CONFIG_CONSOLE 宏找到 5. 制作根文件系统 (1) 下载、编译和安装BusyBox 配置BusyBox: 配置选项: 编译安装: (2) 形成根目录结构 使用脚本 mkrootfs.sh : (3) 系统启动运行 无图形界面: 带图形界面: 6. 下载、编译u-boot代码 下载u-boot: 配置编译: 测试: 7. 实现用u-boot引导Linux内核 (1) 启动QEMU的网络支持 安装工具: 创建 /etc/qemu-ifdown : 创建 /etc/qemu-ifup : (2) 配置u-boot 修改 include/configs/vexpress_common.h : 重新编译: (3) 配置Linux Kernel 编译uImage格式内核: 启动: 8. 用NFS挂载文件系统 (1) 配置u-boot环境变量 (2) 配置内核支持NFS 配置内核: 配置选项: 重新编译内核: 二、用QEMU辅助动态调试 1. 调试RAW格式ARM程序 示例汇编程序 add.S : 编译链接: 创建flash镜像并运行: 查看寄存器状态: 启动GDB调试: 2. 调试ELF格式ARM程序 (1) 编译示例程序 (2) 添加依赖库到文件系统 查看依赖库: 拷贝所需库到busybox文件系统: (3) 制作initramfs 创建 rcS 启动脚本: 制作文件系统: (4) 启动调试 启动QEMU: 在目标系统中启动gdbserver: 在主机使用GDB连接: 3. 使用QEMU+GDB调试内核 (1) 编译调试版内核 配置内核: 确保开启: (2) 构建initramfs根文件系统 编译静态版BusyBox: 创建initramfs结构: 创建init脚本: 打包initramfs: (3) 调试内核 启动内核: 使用GDB连接: 使用内核GDB辅助脚本: