首页
社区
课程
招聘
[原创] 小米路由器固件仿真模拟方案
发表于: 2024-6-4 21:12 29178

[原创] 小米路由器固件仿真模拟方案

2024-6-4 21:12
29178

前言

书接上回,由于我们学校实验室里正好用的是小米AX9000这款路由器,因此当时我就选了这款设备挖,也就没有对固件仿真了。既有女朋友又努力上进的ZIKH26师傅与我这个摆烂人不同,在复现我这个洞的时候,想要研究一下小米路由器的仿真模拟。正好最近我也没啥事,于是也就一起看了看。

恰巧前几天也有师傅私信我关于小米路由器该如何仿真的问题,并且网上目前似乎还没有师傅分析过小米固件的仿真,因此我就写了此文放了出来(所以,我说FirmAE是对某些固件特制的学术玩具会不会被打,逃)。

除了一些特殊的设备,其实对于固件的仿真模拟,总结成一句话就是:IoT设备的仿真过程就是不断地改报错,只要与外设硬件无关,都是小问题。也就是说,主要是要有耐心。

这里依然以小米路由器AX9000为例,小米其他型号的路由器也都可以用如下的方案仿真。在本文的最后,会用我们仿真模拟的路由器环境验证CVE-2023-26315这个漏洞。

环境配置

小米路由器AX9000相对其他一些型号来说,仿真稍微复杂一些,因为小米AX9000的固件是AArch64el架构的,而网上似乎还没有公开的AArch64的内核与文件系统。因此,我们需要自己装一个AArch64的虚拟机,并从中extract提取出内核与磁盘镜像。可参考这篇文章中的步骤完成。

我本人比较懒,装AArch64虚拟机很耗时间和内存,所以这部分是ZIKH26师傅提取的内核与磁盘镜像,在此表示崇高的敬意。


【给看雪的家人们送个福利】 提取好的AArch64el架构的vmlinuzinitrd.img可点击这里下载(账户root/zikh,密码都是root,ssh需要使用普通用户再su),以及若有师傅想自己提取的话,详细步骤可见ZIKH26师傅的博客。这里与我下文有些不同的是,他文中用的是NAT完成QEMU与宿主机通信,我习惯于用桥接的方式。


关于网络环境配置的问题,这里就不再多说了。只简单提一句,qemu-system-aarch64启动后,可以用ip addr看到enp0s1网卡是DOWN的状态,且没有分配IP地址。

因此,我们需要手动分配一个IP地址(与网桥br0处于同一网段即可,qemuenp0s1接口与宿主机的eth0接口通过虚拟网桥br0转发数据),然后再将enp0s1网卡给UP启用即可,命令如下:

1
2
ip add add 192.168.192.132/24 dev enp0s1
ip link set enp0s1 up

完成后,enp0s1网卡的状态应该正常了,再检测下qemu虚拟机与宿主机能否互相正常通信:

下面,就正式开始仿真模拟了。

起手式

将固件解压后,首先将文件系统用scp传入qemu虚拟机,然后就是最经典的三行起手式:

1
2
3
mount --bind /proc proc
mount --bind /dev dev
chroot . /bin/sh

好吧,这一步我竟然还截了一张图:

根据openwrt的内核初始化流程,按理说应该先启动/etc/preinit,其中会执行/sbin/init进行初始化,但是在这套固件仿真的时候,这样会导致qemu重启,所以我们首先先执行/sbin/init中最重要的/sbin/procd &,启动进程管理器即可。

启动httpd服务

下面就该启动httpd服务了,简单检索一下,发现有uhttpdmihttpdsysapihttpd。进一步查看一下配置文件(如/etc/sysapihttpd/sysapihttpd.conf),发现sysapihttpd其实就是nginx,监听了80端口,有了nginx自然就不需要再启动uhttpd了。而mihttpd中监听了8198端口,定义了一些文件上传下载的API,可以暂时先不启。

所以,只需要启动sysapihttpd,执行/etc/init.d/sysapihttpd start即可:

首先,报错缺失/var/lock/procd_sysapihttpd.lock这个文件,这个创建一下对应的目录和文件就行了。接着,会报错Failed to connect to ubus,很显然这里是用到了ubus总线通信,我们需要启动/sbin/ubusd &。但是,接下来又继续报错usock: No such file or directory,但是并没有给出缺失哪个文件,因此我们需要将ubusd拖进IDA定位一下报错点。

很容易定位到sub_20B0函数,我们执行的是ubusd,而不是它的软链接tbusd,因此v8会是路径/var/run/ubus.sock,接着其作为参数传入usock函数中,当usock函数的返回值错误时,就会走到perror("usock")报错。

显然我们缺少/var/run/ubus.sock这个文件,创建后ubusd即可正常启动,接着sysapihttpd服务也启动成功(这里缺失/dev/nvram芯片可以先不用管,因为后续没有用到相关操作,暂时不用hook):

到这里,检查一下进程里相关程序都已经挂起,且netstat查看web端口也正常对外开放:

崩溃&排查

虽然这一切看上去没有任何问题,nmap也能扫到端口,但是我们访问IP就会报错,显示服务器没有传回任何数据。

