小米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一样稳如老狗。

相关链接


评论

  1. 桥洞哲学家 的头像
    桥洞哲学家

    这里还可以提供一个我也验证过的方法:我的是tr609版本,路由器先前用官方救砖工具刷成红米AX1800,后面想刷成openwrt,路由器手里又只有一个,就用CH340 ttl工具,连接路由器,用com登录,但是官方改版了uboot的启动方式,要用长按reset键15s以上开启恢复模式,然后再多次ctrl+c中断恢复,然后在重启uboot一瞬间,断电,重新插电,狂按enter,输入进入命令setenv uart_en 1, saveenv , boot,然后重新启动uboot,按enter,就会看见 Are You Ok,然后输入打开ssh的命令,由于ax1800是二次刷入的新固件,不是最开始的原版的定制固件,ssh的密码已不再是路由器贴纸上的密码了,要登录路由器管理界面,查看当前的SN码,然后在网上找到小米的ssh计算器,计算ssh密码,然后登录ssh,刷入pbboot或者breed

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

      这个好硬核呀~

      ttl我也只在搞光猫密码和刷星际魔盒的时候照着教程用过两次

  2. test 的头像
    test

    如果辅助路由器只是提供一个没有DHCP的热点,那是不是可以直接使用笔记本自带的热点功能。这样还可以省掉一个硬件要求。

  3. sowhat 的头像
    sowhat

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

  4. DD 的头像
    DD

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

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

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

  5. 李政严 的头像
    李政严

    接上文,我的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] 你的主机中的软件中止了一个已建立的连接。

  6. 郭源潮 的头像
    郭源潮

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

  7. 李政严 的头像
    李政严

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

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

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

    2. 李政严 的头像
      李政严

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

发表回复

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