Disclamer: 此文仅供学习逆向技术之用,权利者想要 claim 请直接邮箱联系下掉文章,不要律师函镜糕喵,已投降喵

新年好。

TL; DR

想直接免拆机刷 OpenWRT 不看折腾过程的,按如下步骤操作(要求有一定 Linux 操作能力,注意:笔者不通过包括但不限于评论区/邮箱等任何形式受理一对一技术指导。请仅在确定是文章的步骤描述有问题或官方有了进一步更新再联系笔者)。期待有人整出一键脚本或者更清晰的教程(或许可以分析分析有没有和上一版本相似的 RCE)。

首先准备几个脚本,并安装好 Python 与 Nu Shell(安利一下后者,挺好用的 Shell)。

xor_tool.py

#!/usr/bin/python3
import sys
import os

def xor_file(input_path):
    # 1. Validation: Ensure the file exists
    if not os.path.isfile(input_path):
        print(f"Error: File '{input_path}' not found.")
        return

    # 2. Define the output filename
    base_name = os.path.basename(input_path)
    output_path = f"decoded-{base_name}"

    try:
        # 3. Read the input file in binary mode ('rb')
        with open(input_path, 'rb') as f:
            data = f.read()

        # 4. Perform XOR 0x55 on each byte
        # We use a bytearray for efficient processing
        processed_data = bytearray(b ^ 0x55 for b in data)

        # 5. Write the result to the new file in binary mode ('wb')
        with open(output_path, 'wb') as f:
            f.write(processed_data)

        print(f"Success! Processed file saved as: {output_path}")

    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    # Check if a filename was provided as a command-line argument
    if len(sys.argv) < 2:
        print("Usage: python script_name.py <filename>")
    else:
        xor_file(sys.argv[1])

enable-telnet.sh

#!/bin/sh
telnetd -l /bin/sh -p 7788

packedconf.nu

#!/usr/bin/nu
cd NX30Pro/mnt/config
rm -rf cfgmd5/firewall*
let fwmd5 = open firewall | hash md5
print $fwmd5
touch $"cfgmd5/firewall-($fwmd5)"
cd ../..
tar -czf ../NX30Pro-config/NX30Pro.tar.gz *
cd ../NX30Pro-config
let cfmd5 = open NX30Pro.tar.gz | hash md5
print $cfmd5
$"NX30ProV100R010\n($cfmd5)" | save -f NX30Pro.info
tar -czf ../NX30Pro-finished.cfg *
cd ..
python xor_tool.py NX30Pro-finished.cfg
  1. 从当前系统备份配置,顶端“更多”-左侧“设备管理”-设备管理-配置备份,得到 NX30Pro.cfg 文件;
  2. 解码文件 python xor_tool.py NX30Pro.cfg
  3. 进入 root 用户或 fake root 环境(为了保证文件权限),在其中带权限(-xpzf)解压得到的压缩包 decoded-NX30Pro.cfg 到 NX30Pro-config 文件夹,此文件夹应该有两个文件:NX30Pro.info NX30Pro.tar.gz
  4. 进一步解压内层压缩包到与 NX30Pro-config 同级的 NX30Pro 文件夹(方便后续操作,不直接解压到NX30Pro-config 内),此时的目录结构应该如下(另还有 xor_tool.py packedconf.nu 与这两个目录同级)
  5. 建立 NX30Pro/mnt/config/script 目录并将上述 enable-telnet.sh 放到这里面;
  6. 编辑 NX30Pro/mnt/config/firewall,在开头加上如下片段
config include 'custom'
        option type 'script'
        option path '/etc/config/script/enable-telnet.sh'
        option family 'any'
        option enable '1'
        option reload '1'
  1. 运行上述 packedconf.nu 得到 decoded-NX30Pro-finished.cfg
  2. 在同一界面选择上述文件恢复配置,重新上电;
  3. 完全启动完成后,使用 Telnet 连接到路由器 7788 端口,不需密码直接进入 root;
  4. https://blog.qust.me/nx30pro 或其它任意教程操作;

起因

最近几个月在重新配自己的整个 All in One Homelab,计划在家里云跑跑公网和 dn42 的路由,并且还计划把所有的线上的服务迁到本地,有可能还要做个 Anycast。虽然主机性能其实十分糟糕(消费级平台,i3-12100+32GB 单条 DDR4),但还是打算头铁配,毕竟年底这波硬件涨价加上近期个人经济困窘,很长时间内不会有换硬件的机会了。有时间应该会把整个折腾的记录或者至少结果发出来。

