SyriusM/rtl8188eus-efuse-tool
GitHub: SyriusM/rtl8188eus-efuse-tool
一款通过 pyusb 绕过内核驱动、直接读写 Realtek RTL8188EUS WiFi 适配器 OTP EFuse 存储的用户空间 CLI 工具,附带完善的备份验证与审计机制。
Stars: 1 | Forks: 0
# rtl8188eus-efuse-tool
用于读取和烧录 Realtek RTL8188EUS USB WiFi 适配器 EFuse 内存 的用户空间 CLI 工具。
**状态**:WIP MVP (2026-05-11)。优先实现读取/转储功能,写入功能后续跟进。
## 为什么会有这个项目
- `flashrom` 仅支持 SPI flash,不支持 RTL 内部 EFuse
- 厂商驱动 (`8188eu-dkms`) 将 `/proc/net/8188eu/wlan_mon/efuse_map` 暴露为**只读显示**
- 制造商的 MP 工具仅限 Windows 且非开源 (OSS)
- **小众场景**:提供类似 `flashrom` 的干净 CLI,支持 `dump`/`decode`/`write`/`verify`,但专为 I2C/EFuse 和直接 USB 通信设计
## 架构
```
[CLI argparse] → [pyusb device handle] → [Realtek vendor requests]
↓
[REG_EFUSE_ACCESS=0x69 unlock]
↓
[byte-by-byte EFUSE_CTRL reads]
↓
[decode logical layout]
```
绕过内核驱动——操作期间需要解除绑定 (`unbind`) `8188eu` 或 `rtl8xxxu`。
## 支持的芯片
- RTL8188EUS (`0bda:8179`) — 主要支持
- RTL8188ETV (`0bda:0179`) — 待测试
## 使用示例
### 只读
```
# 识别 dongle
sudo .venv/bin/python src/efuse_tool.py info
# Dump 逻辑 512-byte map (解压后,类似于 kernel /proc 视图)
sudo .venv/bin/python src/efuse_tool.py dump -o my-efuse.bin
# Dump 物理 256-byte map (带有 PG packets 的原始 cells)
sudo .venv/bin/python src/efuse_tool.py dump --raw -o my-efuse-raw.bin
# Human-readable decode (离线,适用于 .bin file)
.venv/bin/python src/efuse_tool.py decode my-efuse.bin
# 显示物理 map 中的第一个 0xFF (下一次写入指针)
sudo .venv/bin/python src/efuse_tool.py find-empty
```
### 比较
```
# 验证 backup 是否与当前 chip 匹配
sudo .venv/bin/python src/efuse_tool.py verify my-efuse.bin
# 带有 OTP burnability 的详细逐 byte diff
sudo .venv/bin/python src/efuse_tool.py diff modified-target.bin
```
### 写入 (破坏性操作,OTP —— 一次性可编程!)
```
# 单 byte burn (POC;--dry-run 显示计划,--yes 跳过确认)
sudo .venv/bin/python src/efuse_tool.py write-byte --addr 0x8F --value 0xAA --dry-run
sudo .venv/bin/python src/efuse_tool.py write-byte --addr 0x8F --value 0xAA --yes
# 基于完整文件的写入 (增量 PG packet 追加)
sudo .venv/bin/python src/efuse_tool.py write modified-target.bin --dry-run
sudo .venv/bin/python src/efuse_tool.py write modified-target.bin --yes
```
所有破坏性操作:
- 会在 `backups/auto-prewrite-*-.bin` 中自动创建物理备份
- 在烧录前打印清晰的操作计划
- 烧录后执行字节级 + 逻辑级的验证
- 保存烧录后的快照
- 记录到 `ops_log.jsonl` (JSONL 审计日志)
## 源码逆向工程
基于 `gglluukk/rtl8188eus` v5.3.9 分支 (内核 6.x/7.0.x 补丁):
- `hal/rtl8188e/rtl8188e_hal_init.c` — `efuse_read_phymap_from_txpktbuf`
- `core/efuse/rtw_efuse.c` — 通用 EFuse 访问
- `include/rtl8188e_spec.h` — 寄存器定义
关键寄存器:
- `REG_EFUSE_ACCESS = 0x00CF` — 厂商锁 (写入 `0x69` 解锁)
- `EFUSE_CTRL` — 读/写控制
## 构建 / 开发
```
cd ~/Projekty/rtl8188eus-efuse-tool
python -m venv .venv
source .venv/bin/activate.fish
pip install -r requirements.txt
sudo python src/efuse_tool.py info # needs CAP_SYS_RAWIO + unbound driver
```
## 为什么测试在这里很重要 —— 一个真实的故事 (2026-05-11)
在最初的开发过程中,测试套件发现了一个**隐蔽的编码器 Bug**,如果
在进行首次真实烧录,该 Bug 本会永久使目标芯片变砖。
Bug 原因:`build_pg_packet()` 在生成扩展 (2 字节) 头时,颠倒了
段索引的高 3 位和低 3 位。Realtek 编码器规范如下:
```
pg_header = ((offset & 0x07) << 5) | 0x0F; // byte1: section[2:0] in [7:5]
pg_header = ((offset & 0x78) << 1) | word_en; // byte2: section[6:3] in [7:4]
```
我最初的 Python 移植版对 byte1 使用了 `(section >> 3) & 0x07` —— 方向反了。
针对段 26 的 MAC 字节 `write` 操作实际上会写入到
段 27 —— 覆盖了 OTP 单元中一个*不同*的逻辑区域,并且是**不可逆的**。
测试 `test_extended_packet_section_26` 重现了 Pentagram 芯片
真实的物理头模式 (对于所有字都被使用的段 26,byte1=0x4F + byte2=0x30)。
它在首次运行时就失败了,在任何真实烧录尝试之前暴露了这个 Bug。
修复方法只是交换一行代码;测试现在全部通过 (green)。
**教训**:针对 OTP / 单向内存的位操作编码器需要
使用已知良好的参考数据进行往返测试。在测试套件上投入 30 分钟
防止了永久性的硬件损坏(以及相关的
“我该怎么向自己解释”的挫败感)。
## 恢复 —— 烧录后如果芯片停止枚举该怎么办
EFuse 是**一次性可编程**的。一次搞砸的烧录可能会使适配器
无法加载固件或报告损坏的 USB 描述符。步骤如下:
### 1. 诊断
```
lsusb | grep 0bda:8179 # is the device still on USB bus?
dmesg | tail -30 # what does kernel say?
```
常见的内核消息及其含义:
| 消息 | 原因 |
|---|---|
| `Fatal - failed to parse EFuse` | EFuse 内容无法解析(PG 包序列已损坏)。 |
| `LLT table init failed` | RF 子系统无法加载校准数据;通常是暂时的(USB 电源波动),但也可能与 EFuse 相关。 |
| 完全没有 `usb 1-X: New USB device` | 适配器未枚举 —— 可能是电源、线缆问题,或者是写入后出现的 `IS_VENDOR_8188E_I_CUT_SERIES` 异常。 |
### 2. 尝试恢复
一个错误的包有时可以通过追加一个具有相同段索引和正确值的纠正包来“遮蔽”。
EFuse 解析器按字采用“后写入者胜出”规则,因此:
```
# 识别损坏的 section
sudo .venv/bin/python src/efuse_tool.py dump -o broken-state.bin
sudo .venv/bin/python src/efuse_tool.py decode broken-state.bin
# 在 hex editor 中编辑 broken-state.bin 以恢复原始值
# (使用 backups/auto-prewrite-*.bin 中的 backup 作为参考!)
xxd backups/auto-prewrite-byte-0x8F-20260511-184958.bin | head
# 应用已修正的文件
sudo .venv/bin/python src/efuse_tool.py write corrected.bin --dry-run
sudo .venv/bin/python src/efuse_tool.py write corrected.bin --yes
```
### 3. 如果恢复失败:物理限制
如果芯片已损坏到无法通过软件恢复:
- 该芯片约 3 美元(在 Allegro 上为 8-15 PLN)。将其视为已消耗的研发预算。
- 保留损坏的适配器以供检查 / PCB 拆解利用(天线 RP-SMA,USB 连接器)。
- 在你的库存(`~/lab/inventory/`)中记录一条“Cmentarz”(墓地)条目。
### 4. 预防清单(在执行任何 `write` 或 `write-byte` 之前)
- [ ] 已在本次会话中获取最新的 `backups/auto-prewrite-*.bin`
- [ ] 已检查 `--dry-run` 输出以确认确切的操作
- [ ] 明确哪些位将翻转 1→0 以及在哪个物理地址上
- [ ] 已确认烧录目标位于**全新的 0xFF 单元范围内**(使用 `find-empty`)
- [ ] 已在 `ops_log.jsonl` 中记录操作理由
## 审计日志
每个操作 (info/dump/write/verify) 都会在
仓库根目录下的 `ops_log.jsonl` 中追加一条 JSONL 记录。格式如下:
```
{"ts":"2026-05-11T19:35:22","op":"write_byte_end","status":"ok","pid":12345,
"addr":"0x8F","burned":"0xAA","verified":true,"logical_diffs":0,
"backup":"backups/auto-prewrite-byte-0x8F-20260511-193512.bin",
"post_snap":"backups/postwrite-byte-0x8F-20260511-193515.bin"}
```
用于取证分析:`jq '.' ops_log.jsonl | less`。
## 免责声明
本工具旨在用于**对你自己拥有的硬件进行安全研究、教育和逆向工程**。
- **不提供任何形式的保证**,无论是明示的还是暗示的 —— 请参阅 GPL-3.0 第 15-17 条。
- 用户有责任遵守**当地法规**(电信法、RF 发射、数据保护)。
- OTP 写入操作是**物理不可逆的** —— 熔丝在硅片层面被单向烧断。请使用你能够接受损失的芯片进行测试。
- 请勿对你不拥有或未获得明确测试授权的硬件使用本工具。
- 作者对因使用本软件而导致的误用、硬件损坏、违规或数据丢失不承担任何责任。
合法的主要用例包括:学习 EFuse OTP 语义的工作原理、厂商协议的可重现逆向工程、为对 Realtek 硬件的 FOSS 认知做出贡献,以及恢复或鉴定你拥有的芯片。该工具刻意包含了安全设计特性(自动备份、审计日志、健全性检查、字节+逻辑双重验证),以反映这些预期的用例。
## 许可证
GPL-3.0 (与其逆向工程来源的 8188eu 源码保持一致)
## 作者
Mateusz Wala (syriusm), 2026
标签:EFuse, Libusb, Linux内核绕过, OTP, Pytest, PyUSB, Realtek, RTL8188EUS, USB外设, Userspace, WiFi适配器, 二进制分析, 云安全运维, 云资产清单, 固件提取, 安全规则引擎, 底层硬件操作, 硬件安全, 硬件黑客, 逆向工具, 逆向工程, 驱动解绑