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