而计划中的一环就是引入一个新的无线 AP,因为有 VLAN 和连公用 Wi-Fi(即无线转有线)的需求,因此原厂固件不够用。笔者先前在本科宿舍用的是经典的基于 MT7621 的红米 AC2100。不过手机都支持 Wi-Fi 7 了,入户也拉了上下行千兆,因此就想着换成至少符合 AX3000 速率的。朋友先前有刷过一个 H3C Magic NX30 Pro 并向笔者推荐,因为网上有很多教程,例如 https://blog.qust.me/nx30prohttps://www.right.com.cn/forum/thread-8356975-1-1.html 等等,同时此机型的原厂固件居然开放了 Telnet 可以很轻易地免拆机刷机。另外,此路由器的价格也相当低廉,笔者在闲鱼 120 左右购得,而全新的在某东也就 149 左右。此机器基于联发科 MT7981 平台,很热门,资料很多。

不过拿到后笔者才发现,此机型的新版原厂固件封堵了 Telnet。似乎 V100R009 和 V100R010 版的固件均默认没有打开 Telnet。网上给出的首选刷机方式是拆机接 TTL 线刷,因此笔者也首先尝试了拆机。

拆机刷机

拆机与连接

NX30 Pro 虽然外壳只有上下两个部分,但却十分难以拆开,卡扣多且特别特别紧。因为天线和本体一体,所以上面的较软又有较紧卡的扣的部分需要特别小心。拆下后盖上的 6 颗螺丝,从下面一点一点用撬棍断开卡扣。

笔者手上没有先前用过那种好用的、较长的金属撬棒,因此只能用镊子、一字螺丝刀,以及废弃的游戏卡拆机。附凶器一览。

说起来这张卡还是 2024 年初那次去韩国日本香港旅游时在香港玩 maimai DX 时开的卡,结果只用了一次就带着里面的几港币余额失效了。这种“未使用的卡在 2 个月后带着余额失效”的规定要是放到内地恐怕是违反一些消费者权益相关规定的罢(笑)。笔者断开卡扣的顺序是先从底部的两个角再扩展到整个底边,并且成功滴血认亲(其实是被一字螺丝刀戳伤了)。

底边松动、所有卡扣松开之后从(第一张图视角的)左边断开侧面卡扣。此后大力出奇迹把最左边天线的根部掰松,再用镊子尖端撬开天线上的卡扣,使得最左侧的上下两部分分离、错开,注意天线的 PCB 就在里面,不要划伤了天线的 PCB。此后直接断最右边会比较困难,可能是因为左边错开使得两片外壳扣得更紧了。因此考虑先断左数第二根天线使得天线根部(即本体顶边)稍微松一点,再从右边松开右数第一和第二根天线,最后掰开外壳两部分。此处的拆机顺序仅供参考,请以实际手感为准。

拆开后上面第二张图右边就是 TTL 了。按理说只需要连接路由器电源,再把这里的 GND、TX、RX 插在 FT232RL 或者 CH340/1 就可以刷机了,但笔者一没有焊台,二没有正经的烧录夹,难以完成稳定的连接。PCB 上只留了四个 SMT 焊盘,而不是那种 DIP 焊排针的位置,没法直接把公头杜邦线插进 DIP 孔中。为了使得至少刷机的数据能稳定传输(而不是用串口上 X/Y/ZMODEM),不得不再接一根网线做 TFTP,任意网口和电脑直接连接即可。

笔者在尝试了电工胶、透明胶等多种方法后,最后采用的方案是把三根杜邦线公头线合成一束,再用挂衣服的夹子夹到 PCB 板上。连接极端不稳定,因此必须拿一只手压住夹子尖端才能正常通信。这里更致命的一点是由于不得不额外插一根网线,而网线的头子难以完全穿过外壳上的孔(正常状态是隔着外壳插进 PCB 板上的接口),同时又不方便完全把外壳和 PCB 分离(因为天线固定在壳子上),并且 TTL 焊盘的正下方正好顶了几个外壳的塑料柱,因此很难夹得上,只能手动辅助辅助。

最后的连接是路由器任一网口接电脑网口,电源接适配器,GND/TX/RX 接 CH340。CH340 TTL 电平设置为 3.3V

