前言:最近不是毕业季嘛,捡垃圾捡了一个小米4C路由器,简单擦洗了一些污垢后直接上电,发现能用。搜了下参数很便宜,但是因为是白嫖的😋,还是准备刷个OpenWrt。目前刷入的是官方版本
22.03.5
,在此感谢 @MALossov巨巨(Orz)的帮助,总算是把这个路由器的坑踩完了🥰。
准备
XiaoMi Mi Router 4C
路由器- 一根网线
Python
环境Breed
:https://blog.hackpascal.net/- 漏洞提权工具:https://github.com/acecilia/OpenWRTInvasion
OpenWrt
固件:https://downloads.openwrt.org/releases/22.03.5/targets/ramips/mt76x8/openwrt-22.03.5-ramips-mt76x8-xiaomi_mi-router-4c-squashfs-sysupgrade.bin
漏洞提权
-
将仓库OpenWRTInvasion下载或clone到本地。
-
使用Python安装目录下依赖:
pip install -r requirements.txt
-
运行漏洞提权工具:
python remote_command_execution_vulnerability.py
-
登录到路由器Web页面,复制链接输入到漏洞提权的工具。
-
提权完成后,通过ssh和ftp连接就可以控制路由器了。
备份
进行下一步工作之前,我们需要将原厂的
bootloader
分区、eeprom
分区备份,通过查阅OpenWrt
的Xiaomi-4C
的原厂闪存布局得知:
mtd1 = bootloader
mtd3 = eeprom
Stock /proc/mtd
dev: size erasesize name
mtd0: 01000000 00010000 "ALL"
mtd1: 00020000 00010000 "Bootloader"
mtd2: 00010000 00010000 "Config"
mtd3: 00010000 00010000 "Factory"
mtd4: 00010000 00010000 "crash"
mtd5: 00010000 00010000 "cfg_bak"
mtd6: 00100000 00010000 "overlay"
mtd7: 00c60000 00010000 "OS1"
mtd8: 00af0000 00010000 "rootfs"
mtd9: 00200000 00010000 "disk"
- 以上信息可连接到路由器后,输入
cat /proc/mtd
查看
-
将整个磁盘分区命名为all.bin备份到tmp路径:
dd if=/dev/mtd0 of=/tmp/all.bin
将Bootloader分区命名为bootloader.bin备份到tmp路径:
dd if=/dev/mtd1 of=/tmp/bootloader.bin
将Eeprom分区命名为eeprom.bin备份到tmp路径:
dd if=/dev/mtd2 of=/tmp/eeprom.bin
-
使用ftp备份到本地(备份前需确认大小是否正确)。
刷入Breed
-
将breed.bin文件复制到远端/tmp目录下。
-
通过ssh执行下列命令刷入Breed:
mtd write /tmp/breed.bin Bootloader
-
刷入完成后,长按复位键复位路由器。
-
通过浏览器访问192.168.1.1进入breed。
刷入OpenWrt
通过阅读OpenWrt的XiaoMi_mi_Router_4C的dts文件
/{your openwrt source location}/openwrt/target/linux/ramips/dts/mt7628an_xiaomi_mi-router-4c.dts
我们发现,firmwire分区的起始地址为0x160000
,大小为0xea0000
,即:内核(kernel)位于0x160000
起始。
然而,需要注意的是,我们使用的通用breed刷机工具并没有对其进行适配。如果你选择使用图形界面刷机方式,只能选择几个有限的位置,比如0x60000
等。这就导致了一个问题:
尽管bootloader
能够在0x60000
地址正确加载内核,但由于内核中嵌入了dtb文件,而dtb文件定义了文件系统的位置,如果你将OpenWrt
刷入0x60000
地址,由于整个文件向前移动了,导致文件系统也跟着向前移动。因此,dtb无法找到正确挂载文件系统的位置(标识为magic:D0 0D FE ED
),导致整个系统启动过程失败并不断重启。
OpenWrt snapshot /proc/mtd
dev: size erasesize name
mtd0: 00020000 00010000 "bootloader"
mtd1: 00010000 00010000 "config"
mtd2: 00010000 00010000 "factory"
mtd3: 00010000 00010000 "crash"
mtd4: 00010000 00010000 "cfg_bak"
mtd5: 00100000 00010000 "overlay"
mtd6: 00ea0000 00010000 "firmware"
mtd7: 002052ab 00010000 "kernel"
mtd8: 00c9ad55 00010000 "rootfs"
mtd9: 00a10000 00010000 "rootfs_data"
为了解决这个问题,我们需要手动将OpenWrt
刷入到0x160000
起始的闪存位置上:
-
使用Python开一个局域网的共享文件夹:
python -m http.server 8000
-
使用telnet连接到Breed,再通过wget命令下载局域网的OpenWrt文件:
wget [.../openwrt.bin]
记住这里的两个信息:
- Length: {Length}
- Saving to address {save addr}
-
运行命令擦除要写入的分区:
flash erase {start addr} {size}
这里以firmwire为例,起始地址0x160000,大小0xea0000
-
运行命令刷入openwrt.bin文件:
flash write {start addr} {save adrr} {size}
这里以
firmwire
和OpenWrt 22.03.5
为例,起始地址0x160000
,存储地址为0x80000000
,大小为0x5c0139
-
运行命令加载内核:
boot flash 0x160000
现在就已经可以正常启动OpenWrt了
-
设置OpenWrt自启动:更改环境变量字段,实现自动执行命令加载内核
后记
这个路由器系统启动的过程分为以下阶段:**引导加载程序(bootloader)启动并加载内核(kernel),内核运行并挂载文件系统,内核开始执行用户模式程序,内核将权限交给用户模式程序以继续系统执行。**如果直接采用通用Breed的图形界面进行刷机就会导致无限重启。