👁 29

新手安全入门:端口收敛与组网访问

⚠️ 先看这段再往下翻
这台光猫没有 TTL 排针,刷坏了只能拆机上编程器。没有自救能力、没有第二台能查资料的设备,不要刷。文中所有 MAC、SN、密码、密钥都已替换成示例值,照抄一定失败,必须换成你自己机器的现场数据。全文 15 节、10 张表,是我这台机器一次真实刷机从开始到验收的完整记录。

这篇文章到底写了什么

网上关于 AN7581 光猫刷机的资料,大多停在「能进 U-Boot 了」或者「刷完能开机了」。真正会让人卡住的其实是另外几件事:

  • 原厂 17 个分区怎么在不拆机、不用 TFTP 的情况下完整备份出来,并且证明备份是对的;
  • U-Boot 要的 1 MiB factory 板级数据怎么从原厂那堆文件里重建,格式是什么;
  • 六步刷写里每一步的期望输出是什么,哪些报错属于正常、哪些必须停下来;
  • 刷完怎么验收,而不是「能亮灯、能上网」就算完。

这篇按顺序全部写清楚:原理、准备、开 Telnet、备份、重建 factory、装恢复引导、U-Boot 六步、验收、故障排查、救砖、以及最后的自动化。

一、这台机器是什么

项目值
型号FiberHome HG5585F CT(中国电信定制)
SoCAiroha AN7581,4 核 ARMv8
内存512 MB
闪存256 MiB NAND
原厂系统Linux 5.4.55 aarch64
原厂 Webhttp://192.168.1.1:8080(80 端口只是 LuCI 前端壳)
刷入系统PonWrt SNAPSHOT r41551-c3b518baec,内核 6.18.52,target airoha/an7581

同平台其它机型(AN7581 / AN7583 那一批光猫)的路子类似,但分区偏移、factory ABI、FIT 型号字符串都可能不同,不要跨机型套用。总览类资料可以看另一篇,这里的每个数字都只对 HG5585F CT 负责。

二、为什么可以免拆

刷机链路实际由三段组成,每段都只依赖上一段的产物:

原厂系统(Telnet root)
  ├─ 备份 17 个 MTD 分区(HTTP,MD5 校验)
  ├─ 导出 factory_conf / table / WiFi EEPROM
  ├─ 重建 1 MiB factory-1m.bin
  └─ 写入 BL2 + FIP(an758x-stock2ubi),重启
        ▼