上位机操作刷 uboot

驱动等不赘述,笔者重装系统后第一次用此 USB-TTL 模块因此手动去 WCH 官网下了最新(24 年版)的驱动。WCH 的驱动质量一直一言难尽,同时又没开源(Linux 版的一些版本倒是有源代码发出来),幸好 24 年版的没有人遇到触发上位机蓝屏的情况。安装好后使用如下连接配置: 3.3V 电平,115200bps 8-N-1 无流控。

在上电之前先配置网卡与 TFTP 和准备 uboot 镜像。网卡随便配置一个私有 IPv4 地址、无网关即可(这里打漏了一个1,笔者实际用的是 192.168.11.2,见后续步骤)。

TFTP 服务器用经典的 TFTPd64。

此处用的 uboot.bin 一开始下载自 H 大 的仓库 https://github.com/hanwckf/bl-mt798x/ (实际上有多种选择,看下面的详细介绍)。在 Release 里找到最新的,找到其中 mt7981_h3c_magic-nx30-pro-fip-fixed-parts.bin 重命名成 uboot.bin

正常打开串口后上电应该会跑码。上电后立即狂按上下键会进入如下选单。

选择第 4 段更新 ATF FIP 即 uboot,再选 0,即从 TFTP 拉取 uboot 数据。如果有稳定的串口连接,可以考虑使用 Xmodem 或 Ymodem,否则还是老实用 TFTP 吧。

同样随便选一个同一网段的 IP 地址,再输入其它信息,即可开始刷写。

进入这个 <H3C> 的提示符后就可以断电重新上电了。上电时按住 RESET 键,再将网段改到 192.168.1.x,访问 192.168.1.1 会进入 uboot 界面,说明 uboot 成功。

不拆机刷机

但笔者此时并不满意,因为在这个状态下无论是 H 大提供的 uboot 网页接口还是串口控制台,均没有提供方法 dump 出来 MTD 存储里的内容,无法备份原厂固件。同时 H3C 又关闭了官网上原厂固件的下载,因此唯一的方法是从路由器上备份。于是笔者仍然尝试去找 break-in 原厂系统的手段。root 用户的真实密码笔者并不知道(并不是网页后台界面管理员密码或者 H3C 之类的),而 tty 登录是需要密码的,因此这条路基本走不通。

笔者找到了如下的线索:

  1. 有人在恩山上发贴称可以把备份导出来,发到闲鱼上花钱找人修改后再导入回去即可开启 Telnet,说明 Telnet 是可以开的。不过这个文件有“加密”;
  2. 由于拿不到最新版的固件分析,笔者在恩山上的这个帖子找到了 V100R002 的旧版固件。
  3. ZIKH26 大佬提交过 CVE-2025-2726,其中涉及一个 RCE 漏洞,并包括了对 H3C 固件 Web API 的一些分析。原贴已经被删除,Web Archive 上有备份

事实证明要解开比想象中的要简单一些,只需要最基础的分析。厂商的安全措施做得还是不尽人意,但这反而对于我们是好事。

固件拆解

从上面提到的帖子里面下载解压出 backup.img 文件,再从备份路由器运行配置得到 NX30Pro.cfg。可以看到这个 backup.img 是一个 UBI 镜像:

chariri@chariri-arch ~/stock> file backup.img 
backup.img: UBI image, version 1

与其费劲地将其用 MTD 工具挂到内核里面,不如直接使用 ubi_reader 进行解压。用 uv tool 安装好此工具后,直接执行 ubireader_extract_images backup.img 后就在当前目录得到 ubifs-root/backup.img/,内有一堆 ubifs 文件。

chariri@chariri-arch ~/stock> ls ubifs-root/backup.img/
img-1660220975_vol-kernel2.ubifs  img-1660220975_vol-rootfs2.ubifs      img-1660220975_vol-rootfs.ubifsimg-1660220975_vol-kernel.ubifs   img-1660220975_vol-rootfs_data.ubifs  img-1660220975_vol-u-boot-env.ubifs
chariri@chariri-arch ~/stock> cd ubifs-root/backup.img/
chariri@chariri-arch ~/s/u/backup.img> file img-1660220975_vol-rootfs.ubifs
img-1660220975_vol-rootfs.ubifs: Squashfs filesystem, little endian, version 4.0, xz compressed, 15089502 bytes, 2361 inodes, blocksize: 262144 bytes, created: Wed Dec  7 17:18:33 2022

