使用QEMU进行IOT固件的虚拟环境搭建
最近在尝试进行固件环境模拟,如果直接购买实物太费钱了,就想了点办法搭建虚拟环境。
尝试了@foxcookie的《D-Link_DIR-830LA1命令执行漏洞(CVE-2021-45382)》中使用的FirmAE,发现在模拟其他路由器时失败率很高。据说使用QEMU手动搭建的成功率会比使用FirmAE等工具高得多,于是尝试用QEMU搭建了一个虚拟环境,重新复现了一下Dlink的CVE-2021-45382。
实验环境
ubuntu18.04
binwalk v2.1.1
路由器固件:DIR830LA1_FW100B07
1 | ➜ ~ qemu-system-mips --version |
环境安装相关指令
1 | git clone https://github.com/devttys0/binwalk.git #安装binwalk |
下载固件
ftp://ftp2.dlink.com/PRODUCTS/DIR-830L/REVA/DIR-830L_REVA_FIRMWARE_1.00.B07.ZIP
#直接丢给迅雷下载
此为D-Link DIR-830LA1路由器固件DIR830LA1_FW100B07下载链接,解压后可以看到bin文件
binwalk提取文件系统
1 | binwalk -Me DIR830LA1_FW100B07.bin |
然后binwalk会提取出bin中的文件
1 | ➜ CVE-2021-45382 D-Link ls |
进入_DIR830LA1_FW100B07.bin.extracted看一下文件,其中的squashfs-root便是文件系统
随便找一个文件file一下看看系统架构
1 | ➜ bin file busybox |
这决定了一会使用qemu的哪个架构。
MIPS决定了一会用mips,MSB或LSB决定一会用mips还是mipsel,32-bit决定是用mips还是mips32。
这里是32-bit的MSB,所以选择使用qemu-system-mips。
网络配置
网络配置我基本上是小白,看着大佬怎么配我就怎么配。
大概意思是我们需要桥接一个网卡,用于qemu和本机通信。
1 | tunctl –t top0 –u root |
使用三条指令后,ifconfig里应该会出现
这样的一个新网口。现在就可以配置QEMU虚拟机了
配置QEMU虚拟环境
下载对应系统内核
我是直接在_DIR830LA1_FW100B07.bin.extracted文件夹下执行以下两个指令
1 | curl https://people.debian.org/~aurel32/qemu/mips/vmlinux-2.6.32-5-4kc-malta |
然后在这个路径下touch一个init.sh,内容为:
1 | #!/bin/sh |
其中-nographic 代表不新起一个qemu窗口。
写好后直接sudo ./init.sh即可。
然后会跳出debian-mips的登陆界面,用户名和密码都是root
现在要把虚拟机和本机都配置到一个网段下:
1 | ifconfig eth0 192.168.10.2/24 |
此时虚拟机和本机应该是可以互相ping通的
回到本机,在_DIR830LA1_FW100B07.bin.extracted文件夹下执行
tar -czvf 1.tar squashfs-root/
将系统文件打包,然后用scp传输到虚拟机中
scp 1.tar root@192.168.10.2:/root/
转到虚拟机,可以看到1.tar已经在目录下
解压
tar –zxvf 1.tar
然后将系统文件进行挂载
mount -o bind /dev ./squashfs-root/dev
mount -t proc /proc ./squashfs-root/proc/
然后就可以直接chroot进入路由器系统了
chroot ./squashfs-root/ sh
启动路由器服务
从这里开始每个路由器都不太一样了,一般的思路是去/etc/下找init相关文件,看哪个文件是启动文件。
这里我测试出Dlink的启动程序在/etc/init.d/rcS
使用ssh连接虚拟机
使用chroot进入路由器系统,然后直接运行etc/init.d/rcS
执行后就会一直跳already enabled!
此时用主机访问192.168.10.2
路由器虚拟环境搭建成功
复现cve-2021-45382
在这个网页一直下一步,全部使用默认设置,直到配置完成。
然后等它倒数完就会直接进入登陆后的界面。
对该页面进行抓包,直接用转发到repeater构造POC。
cve的具体原理在此就不过多赘述了,毕竟这只是一个环境搭建的记录。
1 | POST /ddns_check.ccp HTTP/1.1 |
然后直接访问1.html
可以看到“ls /”已经被执行