U-Boot 恢复模式(http://192.168.0.1/)
  ├─ flash-bl2
  ├─ ubi-rebuild
  ├─ flash-board-data(factory 卷)
  ├─ flash-uboot(FIP)
  ├─ flash(sysupgrade.itb)
  └─ boot-production
        ▼
OpenWrt / PonWrt(http://192.168.1.1/)
  └─ 型号、网络、Web、SSH、MAC、UBI 卷、回读哈希逐项验收

真正难的不是「刷」,是备份校验和 factory 重建。这两步错了,后面全白干。

三、准备清单

类别需要的东西说明
硬件网线一根、电脑一台全程不需要 TTL、不需要拆机
主机环境Linux,curl、Python 3、telnet 客户端Windows 也能刷,但备份和 factory 脚本都在 Linux 侧
工具an758x-stock2ubi(ARM64 静态二进制)跑在原厂系统里,提供备份和写引导的 HTTP 接口
引导preloader.bin(BL2)、bl31-u-boot.fip(FIP)必须是为 HG5585F CT 构建的产物,两处用同一组文件
系统*-squashfs-sysupgrade.itbFIT 型号必须是 fiberhome,hg5585f-ct
磁盘至少 1 GB 空闲17 个分区备份约 416 MB
耐心首次进入 U-Boot 网页要等 60–90 秒25 MiB 固件上传可能要 5–15 分钟

关于引导文件有一个必须说清楚的点:BL2 和 FIP 不能从原厂 mtd0 里提取。原厂 mtd0 是厂商自己的引导,不是你要装的 U-Boot。要从 pbs05/uboot-an758x 这类项目拿为该机型构建的成品,并且「装恢复引导」和「U-Boot 六步」用的是同一组 preloader 和 FIP,不能一个用 A 版、一个用 B 版。

四、第一步:免拆开 Telnet

4.1 关键前提

必须先登录 8080 的 Web 管理页,否则所有 POST /cgi-bin/ajax 一律 404——加密写得再对也没用。80 端口那个 LuCI 页面只是前端,认证和接口都在 8080。

会话按客户端 IP 绑定,不需要 cookie。也就是说:同一台电脑登录一次,后面直接用。

4.2 五步接口

步骤请求作用
1POST /login.cgi(username=telecomadmin&psd=)建立管理会话,成功响应里含 window.location.href="main.html"
2GET /cgi-bin/ajax?ajaxmethod=web_get_brmad读设备 MAC,返回 {"brmad":"AABBCC112233"}
3本地计算sha256(MAC大写) 的十六进制串:前 16 位做 IV,第 32–48 位做 key
4GET /cgi-bin/ajax?ajaxmethod=web_get_refresh_sessionid取一次性 sessionid
5POST /cgi-bin/ajax(AES 密文的十六进制)提交 telnet=1&action=telnet&sessionid=&ajaxmethod=set_services

加密方式是 AES-128-CBC + PKCS7,key 和 IV 就是上面那两段 16 个字符(16 字节),输出小写十六进制作为请求体。

成功响应长这样,randstr 每次不同:

{"randstr":55407696,"services":{"ftp":"0","telnet":"1","dnsrelay":"1","portal":"0","access":"0","terminal_number":"255","status":"99","result":"99"}}

判断成功的唯一标准是响应里出现 "telnet":"1"。部分固件会把响应也加密成十六进制,脚本要兼容两种。

4.3 最小实现

import hashlib, binascii, urllib.request, urllib.parse, json
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

BASE = "http://192.168.1.1:8080"
UA = {"User-Agent": "Mozilla/5.0"}

def get(p):
    return urllib.request.urlopen(urllib.request.Request(BASE + p, headers=UA), timeout=8).read().decode()

def post(p, body):
    req = urllib.request.Request(BASE + p, data=body.encode(),
        headers={**UA, "Content-Type": "application/x-www-form-urlencoded"}, method="POST")
    return urllib.request.urlopen(req, timeout=8).read().decode()

# 1. 先登录,不登录后面全是 404
post("/login.cgi", urllib.parse.urlencode({"username": "telecomadmin", "psd": "你的Web密码"}))

# 2. MAC → 密钥
mac = json.loads(get("/cgi-bin/ajax?ajaxmethod=web_get_brmad"))["brmad"].strip().upper()
h = hashlib.sha256(mac.encode()).hexdigest()
iv, key = h[:16], h[32:48]

# 3. sessionid
sid = json.loads(get("/cgi-bin/ajax?ajaxmethod=web_get_refresh_sessionid"))["sessionid"].strip()

# 4. 加密提交
plain = f"telnet=1&action=telnet&sessionid={sid}&ajaxmethod=set_services".encode()
n = 16 - len(plain) % 16
enc = Cipher(algorithms.AES(key.encode()), modes.CBC(iv.encode())).encryptor()
body = binascii.hexlify(enc.update(plain + bytes([n]) * n) + enc.finalize()).decode()
print(post("/cgi-bin/ajax", body))

4.4 验证

nc -v 192.168.1.1 23     # 连上就说明端口开了
telnet 192.168.1.1       # 账号 telnetadmin
su                       # 提权到 root,id 应该是 uid=0(root)

Telnet 密码不是固定值,按 MAC 派生:Telnet 账号用 FH- 前缀 + MAC 后 6 位大写,su 用 Fh@ + MAC 后 6 位大写。具体字母和规则随机型不同,本文不贴固定串。

三点注意:

  • Telnet 是明文协议,只在 LAN 内用,别映射到公网;
  • 光猫重启后 23 端口是否保持,没有验证过,不通就重跑一次脚本;
  • 开 Telnet 只调用 Web 自己的接口,不刷机、不改固件,可逆。

五、第二步:17 个分区,一个都不能少

5.1 分区表

MTD名称大小物理偏移性质
mtd0boot2.5 MiB0x00000000只读,必须一致
mtd1bootflag512 KiB0x00280000启动标志,救砖关键
mtd2KernelA6 MiB0x00300000只读
mtd3RootfsA_Header8.2 KiB0x00900000只读
mtd4RootfsA_Data31.99 MiB0x009020cc只读
mtd5RootfsA32 MiB0x00900000只读
mtd6KernelB6 MiB0x02900000只读
mtd7RootfsB_Header8.2 KiB0x02f00000只读
mtd8RootfsB_Data31.99 MiB0x02f020cc只读
mtd9RootfsB32 MiB0x02f00000只读
mtd10apps120 MiB0x04f00000运行中可写
mtd11frameworka16 MiB0x0c700000只读
mtd12frameworkb16 MiB0x0d700000只读
mtd13factory3 MiB0x0e700000板级数据,JFFS2,挂 /fhdata
mtd14userlocalct2 MiB0x0f700000只读
mtd15apps(UBI 卷)106.08 MiB无物理偏移在 mtd10 内部
mtd16userdata(UBI 卷)8.36 MiB无物理偏移运行中可写

两个容易搞错的地方:

  • mtd15 / mtd16 不是物理分区,它们是 mtd10(120 MiB apps)内部的 UBI 卷,所以没有物理偏移。精确字节数:mtd15 = 111230976,mtd16 = 8761344。
  • 表里的大小是给人看的约数。校验时必须用 /proc/mtd 里的精确字节数,不能用 106.08 MiB 这种四舍五入的值。

5.2 怎么备份

把 an758x-stock2ubi 传到原厂系统上运行:

wget http://<你的电脑IP>:8000/an758x-stock2ubi -O /tmp/an758x-stock2ubi
chmod +x /tmp/an758x-stock2ubi
nohup /tmp/an758x-stock2ubi >/tmp/stock2ubi.log 2>&1 &
# 日志里应出现:AN758x Stock2UBI listening on http://0.0.0.0:3333

它自带备份接口,不用 TFTP,也不占 /tmp 空间:

for i in $(seq 0 16); do
  curl -o mtd$i.bin http://192.168.1.1:3333/backup/$i
done

index 严格对应 /proc/mtd 的顺序,从 0 到 16,一共 17 个文件,约 416 MB。

5.3 校验规则(这一步决定你敢不敢往下走)

1. 本地文件大小必须与 /proc/mtd 的精确字节数一致;

2. 在设备上跑 md5sum /dev/mtdX,与本地 md5sum 逐项比对;

3. mtd0–mtd9、mtd11–mtd15 必须完全一致;

4. mtd10 和 mtd16 允许不一致——它们是运行中可写分区,你读第一遍和第二遍都会不同。这不是备份坏了;

5. 生成 backup_md5.txt 存档,和备份放在一起。

只要 mtd0–mtd9、mtd11–mtd15 有一个不一致,就重新下载那个分区;两次都不一致,停下来查 NAND 坏块,别继续。

六、第三步:重建 1 MiB 的 factory

6.1 为什么要重建

U-Boot 要的 factory 是 UBI 里一个固定 1 MiB(1048576 字节)的静态卷,格式由 an7581-fiberhome-ubi-parts.dtsi 定义。而原厂 mtd13 是一个 3 MiB 的 JFFS2 分区(挂载在 /fhdata),两者完全不是一回事。

绝对不能把 3 MiB 的 mtd13 备份直接写进 1 MiB 的 factory 卷。 写进去的结果是 MAC 变随机、PON 校准丢失、WiFi 起不来。

6.2 三份输入

来源内容
/fhdata/factory_confUCI 文本:brmac(6 字节 MAC)、GponSN(8 字节 hex)、SerialNumber(ASCII)
/fhdata/table2048 字节,magic fiberhomebdbob,PON 校准数据
/fhdata/wlan/AX3000_RT30xxEEPROM_5.bin前 4096 字节是 MT7916 的 WiFi EEPROM

6.3 1 MiB 的布局

偏移大小内容
0x0000000x800APONCAL PON 校准块
0x0010000x1000MT7916 WiFi EEPROM
0x0020006基础 MAC
0x0020108PON SN(二进制)
0x0020200x20设备 SN(ASCII,NUL 补齐)
其余—全部 0xFF

APONCAL 头结构:

0x00  8   "APONCAL" + NUL(0x00)
0x08  u16 version = 1
0x0a  u16 header_size = 0x80
0x0c  u32 chip       (1 = GN28L95, 2 = 另一种)
0x10  u32 format     (1 = native)
0x14  u32 payload_size
0x18  u32 payload_crc
0x7c  u32 header_crc (覆盖 0x00..0x7b)
0x80  ... payload

CRC 是标准 CRC-32(poly 0xEDB88320、init 0xFFFFFFFF、末尾异或 0xFFFFFFFF),跟 zlib.crc32 一样。注意原厂 fiberhomebdbob 表里那个 CRC 用的是变体:同样是反射多项式,但从 0 开始、末尾取反,等价于 crc32(data, 0) ^ 0xFFFFFFFF。

WiFi MAC 的派生规则:

wifi_2g = base_mac; wifi_2g[1] += 1
wifi_5g = wifi_2g;  wifi_5g[5] += 8  (mod 256)

EEPROM 里的 device ID 必须是 0x7916。

6.4 写完的校验清单

  • 文件长度恰好 1048576 字节;
  • APONCAL magic、version=1、header_size=0x80;
  • header CRC 和 payload CRC 都通过;
  • 基础 MAC 是单播地址且不为全零;
  • PON SN 是 8 字节,设备 SN 不超过 32 字节;
  • WiFi EEPROM 的 device ID 是 0x7916;
  • 0x2040 之后全是 0xFF。

任何一条不过,都不要往设备上写。

七、第四步:装恢复引导,进 U-Boot

在原厂系统里调 an758x-stock2ubi 的接口,multipart 提交 BL2 和 FIP:

curl -F "[email protected]" -F "[email protected]" http://192.168.1.1:3333/api/flash

期望响应:

{"message":"BL2 written to /dev/mtdblock0; bootstrap UBI at 0x20000..0xe0000; readback verified; rebooting"}

看到 readback verified; rebooting 就说明写进去并回读验证过了。设备重启后进入 U-Boot 的 HTTP 恢复模式:

  • 地址变成 http://192.168.0.1/;
  • U-Boot 跑了 httpd dhcp,电脑会拿到 192.168.0.100 这类地址;
  • 页面可能要等 60–90 秒才出来,别急着断电。

没拿到 DHCP 就手动配静态 192.168.0.2/24,网关 192.168.0.1。

进去先读设备信息:

curl http://192.168.0.1/api/device

必须确认:

  • model 是 FiberHome HG5585F CT;
  • ubi = true、rebuild = true;
  • board_data 里有 {"kind":"ubi","target":"factory","size":1048576}。

从这一步开始,原厂系统已经没了,后面全靠 U-Boot 页面救。

八、第五步:U-Boot 六步刷写

8.1 接口长什么样

U-Boot 的 HTTP API 很朴素,但有两个坑必须先讲清楚:

接口方法说明
/api/deviceGET型号、内存、闪存、U-Boot 版本、ubi、rebuild、board_data
/api/storageGET可写目标:mtd nand0、bl2、ubi
/api/taskGET当前任务:id、state、busy、phase、code、upload_id、output
/api/envGETU-Boot 环境变量
/api/uploadPOST请求体就是文件原始字节,Content-Type: application/octet-stream
/api/taskPOSTJSON:{"operation":"...","upload_id":...}

坑一:/api/upload 不解析 multipart,必须发原始字节。而第四步原厂那侧的 ...:3333/api/flash 恰恰是 multipart——两个接口长得像,用错就传不上去。

坑二:/api/upload 的响应里同时有 upload_id 和 id。upload_id 是这次上传的句柄,用来提交任务;id 只是当前任务快照,不是新任务 ID。把 id 当任务号去轮询,会一直看到别人的任务。

8.2 提交与轮询

POST /api/task
{"operation":"flash-bl2","upload_id":8338}

返回 state=queued、busy=true。记下它的 id,每 0.7–1 秒轮询 GET /api/task,直到 state=done;code=0 才算成功,否则 output 里是错误。

两个必须遵守的规则:

  • 返回 HTTP 409 说明有任务在跑,等 busy=false 再提交,不要并发重试;
  • 轮询到的 id 和你提交的不一样,说明有另一个客户端(浏览器页面或另一个 agent)接管了,停下来重新读状态,不要假设你的任务执行过。

boot-production 是唯一例外:设备可能在 POST 返回前就重启,连接直接断。断开不等于失败,只有验收通过才算成功。

8.3 六步顺序与期望输出

顺序操作文件期望输出
1flash-bl2preloader.binBL2 written and verified (131072 bytes)
2ubi-rebuild—创建 fip、ubootenv、ubootenv2、factory 卷
3flash-board-data(target=factory)factory-1m.binWrote and verified 1048576 bytes in UBI volume 'factory'
4flash-ubootbl31-u-boot.fipFIP written and verified(FIP 340992 B)
5flash*-squashfs-sysupgrade.itbFirmware FIT verified for fiberhome,hg5585f-ct + 回读 CRC
6boot-production—设备重启,恢复页失联

顺序不可换,理由是硬的:

  • 先 BL2:没有 BL2 就没有启动链;
  • 再重建 UBI:旧厂商卷和新布局冲突,首次安装跳过 ubi-rebuild 必炸;
  • 板级数据必须在重建之后写:写在前面会被重建一起冲掉;
  • 最后才是 U-Boot 和系统:这两步失败还能回恢复页重来,前面错了就只剩串口/编程器。

8.4 哪些输出看着像错、其实是正常

  • Skipping bad block:NAND 出厂坏块,正常,记录偏移继续(这台机器的坏块在 0x0bfe0000、0x0c000000);
  • 写板级数据前出现 Read N bytes from volume factory to ...;
  • Creating dynamic volume fit.new 随后重命名为 fit;
  • code=0 但 output 很长。

真正必须停的:

  • 任何一步 code != 0;
  • FIT 校验报出别的型号;
  • 任务输出里 factory CRC 不匹配;
  • flash 之后没有 fit 卷;
  • boot-production 之后又回到 192.168.0.1。

还有三个操作永远不要用来「修」失败:nand-scrub(擦掉出厂坏块标记)、flash-all(整片覆盖,连引导一起)、write(裸写目标)。它们只会把可恢复的问题变成不可恢复。

九、第六步:验收,别用「能亮灯」当标准

设备起来后,电脑应该通过 DHCP 拿到 192.168.1.x,网关 192.168.1.1。

# 1. Web 是否可达
curl -sS -o /dev/null -w '%{http_code}' http://192.168.1.1/; echo

# 2. 型号与系统
ssh [email protected] 'ubus call system board; cat /etc/openwrt_release'

# 3. 接口与 MAC
ssh [email protected] 'ip -br addr; cat /sys/class/net/eth0/address'

# 4. UBI 卷
ssh [email protected] 'ubinfo -a'

# 5. factory 卷与本地镜像比对(静态卷,可整卷 md5)
ssh [email protected] 'md5sum /dev/ubi0_3'
md5sum factory-1m.bin

# 6. fit 卷只比前 N 字节(动态卷会用 0xFF 补齐)
N=$(stat -c%s sysupgrade.itb)
ssh [email protected] "head -c $N /dev/ubi0_4 | md5sum"
md5sum sysupgrade.itb

/dev/ubi0_3、/dev/ubi0_4 是这台机器的卷号,换机器要先 ubinfo -a 确认编号,别照抄。

期望值:

检查项期望
curl http://192.168.1.1/200,跳转 cgi-bin/luci/
curl http://192.168.1.1/cgi-bin/luci403(未登录时的正常响应,403 body 就是登录页)
ubus call system boardmodel FiberHome HG5585F CT,board_name fiberhome,hg5585f-ct
系统PonWrt / OpenWrt,target airoha/an7581
br-lan192.168.1.1/24
WANpon0,dhcp
eth0 MAC等于 factory 里 0x2000 处的 MAC
SSHdropbear 可连,初始 root 空密码——立刻设密码
UBI 卷fip、ubootenv、ubootenv2、factory、fit、rootfs_data
/overlay挂在 rootfs_data 上,有剩余空间
WiFiphy0-ap0、phy1-ap0 存在,MAC 是按规则派生的

任一红旗下出现就回恢复模式,别继续:

  • MAC 是全零或者跟 factory 对不上;
  • factory 卷哈希和本地不一致;
  • fit 卷不存在或哈希对不上;
  • 型号报成了别的机器;
  • boot-production 之后又回 192.168.0.1。

十、换成自己的固件

PonWrt 只是「能跑」的跳板。换成自己编译的固件不用回 U-Boot,直接 sysupgrade:

1. LuCI → 系统 → 备份/刷写固件;

2. 上传同机型的 *-squashfs-sysupgrade.itb;

3. 取消勾选「保留配置」——跨固件保留配置是诡异故障的头号来源;

4. 等自动重启,重新用 192.168.1.1 进。

三条硬约束:固件必须为 fiberhome,hg5585f-ct 构建;分区布局必须一致(fip/factory/fit 卷名和大小对得上);刷完重新核对 MAC 和无线校准,WiFi 起不来先查 factory 卷,不要急着重刷。

十一、故障排查表

现象原因处理
/api/upload 返回里没有 upload_id用了 multipart改成原始字节 + application/octet-stream
任务返回 HTTP 409另有任务在跑等 busy=false 再提交
轮询发现 id 变了别的浏览器/agent 接管停,重新读状态,别假设自己跑过
flash 拒绝镜像FIT 型号不符或文件损坏核对型号,重新下载比对 MD5
ubi-rebuild 报 Skipping bad blockNAND 出厂坏块正常,记录偏移继续
mtd10 / mtd16 哈希和路由不一致可写分区在变正常,只要引导/factory 一致即可
恢复引导后一直没 DHCP网页还没起 / 旧租约等 60–90 秒,续租,或静态 192.168.0.2/24
192.168.0.1 不通但链路是通的设备还在启动或启动失败等;断电重启;启动失败会自动回恢复页
新系统 Web 返回 403LuCI 未登录正常,浏览器开 /cgi-bin/luci/
SSH 拒绝登录没设密码或客户端只认密钥新系统 root 空密码可用,先设密码
刷完 MAC 全零/不对factory 没写或写错重新 flash-board-data
25 MiB 固件上传超时客户端超时太短留 5–15 分钟,单次原始 POST
重启又回原厂系统没执行 boot-production 或缺 fit 卷回恢复页重跑 flash + boot-production
需要重新进恢复模式系统启动失败或按住复位U-Boot 会自动回 httpd dhcp 192.168.0.1

十二、救砖与回原厂

回恢复模式:断电重启,启动失败时 U-Boot 自动回 192.168.0.1;不行就按住复位再上电。

恢复顺序(从失败那一步重来,不要跳):

1. 192.168.0.1 通不通?不通查链路/DHCP/换 LAN 口,最后才是串口;

2. /api/device 型号是不是 HG5585F CT、ubi:true?不是就停,说明引导不对;

3. BL2 和 FIP 是否完好?先重跑 flash-bl2、flash-uboot,这两步可重复执行;

4. UBI 是否健康?重跑 ubi-rebuild → 板级数据 → FIP → 系统 → 启动。

回原厂:按 mtd0 → mtd16 顺序回写备份,并且恢复 bootflag(mtd1)。顺序错或漏 bootflag,机器起不来。 这一步没有 U-Boot 兜底,属于真正的最后手段。

最值钱的东西:17 个分区备份和 factory-1m.bin。别只存刷机那台电脑上,也别只存一份。

十三、八个常见误区

1. 开 Telnet 前不登录 8080 的 Web,接口全 404,误以为加密算法错了;

2. 在 80 端口的 LuCI 页面登录,以为已经登录,其实认证在 8080;

3. 备份时看到 mtd10/mtd16 哈希不一致就慌,其实那是可写分区;

4. 把 3 MiB 的 mtd13 写进 1 MiB 的 factory 卷,MAC、SN、校准全丢;

5. 首次安装跳过 ubi-rebuild,旧卷冲突,开机异常;

6. 跨机型套用 preloader / FIP,直接黑砖;

7. 用 nand-scrub / flash-all 去「修」失败,把可恢复变成不可恢复;

8. 刷完不验收 MAC 和 factory 卷,WiFi 不通又回头重刷,越刷越乱。

十四、这套流程能不能交给 agent 自动跑

可以,但前提是把「什么时候必须停」写进约束里。这次刷完,我把它整理成了两份东西:

  • 一份任务提示词:角色、目标、硬性约束、阶段 0–5、每阶段门禁、失败处理、最终报告模板;
  • 一个 Skill:SKILL.md + 4 份参考文档(API、分区布局、验收、故障排查)+ 4 个脚本(备份、重建 factory、U-Boot 客户端、原厂数据导出)。

门禁的设计是关键:不是「检查一下」,而是「把校验结果念出来,对不上就终止」。比如备份阶段的门禁是「mtd0–mtd9、mtd11–mtd15 的 MD5 必须与设备一致」,写成「检查备份完整性」,它就会自己脑补一个通过。

下载(提示词 + Skill + 脚本 + 现场记录,约 29 KB):

hg5585f-ct-agent-pack.7z

提示词和 Skill 的完整复盘,包括它当时怎么在没被授权的情况下把机器刷完的、哪三步其实很危险,写在另一篇:

我只让 AI 整理一份刷机教程,它把我光猫刷了

十五、一句话总结

免拆刷 AN7581 光猫,真正决定成败的不是 U-Boot 那六下点击,而是备份有没有校验、factory 有没有重建对。这两件事做扎实,剩下的是照顺序点;这两件事糊弄,后面全是玄学。

同平台其它机型的路线差异、文件清单,看这篇总览:

AN758x 光猫刷机总览:一套 Web U-Boot,14 款机型的刷机路线与文件清单