逆向一台 MT6261 山寨功能机:BROM 协议、固件备份与刷机变砖实录
完整记录一台 MT6261 2G 功能机的逆向:从 USB 设备识别、AT 命令探测、BROM 下载协议逆向,到用 mtkclient 完成固件备份与写回,以及刷第三方固件变砖的教训。
逆向一台 MT6261 山寨功能机
一台 MT6261 2G 功能机(山寨机)的完整逆向:设备识别 → AT 命令探测 → BROM 协议逆向 → 固件备份/刷写 → 第三方固件分析。最终目标是搞清「这类老式功能机能不能刷机、能不能装软件、能不能跑自己的代码」。
本文隐去了设备 IMEI、硬件项目号等敏感信息。
设备识别:别信 lsusb 的名字
设备插上 USB,内核把它枚举成一个 GSM modem,串口挂到 ttyUSB4。lsusb 显示厂商 ID 0e8d(MediaTek Inc)。
第一个坑就在这:usb.ids 数据库把 0e8d:0003 标成 "MT6227 phone"。这是个误导性的通用名——0003 这个 PID 在功能机上同时被两种状态共用:
flowchart LR
USB[USB 0e8d:0003] -->|关机插电 ~2.8s| BROM[BROM 下载口]
USB -->|开机运行| AT[AT/modem 口]
BROM -->|之后跳转| MSC[0e8d:0002 充电壳]
真实芯片型号不能靠 lsusb,要靠 AT 命令读回,或者靠 mtkclient 的 chip 识别——最后确认是 MT6261(ARM7EJ-S 内核,Thumb 指令集)。
AT 命令:高度裁剪,EGMR 是核心
功能机固件的 AT 命令子集小得可怜。大部分标准 3GPP 命令直接返回 +CME ERROR: 100(不支持/被屏蔽)。能用的只有:AT、ATE0/1、ATV0/1、AT+CGMM、AT+CGMR、AT+CSQ、AT+COPS?、AT+CFUN(0/1/4),以及最关键的 AT+EGMR。
EGMR 是 MTK 的私有身份命令,既能读工厂身份段,又能改写 IMEI(改串号,敏感)。读出来的索引表大致是:
| index | 内容 |
|---|---|
| 0 | 芯片名(MT6261) |
| 3 | 软件版本 |
| 4 | 硬件项目/板号 |
| 7 / 10 | SIM1 / SIM2 的 IMEI |
| 8 | 资源版本(音频/图片/字体/字符串) |
这一段读下来,设备的「完整身份证」就到手了——芯片、软硬件版本、产线批次、IMEI 全都暴露在一个命令里。
BROM 协议逆向:老 MAUI bootloader 不按套路出牌
想备份固件,得走 BROM(Boot ROM)下载口。mtkclient 是 MTK 刷机/备份的标准工具,但它主要面向智能机(MT65xx+),对 MT6261 这种老式 MAUI bootloader 有系统性不兼容。
第一个坎:BROM 窗口只有 2.8 秒
关机插 USB,设备先进 BROM(0e8d:0003),但只停留约 2.8 秒,然后就跳去充电壳(0e8d:0002)或自动开机。按键没法延长这个窗口。握手代码慢了半拍就抓不到。
第二个坎:握手后的命令集对不上
mtkclient 握手成功后,会发 GET_HW_CODE(0xFD) 去要硬件码。但 MT6261 的 BROM 只 echo 这个字节、根本不返回 hwcode,于是 rdword() 干等,直到 BROM 自己超时重启。
用独立 pyusb 脚本逐个命令字节探过去,才摸清真实命令集:
| 命令 | 响应 |
|---|---|
简单 echo(0xFE/0xFD/0xFC/0xBF/…) |
立即回显 |
0xFF(GET_VERSION) |
返回 05 |
0xA2(READ16_A2) |
唯一可用的读内存命令 |
0xD0/0xD1(READ16/READ32) |
无响应(不支持) |
关键结论:0xA2 是全班唯一能读内存的命令,hwcode 可以从内存地址 0x80000008 用 read_a2 读出来,根本不用 GET_HW_CODE。
改造 mtkclient:7 处代码修改
摸清协议后,对 mtkclient 打了 7 处补丁,让它能完整备份 + 写回 MT6261:
| 文件 | 修改 | 解决 |
|---|---|---|
Port.py echo() |
显式超时 read | 握手后 EIO |
Port.py run_handshake() |
跳过 CDC 控制传输 | 端点状态被干扰 |
Port.py 握手循环 |
sleep 0.3/0.1 → 0.05 | 抢 2.8s 窗口 |
mtk_preloader.py |
跳过 rdword() |
GET_HW_CODE 不返回 |
mtk_preloader.py |
read32() list 类型保护 |
TypeError |
dalegacy_lib.py |
新增 nor_write_data() |
补 NOR 写分支 |
mtk_main.py |
跳过 crasher | 功能机已 BROM |
改完后 rf(读全 flash)成功读出 4MB 原厂固件,wf(写全 flash)也补上了对称的 NOR 写路径(WRITE_CMD 0xD5,擦除块 16KB 对齐)。
第三方固件分析:硬件兼容,但都装不了软件
网上找了 4 个 MT6261 的第三方固件想刷,逐个做了二进制对比——LCD 驱动、运行时、硬件配置:
| 固件 | LCD 驱动 | 应用运行时 |
|---|---|---|
| 5Star GR7 | GC9304, ST7789V | ❌ 无 MRE |
| Symphony B17 | GC9102D, ILI9163C, ST7735S | ❌ 无 MRE |
| iSmart IS-203i | GC9312 | ❌ 无 MRE |
| Karbonn E3 | GC9303, ILI9341, ST7789S | ❌ 无 MRE |
结论很明确:
- 硬件大概率兼容——4 个固件都是同一个「11C」参考设计,且每个都内置多款 LCD 驱动自动检测
- 但全都没有 MRE 应用运行时——刷了也装不了软件,只是换个品牌界面
- 这些固件多是海外版(英国/印度),射频频段和国行不同,刷了很可能插卡没信号
刷机变砖:bootloader 前 16KB 的教训
最终还是刷了 5Star(4MB 完整镜像,最方便)。刷完设备半砖了——屏幕不亮。
复盘根因:整片 wf 写入时,flash 前 16KB(bootloader)被第三方固件的 bootloader 覆盖。之后想刷回原厂备份,DA(下载代理)在读取 flash 分区信息阶段就崩溃重启,因为 bootloader 区布局已经对不上。
但半砖不是死刑:BROM 入口完好 + 原厂完整备份完好,两条命都在。恢复只是时间问题——多试几次碰 DA 稳定、让 DA 跳过 bootloader 区校验、或者丢给 Windows 下的 MTK Flash Tool 整片刷回。
这场事故换来一条铁律:刷机前必须完整备份。这次能全身而退,靠的就是先 rf 出来的那 4MB。
总结
这个项目最大的收获不是「成功刷机」,而是把整条链路打通了:
- ✅ 设备识别:别信 lsusb,用 EGMR / dacode 确认芯片
- ✅ AT 命令:功能机高度裁剪,EGMR 是身份与 IMEI 的核心入口
- ✅ BROM 协议:
0xA2唯一读内存、窗口 2.8s、命令集与智能机不同 - ✅ 工具链改造:7 处补丁让 mtkclient 支持 MT6261 备份 + NOR 写回
- ❌ 装软件:固件无 MRE,刷第三方固件也装不了应用,唯一路径是 BROM 代码注入
- ⚠️ 教训:刷机前必须完整备份,bootloader 前 16KB 是变砖高危区