固件模拟浅谈

概述

在研究固件时,把固件跑起来是不必可少的一步,通常有两种方法,一种是用qemu等工具来搭建模拟环境;另一种就是买成品。固件模拟比起买成品显然有更大的优势:除了节约财力外,更重要的是模拟环境通常直接拥有shell,方便调试,而成品一般不会给shell,只能尝试通过NDAY来拿shell。因此,学会固件模拟,是iot安全研究不可绕过的重点。

固件模拟的三种方法

现成自动化工具:FirmAE等

可参考:FirmAE 模拟固件-CSDN博客

FirmAE具有一键式模拟固件的能力,提供shell、gdb调试甚至fuzz功能,但是成功率有限,而且耗时较长:

qemu用户模拟

演示固件下载:AX12 V1.0 升级软件_腾达Tenda官方网站

qemu是最常用的固件模拟工具之一,有两种模拟方式:用户模拟和系统模拟。

用户模拟通常是对某个二进制程序进行模拟,由于只是对单个程序进行模拟,该程序的很多前置服务都没启动,在模拟中会出现很多报错。

在用户模拟时,先使用chroot命令来指定固件的文件系统目录为根目录(这样/bin才会找到固件的文件系统的bin而不是本机的bin),然后使用命令./qemu-xxx-static 来启动对应二进制程序,xxx代表指令集,如:

sudo chroot ./ ./qemu-mips-static ./usr/sbin/httpd

可以看到,httpd已经启动:

访问127.0.0.1,抓包,可以看到web页面:

但是在后续请求中会报错,页面丢失:

报错:

原因就是之前提到的,必要的前置服务没有启动。有时候用户模拟也可以满足漏洞挖掘/复现的需求,前置服务没有启动的问题,可以通过启动项和逆向来分析,通过手动执行启动项的命令或者patch该二进制程序的逻辑来解决报错。

可以参考:

手把手带你分析mips架构下固件分析与漏洞挖掘 – IOTsec-Zone

路由器通用0day漏洞挖掘及RCE思路-先知社区

qemu系统模拟

概述

qemu系统模拟是把整个操作系统给模拟出来(可以结合kvm虚拟化模块来提升效率,注意虚拟化和模拟的区别),然后直接在这个模拟的操作系统里面跑固件,这种方法成功率最高,也基本能还原固件的所有功能。

一般有三种方式:

1、直接使用固件自带的内核和文件系统

很多时候固件的压缩包会自带内核,qemu可以直接指定该内核和固件的文件系统来模拟,这种方法最省事,但是成功率相对比较低

2、网上下载对应内核,使用固件的文件系统

这种方法不使用固件自带的内核,而是从网上下载对应版本,但是文件系统还是用的固件的,成功率比第一种高一些。

3、网上下载对应内核和默认文件系统,跑起来后再通过scp等方法把固件文件系统传到模拟系统上运行。

这种方法成功率最高,相比之下也最麻烦。

此处演示第三种方法。

演示

先判断固件的指令集和操作系统型号:

从openwrt下载对应版本:

Index of /releases/19.07.1/targets/malta/be/

直接下载vmlinux-initramfs.elf文件,该文件包含了简单的文件系统,可以直接跑起来。

首先是配置网卡。

找到自己用的物理网卡名称,我的是ens33,之前已经创建并加入到vqfx-br网桥中,所以此处直接新增一个tap0,加入到该网桥即可:

# 1. 创建tap0虚拟网卡,指定当前用户权限
sudo tunctl -t tap0 -u $(whoami)

# 2. 关闭tap0的默认IP(后续通过桥接获取网段)
sudo ifconfig tap0 0.0.0.0 up

# 3. 将tap0添加到vqfx-br桥接(关键:让虚拟机通过桥接接入192.168.x.x)
sudo brctl addif vqfx-br tap0

# 4. 确认桥接状态(应看到vqfx-br包含tap0和原有接口)
sudo brctl show vqfx-br

然后使用命令启动模拟系统:

qemu-system-mips -M malta   -kernel openwrt-19.07.1-malta-be-vmlinux-initramfs.elf   -m 512   -nographic   -net nic,model=pcnet   -net tap,ifname=tap0,script=no,downscript=no   -append "console=ttyS0"