发现 ubifs 文件内部是 squashfs 文件系统,使用 unsquashfs 解压。

chariri@chariri-arch ~/s/u/backup.img> unsquashfs -mem 128M -f -d rootfs1 img-1660220975_vol-rootfs.ubifs
Parallel unsquashfs: Using 8 processors
2256 inodes (2105 blocks) to write


create_inode: could not create character device rootfs1/dev/console, because you're not superuser!
[=================================================================================================================================================================| ] 4360/4361  99%

created 1962 files
created 105 directories
created 293 symlinks
created 0 devices
created 0 fifos
created 0 sockets
created 0 hardlinks

发现根目录下面就有一个 /www 里面是网页和 API 后端(/www/api)。复制到本地加载到 IDA 分析。小孩子不懂逆向弄着玩的(,直接结合抓包发现关键接口是 /esps,搜字符串结合上述 CVE 披露的细节定位到如下代码。

这里这个 execcmd 最后被 popen 了。上述 CVE 似乎已经在最新版本被封堵(未从代码验证),笔者未能直接用 ZIKH26 写的 PoC 拿到 Telnet,因此需要进一步分析 /usr/lib/lua/protol_cvt.lua

对应的文件是 ubifs-root/backup.img/rootfs1/usr/lib/lua/magic_link/magic_link.lua,发现里面直接调用了 OpenWRT ubus 上的命令。笔者懒得细细去查,因此直接整个文件系统搜执行的 method:

chariri@chariri-arch ~/s/u/b/rootfs1> grep -abor "backupprofile" .
./usr/libexec/rpcd/esps.system:5010:backupprofile
./usr/libexec/rpcd/esps.system:8313:backupprofile
./usr/bin/outinfo.sh:580:backupprofile
./www/assets/equip.ade96d1d.js:1137:backupprofile
./www/assets/portal.efed5bda.js:1633:backupprofile
chariri@chariri-arch ~/s/u/b/rootfs1> file ./usr/libexec/rpcd/esps.system
./usr/libexec/rpcd/esps.system: POSIX shell script, Unicode text, UTF-8 text executable

里面涉及写出备份的代码只有一行 cfgFileFinal=$(cfg_backup)。再定位到 /usr/sbin/cfg_backup

chariri@chariri-arch ~/s/u/b/rootfs1> find -name "cfg_backup"
./usr/sbin/cfg_backup
chariri@chariri-arch ~/s/u/b/rootfs1> file ./usr/sbin/cfg_backup 
./usr/sbin/cfg_backup: POSIX shell script, ASCII text executable

同样,里面重要的只有一行 file_encrypt "${cfgFileOrg}" "${cfgFileFinal}"

file_encrypt 是个 ELF 文件,拷出来看看,结果把我整笑了。

原来就是整个文件异或 0x55 啊。直接写一个 Python 脚本就可以了(其实 NuShell 也行,但 NuShell 也不是特别方便就是了)。见文章开头的 xor_tool.py。解码出来根据上述 ./usr/libexec/rpcd/esps.system 的代码,是一个 tar.gz 套 tar.gz,第一层 tar.gz 里面还有一个 info 文件捆了 hostname 和 第二层 tar.gz 的 MD5 信息,此文件在恢复时要校验,因此重新打包第二层 tar.gz 之后需要同步修改这个 info 文件。

配置拆解与注入

解压时笔者在 root 下操作,主要为了保留 tar 文件的权限。解开不出意外是经典的 OpenWRT UCI 文件,不过并不是在标准的 /etc/config 而是在 /mnt/config,网上的文章称此机器只有 /mnt/ 内的会保存,似乎 H3C 的固件会在开机时把 /mnt/config 复制到 /etc/config。总之只需要在这里面找到能开关 telnet 的选项即可。笔者尝试建立了一个 rc.d 目录在里面符号链接到 telnetd,封回导入配置后并没有成功。

此时笔者非常希望 OpenWRT UCI 能给个任意代码执行的 gadget,想睡觉就来枕头,在恩山的这篇文章找到了。具体的文档在 OpenWRT 官方 Wiki,也就是在防火墙的 UCI 里面可以写一个任意执行的脚本,因此只需要在 /mnt/config/firewall 里加这么一段:

config include 'custom'
        option type 'script'
        option path '/etc/config/script/enable-telnet.sh'
        option family 'any'
        option enable '1'
        option reload '1'

并把 enable-telnet.sh 放到 /etc/config/script 目录配置好权限即可在开机时自动执行脚本。enable-telnet.sh 的具体内容方面笔者有如下尝试:

  1. service telnet start/etc/init.d/telnet start 无效,后面会意识到是 telnet 的服务脚本本身改了所致,与先前 rc.d 添加 S50telnet 无效一个原因;
  2. ping 和 wget 主机成功,说明脚本的确被执行了。
  1. 从先前的那个 CVE 细节中抄出来一段 telnetd -l /bin/sh -p 7788 成功了;

为了自动化封装回去可以导入的配置,笔者写了一个简短的 nushell 文件,在文章开头的 packedconf.nu。读者想复现可以直接调用或者参考里面的具体实现自行操作。注意到 /mnt/config 里面还有一个目录 cfgmd5 里面是各个配置文件的 MD5(直接写在文件名里),怀疑如果不正确更新这里的 MD5 会造成配置被回滚,因此顺手把此处的 MD5 也更新了。

一通操作后,终于可以在 7788 端口上拿到一个 root shell。

备份与刷 uboot

笔者在这个 shell 里面读了下 telnet 的 init.d 服务文件,发现里面多了逻辑,但即使配置 uci -q set telnetcfg.telnet.enable=1/etc/init.d/telnet start 也没法正常打开 telnet,遂懒得折腾,先把 SSH 打开要紧,用教程中的方法下载 Dropbear 并重置 root 密码。

curl -o /tmp/dropbear.ipk http://192.168.124.2:8000/dropbear_2019.78-2_aarch64_cortex-a53.ipk
opkg install /tmp/dropbear.ipk
/etc/init.d/dropbear enable
/etc/init.d/dropbear start
passwd

此时便可以使用 root 连接,记得允许老旧 ssh-rsa。

同样抄自论坛上的教程,备份原厂固件:

# 查看分区表
cat /proc/mtd

# 备份原厂固件
dd if=/dev/mtd5 of=/tmp/mtd5_ubi
# (先把最大这个 ubi 拷出来)

# 单独备份(小)分区
rm -rf /tmp/mtd5_ubi
dd if=/dev/mtd1 of=/tmp/mtd1_BL2
dd if=/dev/mtd3 of=/tmp/mtd3_Factory
dd if=/dev/mtd4 of=/tmp/mtd4_FIP

注意中途删掉了 mtd5_ubi,拆成两段做就行。拷文件可以用 WinSCP,但显然直接在命令行里更简单。这里因为是在 Windows 上执行因此用的是 NUL,如果是 Linux 当然用的是 /dev/null

> scp -O -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL -o PubkeyAcceptedAlgorithms=+ssh-rsa -o HostKeyAlgorithms=+ssh-rsa -P 22 root@192.168.124.1:/tmp/mtd5_ubi .
Warning: Permanently added '192.168.124.1' (RSA) to the list of known hosts.
root@192.168.124.1's password:
mtd5_ubi                                                                              100%   64MB   8.7MB/s   00:07

> scp -O -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL -o PubkeyAcceptedAlgorithms=+ssh-rsa -o HostKeyAlgorithms=+ssh-rsa -P 22 root@192.168.124.1:/tmp/mtd1_BL2 .
Warning: Permanently added '192.168.124.1' (RSA) to the list of known hosts.
root@192.168.124.1's password:
mtd1_BL2                                                                              100% 1024KB   9.5MB/s   00:00

> scp -O -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL -o PubkeyAcceptedAlgorithms=+ssh-rsa -o HostKeyAlgorithms=+ssh-rsa -P 22 root@192.168.124.1:/tmp/mtd3_Factory .
Warning: Permanently added '192.168.124.1' (RSA) to the list of known hosts.
root@192.168.124.1's password:
mtd3_Factory                                                                          100% 2048KB   9.4MB/s   00:00

> scp -O -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL -o PubkeyAcceptedAlgorithms=+ssh-rsa -o HostKeyAlgorithms=+ssh-rsa -P 22 root@192.168.124.1:/tmp/mtd4_FIP .
Warning: Permanently added '192.168.124.1' (RSA) to the list of known hosts.
root@192.168.124.1's password:
mtd4_FIP                                                                              100% 2048KB  10.4MB/s   00:00

备份完后,继续按 https://blog.qust.me/nx30pro 的教程刷 uboot 就行。把 uboot.bin 用 scp 拷到机器 /tmp 下后就可以执行:

md5sum uboot.bin
mtd write /tmp/uboot.bin FIP

但是关于刷哪个 uboot,其实是有讲究的。至少笔者最后没有用上述提到的 uboot。

OpenWRT 与 uboot 版本选择

无论是免拆机还是拆机刷机,笔者均提到了 uboot 的版本选择有讲究,这还与 OpenWRT 镜像采用的格式与分区布局有关。想来以前刷部分机型时要先刷 factory 再从只读系统里面刷,似乎这台不需要了,因为别人编译的 uboot 已经有 sysupgrade 格式的支持。分区布局有原厂、大分区、OpenWRT uboot 等各种各样的布局。

NX30 Pro 这台机器根据 H 大的说法,因为原厂的一些数据使用 YAFFS 文件系统,如果刷非原厂的分区布局似乎有些神秘问题会导致 NMBM 把整个闪存标记成坏块而变砖,因此建议保留原厂布局。同时原厂布局里面也有一些无线校准和 MAC 地址之类的数据,保留下来比较好。笔者反正也用不到各种魔法上网等需要在路由器上跑大量任务的需求,因此原厂布局足够了。坏块管理方便笔者也不知道是怎么处理的(误),可能是和原厂一样的 UBIFS 套 squashfs 吧,反正 NMBM 是没有启用的。

镜像格式方面,天灵写过一篇简短的文章介绍。比较关键的是两种格式:-sysupgrade.bin-sysupgrade.itb 两种。前者可以直接刷,后者是新的 Flattened uImage Tree (FIT) 格式,需要 uboot 支持。除了官方的 uboot 之外,还有常用如下 uboot:

  • OpenWRT 的 uboot(事实上是 das uboot),编译 OpenWRT 就会得到一个 uboot 的 bin 文件,功能很强,但使用稍微麻烦一点,主要是没法从 Web 界面直接刷系统,还有人因为进不去 Web 界面以为砖了;
  • H 大的 uboot,改自 MTK 给的 uboot,因此有各种命令行工具,同时还加了 Web UI 可以直接刷,有23、24 等多个版本,似乎最新的(没有发布预编译二进制)的 25 版本添加了 FIT 的支持;
  • 天灵大佬的 uboot,改自 H 大的旧版 uboot,提供二进制的同时支持 FIT;

系统方面,有几个常用系统:

  • 官方原厂系统,基于 OpenWRT 21.02,有硬件加速和闭源驱动;
  • OpenWRT 主线系统,目前最新稳定版是 24.10,内核版本为 6.6,只有开源驱动,例如已经较为成熟的 mt76 驱动
  • H 大的 ImmortalWRT-mt798x,基于 OpenWRT + ImmortalWRT 21.02,有硬件加速和闭源驱动;
  • P 大的 ImmortalWRT-mt798x-6.6,基于 OpenWRT + ImmortalWRT 24.10,内核版本为 6.6,同样有硬件加速与闭源驱动;
  • 头铁可以试试把 mtk-openwrt-feeds 整合到主线 OpenWRT 里面,实现最新主线 + 闭源驱动,笔者编译没成功,也没时间适配和调试了;

笔者不需要 ImmortalWRT 的丰富软件包源等,因此选择了自己编译一个主线 OpenWRT 24.10 系统。由于主线系统使用 FIT .tib 格式,因此 uboot 使用了天灵大佬的支持 FIT 的版本。编译本身没有什么可写的,跟着 OpenWRT Wiki 上的教程一步一步做即可。最后会得到如下文件:

这里面需要刷入的有 -squashfs-sysupgrade.itb-proloader.bin 两个文件。首先上面刷的 uboot 版本不对,因此手动给有线网卡指定 192.168.1.2(因为上面几个 uboot 都没有 DHCP 功能),按住 RESET 上电,打开 http://192.168.1.1/uboot.html 刷入天灵的 uboot。

刷好后再次按住 RESET 上电,打开 http://192.168.1.1/bl2.html 刷入 preloader。注意到下面的 footer 应该有一行《缘之空》的副标题“In solitude, where we are least alone”。

最后刷入 FIT .itb 格式的系统:

刷好后重启改为自动获取 IP,即可打开 http://192.168.1.1 进入 OpenWRT。