此外,查看进程,可以发现sysapihttpd的主进程进程号没变,但是子进程的进程号却已经改变,这就说明当我们访问IP的时候,server崩溃了,所以子进程crash了,主进程作为守护进程又开了个新的子进程。

因此,我们可以用strace跟踪一下子进程的进程号,判断出现了什么问题导致sysapihttpdcrash的。这里直接在外面的qemu文件系统中用apt或者dpkg安装一下strace_arm64deb包,然后再ssh开个窗口跟踪进程即可。先attach上去卡住,然后访问IP后,strace跟踪的结果如下:

可以看到最后是发生了段错误导致了crash的。我们需要解决的是上面的三个报错,前两个错误都是由于缺少/etc/TZ文件所导致的,这是一个和时区有关的配置文件,echo "WAUST-8WAUDT" > /etc/TZ创建一下即可。

对于后面getsockopt的报错,我们可以将/usr/sbin/sysapihttpd拖进IDA,定位一下getsockopt参数一致(主要关注第三个参数是0x50)的位置,可以找到sub_1EDACsub_27570两个函数。至于是哪个函数中getsockopt调用的位置才是关键,结合strace上下文,根据上面调用了accept4系统调用,可以确定sub_27570函数中getsockopt的位置才是调用点。

根据上面的代码,结合strace后面输出的log报错信息,可以得知这里是由于getsockopt发生了错误,从而重定向到了0.0.0.1:65535,导致了后续的崩溃。因此,最简单粗暴的办法就是绕过这个if分支,不执行其中的内容,即将CBZpatch成相反的CBNZ即可:

patch后的sysapihttpd程序按照如下的步骤更新至固件的文件系统中,并重启httpd服务:

然后,访问IP并重定向至/init.html,可以看到路由器初始化配置页面终于是成功出现了:


[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 2024-6-6 14:00 被winmt编辑 ,原因: 修改格式
收藏
免费 15
支持
分享
最新回复 (7)
雪    币: 245
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
在绕过密码设置那部分,如果你手贱一点看到了uci show,然后练就一双火眼金睛,在一闪而过的大量数据中看到值长得像SHA1的account.common.admin,这部分就能直接秒(
但不得不说,论优雅还得是winmt师傅的源码分析 :)
2024-6-4 21:32
0
雪    币: 145
活跃值: (8764)
能力值: ( LV13,RANK:438 )
在线值:
发帖
回帖
粉丝
3
Unauth401 在绕过密码设置那部分,如果你手贱一点看到了uci show,然后练就一双火眼金睛,在一闪而过的大量数据中看到值长得像SHA1的account.common.admin,这部分就能直接秒( 但不得不说 ...
还得是田师傅,学到一手(已经被学弟秒了呜呜呜
2024-6-4 21:39
0
雪    币: 933
活跃值: (1816)
能力值: ( LV8,RANK:125 )
在线值:
发帖
回帖
粉丝
4
arm64配置好的环境下载链接:ba1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1M7X3W2$3k6g2)9J5k6h3N6G2L8$3N6D9k6g2)9J5k6h3y4G2L8g2)9J5c8X3k6A6L8r3g2Q4x3V1k6V1i4K6u0r3x3f1k6U0j5V1y4C8k6V1N6#2d9r3I4$3L8$3S2s2L8s2A6m8i4K6u0V1d9q4u0d9P5f1@1^5K9i4A6I4K9p5S2m8e0p5g2Q4x3V1k6$3K9h3g2%4i4K6y4r3N6i4y4H3i4K6y4p5M7$3S2S2M7X3W2F1k6#2)9J5y4X3&6T1M7%4m8Q4x3@1u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7i4K6t1$3L8X3u0K6M7q4)9K6b7W2)9J5y4X3&6T1M7%4m8Q4x3@1u0Q4c8f1k6Q4b7V1y4Q4z5o6S2J5L8$3!0@1i4K6u0r3M7X3!0G2N6q4!0q4c8W2!0n7b7#2)9^5z5b7`.`.
花园宝宝级教程:483K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6*7K9h3E0Z5x3U0k6Q4x3X3g2Y4K9i4c8Z5N6h3u0Q4x3X3g2A6L8#2)9J5c8Y4m8G2M7%4c8K6i4K6u0r3x3$3b7&6y4o6V1H3k6q4)9J5k6h3S2@1L8h3H3`.
2024-6-6 13:39
0
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
那个0.0.0.1:65535的重定向,我也是卡了好久,最后发现在它对应的配置文件里有注释掉的这条:
redirect 0.0.0.1:65535 127.0.0.1:5081;
似乎是把它又重定向了,然后就可以了。不过我一直卡在前端的初始化配置,还可以这样绕过学到了,谢谢师傅
2024-6-12 21:01
0
雪    币: 4233
活跃值: (813)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
师傅有没有推荐的能模拟出IOT设备的虚拟环境呢,不需要硬件什么的,只需要搭建一个模拟物联网接受漏洞测试攻击的平台,然后使用虚拟机中的Kali去测试它,最后提取并分析iot设备里的固件。并用二进制去分析
2024-6-14 22:37
0
雪    币: 231
活跃值: (280)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
狠狠的学到了
2024-7-11 14:28
0
雪    币: 4569
活跃值: (6260)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谷歌盘不方便下载
2025-2-26 15:51
0
游客
登录 | 注册 方可回帖
返回