启动后在模拟系统的终端执行:

# 配置静态IP(与主机vqfx-br同网段,如192.168.x.200)
ifconfig eth0 192.168.x.200 netmask 255.255.255.0 up

# 添加默认网关(指向主机vqfx-br的IP,确保路由互通)
route add default gw 192.168.x.149 eth0

测试,能ping通即可。

接下来关闭防火墙,否则ssh连接可能被ban:

/etc/init.d/firewall stop

启动ssh服务,openwrt中通常是dropbear程序负责:

/etc/init.d/dropbear start

主机ssh成功登录:

上传固件:

tar -czvf ugw_firmware.tar.gz squashfs-root/
scp ugw_firmware.tar.gz root@192.168.x.x:/tmp/
连不上执行:ssh-keygen -f "/home/yourusername/.ssh/known_hosts" -R "192.168.x.x"

模拟系统中解压并运行:

cd /tmp
tar -xzvf ugw_firmware.tar.gz

然后就可以运行固件了

先挂载:

mount --bind /proc proc
mount --bind /dev dev
mount --bind /sys sys

启动httpd

cd squashfs-root
chroot . sh
./sbin/procd &
./sbin/ubusd &
/usr/sbin/httpd

此时会报错,说端口80不可用:

这是因为openwrt自带的web服务uhttpd默认启动,把端口占了,所以需要ctrl c跳出去,关掉自带的uhttpd服务(动作要迅速)。

关掉后即可启动:

但是还是会报原来用户模拟时候的错误,原因依然是前置服务没启动,重新启动前置服务:

cd squashfs-root
chroot . sh
./sbin/procd &
./sbin/ubusd &
/usr/sbin/httpd

发现还是报错,ps aux|grep ubusd发现拥有多个ubusd,怀疑是因为固件的文件系统会和openwrt的文件系统产生冲突,启动httpd服务之后连页面都进不去了。

尝试使用非openwrt系统来搭建环境,这里参考了H3C系列部分路由器(CVE-2025-2725~2732)漏洞复现 – IOTsec-Zone

使用的环境是:Index of /~aurel32/qemu/mipselvmlinux-3.2.0-4-4kc-maltadebian_squeeze_mipsel_standard.qcow2

使用的固件是H3C NX15:H3C NX15V100R013 软件版本及说明书-新华三集团-H3C

命令如下:

ubuntu:
sudo tunctl -t tap0
sudo ifconfig tap0 192.168.0.1/24 up
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward > /dev/null
sudo iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE
sudo iptables -A FORWARD -i tap0 -j ACCEPT
sudo iptables -A FORWARD -o tap0 -j ACCEPT
qemu-system-mipsel \
    -M malta\
    -kernel vmlinux-3.2.0-4-4kc-malta \
    -hda debian_squeeze_mipsel_standard.qcow2 \
    -append "root=/dev/sda1 console=tty0" \
    -net nic -net tap,ifname=tap0,script=no,downscript=no \
    -nographic
    
qemu:
ip addr add 192.168.0.2/24 dev eth0
ip link set eth0 up
ip route add default via 192.168.0.1

ubuntu:
tar -czvf ugw_firmware.tar.gz squashfs-root/
scp ugw_firmware.tar.gz root@192.168.x.x:/tmp/

qemu:
tar -xzvf ugw_firmware.tar.gz
cd /tmp/squashfs-root/
mount --bind /proc proc
mount --bind /dev dev
mount --bind /sys sys

cd squashfs-root
chroot . sh
./sbin/procd &
./sbin/ubusd &
./usr/sbin/lighttpd -D -f ./etc/lighttpd/lighttpd.conf

可能在启动ubusd的时候会出现如下报错:

这是由于缺少了/var/run这一目录导致的,ubusd会在这目录下创建usock,所以手动创建一个即可启动ubusd:

mkdir /var
cd /var
mkdir run

启动lighttpd时候可能会有如下错误:

同样也是少了该文件,手动创建即可启动:

由于缺少result字段,所以显示异常,但是各个接口的可以正常访问,成功模拟:

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