rebehzat/j700f-s310-modem-unlock

GitHub: rebehzat/j700f-s310-modem-unlock

该项目是对三星 Galaxy J7 (SM-J700F) Shannon S310 基带的完整逆向工程,旨在解决因 NV 数据损坏导致的永久网络锁死问题,并提供了自定义基带引导守护进程等底层解锁工具。

Stars: 0 | Forks: 0

# SM-J700F Shannon S310 基带解锁 [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Status: Complete](https://img.shields.io/badge/Status-Unlocked-brightgreen)]() [![Architecture](https://img.shields.io/badge/Arch-ARMv7--A%20%2F%20Thumb2-blue)]() 针对三星 Galaxy J7 (SM-J700F) Shannon S310 蜂窝基带的完整逆向工程、自定义固件开发及网络解锁。本仓库记录了从初始诊断、多次失败尝试到最终成功方案的完整过程。 ## 目录 - [背景](#background) - [硬件与软件环境](#hardware--software-environment) - [攻击面](#attack-surface) - [尝试的方案](#approaches-attempted) - [1. 分区级攻击](#1-partition-level-attacks) - [2. DIAG 协议 NV 篡改](#2-diag-protocol-nv-manipulation) - [3. AT 命令暴力破解](#3-at-command-brute-force) - [4. 固件修补(自定义 CBD)](#4-firmware-patching-custom-cbd) - [5. 捐赠者 EFS/NV + IMEI 修复](#5-donor-efsnv--imei-repair-the-solution) - [自定义工具](#custom-tools) - [qnd_cbd — 自定义启动守护进程](#qnd_cbd--custom-boot-daemon) - [rfs_daemon — RFS 文件服务器](#rfs_daemon--rfs-file-server) - [diag_nv — DIAG NV 读写](#diag_nv--diag-nv-readwrite) - [固件分析](#firmware-analysis) - [TOC 结构](#toc-structure) - [IDEX 注册表](#idex-registry) - [CME 错误表](#cme-error-table) - [NS_SIMLOCK 消息分发](#ns_simlock-message-dispatch) - [我们的固件补丁](#our-firmware-patch) - [未知事项与后续工作](#unknowns--future-work) - [参考资料](#references) - [许可证](#license) ## 背景 SM-J700F(代号 `j7elte`)是 2015 年款的三星 Galaxy J7,由 Exynos 7580 SoC 驱动,并集成了 Shannon S310 蜂窝基带处理器 (CP)。该设备出厂时为解锁状态(INS/印度销售代码,`SM-J700FZDDINS`),但在安装 LineageOS 17.1 期间,由于 NV(非易失性存储器)数据损坏,导致其被永久网络锁定。 **症状:** - RIL 报告 `NETWORK_LOCKED,ABSENT` - `CPIN: READY`,但 `CPWD=?` 仅显示 P2 出厂锁 - `CREG: 0,3` — 网络注册被拒绝 - 即使完全擦除分区(EFS, CPEFS, m9kefs, PERSISTENT, CARRIER),锁定状态依然存在 - 测试了三种不同的 CP 固件变体 — 均显示相同的锁定状态 **根本原因:** Shannon S310 基带将网络个性化状态存储在 NV 内存中经过签名的 IMEI 证书链中。当刷机过程中 NV 数据损坏时,调制解调器回退到了包含激活状态个性化锁的硬编码默认值,并且 IMEI 证书失效。调制解调器的安全架构阻止其接受未经签名/未认证的 NV 数据。 ## 硬件与软件环境 | 组件 | 规格 | |-----------|--------------| | 设备 | SM-J700F(三星 Galaxy J7 2015)| | SoC | Exynos 7580 (Cortex-A53 ×8) | | 基带 | Shannon S310 (ARM Cortex-R) | | Bootloader | J700FXXU4BRA1(已解锁,保修位=1)| | CP 固件 | J700FXXU4BQC3 (XSG), J700FXXU4BRG1 (INS), BQC3 (TUR) | | Android | LineageOS 17.1 (Android 10) / Stock 6.0.1 | | Recovery | TWRP 3.7.0-9 | | Root | Magisk v30.7 | ## 攻击面 Shannon S310 调制解调器向 Linux 内核暴露了多个接口: | 接口 | 设备节点 | 用途 | 可访问性 | |-----------|------------|---------|------------| | 启动控制 | `/dev/umts_boot0` | 固件上传、安全握手、状态控制 | ioctl, root | | AT 命令 | `/dev/umts_router` | 标准 Hayes AT 命令集 | read/write, radio group | | DIAG | `/dev/umts_dm0` | 兼容 Qualcomm 的诊断协议,NV 读写 | read/write, radio group | | RFS | `/dev/umts_rfs0` | 远程文件系统(SIPC 协议)— 调制解调器请求 EFS 文件 | read/write, radio group | | IPC | `/dev/umts_ipc0` | 核心间通信 | read/write, radio group | | CSD | `/dev/umts_csd` | 核心/系统转储 | read, radio group | | RAM Dump | `/dev/umts_ramdump0` | 崩溃转储提取 | read, radio group | ## 尝试的方案 ### 1. 分区级攻击 **假设:** 擦除所有与调制解调器相关的分区将迫使 CP 从出厂默认值重建 NV。 **方法:** ``` for part in EFS CPEFS m9kefs1 m9kefs2 m9kefs3 CARRIER PERSISTENT; do dd if=/dev/zero of=/dev/block/platform/13540000.dwmmc0/by-name/$part done ``` **结果:失败。** 调制解调器从 MAIN 固件段内 IDEX 注册表 blob 中的硬编码默认值重建了 NV。这些默认值包含了处于激活状态的个性化锁数据。该锁定不仅仅存在于可写分区中,它还存在于固件镜像本身。 ### 2. DIAG 协议 NV 篡改 **假设:** 通过兼容 Qualcomm 的 DIAG 接口,向已知的 三星 NV 项目 550-554(网络锁代码)写入零,将禁用该锁定。 **方法:** ``` // DIAG packet format // magic(0x75) + cmd(0x27) + subcmd(0x0039) + len + data + crc16 diag_send(fd, 0x27, 0x0039, payload); // NV_WRITE ``` **结果:部分失败。** 对于 0-2000 的项目,DIAG NV 读取成功(识别出 256 个活动项目,16 个大型加密项目)。写入操作因 `EPERM` 失败 — 当处于锁定安全状态时,调制解调器会拒绝 NV 修改。NV 安全状态本身在加密上与 IMEI 证书绑定。 ### 3. AT 命令暴力破解 **假设:** 可以通过标准 AT 命令发送正确的 NCK(网络控制密钥)来清除网络锁。 **方法:** 通过 `/dev/umts_router` 测试了 15 个常见的默认解锁码: ``` AT+CPIN= AT+CPWD="PN",, AT+CLCK="PN",0, ``` **结果:失败。** 所有代码均被拒绝。调制解调器处于 PUK 阻塞状态(`CPWD=?` 仅显示 P2),这意味着 NCK 计数器已被损坏的 NV 状态耗尽。 ### 4. 固件修补(自定义 CBD) **假设:** 在调制解调器的 MAIN 固件中找到个性化检查函数并将其替换为 NOP,然后使用绕过三星签名验证的自定义启动守护进程来引导修补后的固件。 **发现过程:** 1. 在 VA `0x4007D5AC` 和 `0x41EED070` 处定位到了 `usim_LockApps.c` 源码引用 2. 在 VA `0x412B0F38` 处找到了 CME 错误表,该表将错误代码 41-48 映射到个性化错误字符串 3. 在 VA `0x409B5D2C` 处识别出 `NS_SIMLOCK_ENABLE_REQ` 消息分发 4. 将消息处理程序追踪至 VA `0x409B5DBA`(Thumb 代码) 5. 在 VA `0x409B5DD0` 处找到了单指令修补点 **补丁:** ``` Offset: 0x009A77F0 in modem.bin Original: 0x7820 = ldrb r0, [r4] ; read lock enable flag Patched: 0x2000 = movs r0, #0 ; always skip lock enable ``` **自定义 CBD:** 构建了 `qnd_cbd.c` — 这是一个极简的用户空间启动守护进程,它: - 解析 TOC 标头以定位 BOOT/MAIN/NV 段 - 通过 `ioctl(0x6f40)` (send_chunk) 上传固件 - 通过忽略其返回值来跳过 `security_request` - 打开 `/dev/umts_rfs0` 和 `/dev/umts_ipc0` 进行 RFS 通信 **结果:部分成功。** 修补后的固件通过自定义 CBD 成功启动。调制解调器达到了状态 3 (BOOTING),并且手机短暂接收到了一条短信 — 证明该固件补丁有效。然而,调制解调器从未进展到状态 4 (ONLINE),因为自定义 CBD 的 RFS 实现没有处理调制解调器所需的所有文件操作(目录创建、向 /efs 写入文件)。 **为何这很重要:** 这证明了只需更改一条指令即可绕过锁定。如果 RFS 守护进程补充了完整的文件操作支持,这将成为一种 100% 纯软件的解锁方案。 ### 5. 捐赠者 EFS/NV + IMEI 修复 + NCK 计算(最终解决方案) **假设:** 来自另一台正常工作/已解锁的 J700F 的完整 EFS + NV + 证书集,结合通过 Samsung Tool PRO 进行的适当 IMEI 修复和 NCK 计算,将解决证书链问题并提供正确的解锁码。 **关于解锁码的说明:** NCK(网络控制密钥)`40629636` 是由 Samsung Tool PRO 根据设备的 IMEI **计算得出的**。NCK 是使用在 Z3X 硬件内运行的三星专有算法从 IMEI 派生出来的。如果没有 Z3X 盒子,就无法计算出正确的 NCK — 这就是为什么方案 #1-4 本身永远无法完全成功的原因。 **方法:** 1. 从已解锁的 J700F(AOFJ 固件)获取了捐赠者的 `efs.img` (8.9MB)、`nv_data.bin` (2MB) 和 `.cert` 文件 2. 通过 TWRP 将捐赠者的 EFS 刷入 `/dev/block/mmcblk0p3` 3. 启动 Stock ROM — 调制解调器根据捐赠者的结构重建了 NV 数据 4. 使用 Samsung Tool PRO (Z3X) 执行了以下操作: - 修复 IMEI(将原始 IMEI 恢复至捐赠者的 NV 结构中) - 重新生成 IMEI 证书(在盒子内部使用三星的私钥对 IMEI 进行签名) - **计算出 NCK 解锁码** (`40629636`) 5. 在 Stock ROM 上输入 NCK 码 — 网络锁立即被清除 6. 手机注册网络(Turkcell 28603, LTE)— `gsm.sim.state` 变为 `READY` 7. 重启至 TWRP,擦除除 EFS 之外的所有内容,刷入 LineageOS 17.1 + Magisk **结果:成功。** 来自捐赠设备的合法 EFS/NV 结构、适当的 IMEI 证书修复,**加上由 Samsung Tool PRO 计算出的 NCK 码**,共同彻底消除了网络锁。调制解调器接受了捐赠者的 NV 格式,并使用我们的 IMEI 进行了重建,证书链合法,计算出的 NCK 也被接受。 **核心洞察:** Shannon S310 上的网络锁从根本上说是一个 IMEI 证书问题,而不是基于标志位的开关。调制解调器在加密层面上验证 IMEI 是否与其签名证书匹配。NCK 是使用三星专有算法从 IMEI 派生出来的 — 如果没有 Z3X 硬件,就无法计算出正确的解锁码。正是这种强依赖性,使得如果不从 Z3X 盒子中提取三星的私钥,或者不完成固件补丁 + RFS 方案,就根本无法实现纯软件解锁。 ## 自定义工具 ### qnd_cbd — 自定义启动守护进程 `cbd/qnd_cbd.c` — 三星 `cpboot-daemon` 的极简替代品,可绕过加密签名检查来启动调制解调器固件。 **功能:** - 用于发现 BOOT/MAIN/NV 段的 TOC 标头解析器 - 通过 `ioctl(0x6f40)` 进行分块固件上传 - 安全请求绕过 (`ioctl(0x6f53)`) - 具备 SIPC 协议处理功能的内置 RFS 守护进程 - 支持 OPEN, CLOSE, READ, STAT 和 WRITE (ack) RFS 操作 **ioctl 参考:** | ioctl | 值 | 用途 | |-------|-------|---------| | modem_reset | `0x6f21` | 重置调制解调器 CP | | security_request | `0x6f53` | 检查固件签名(对于未签名固件返回 -EPERM,此处被忽略)| | send_chunk | `0x6f40` | 上传固件段 | | modem_on | `0x6f19` | 开启调制解调器电源 | |_boot_on | `0x6f22` | 启动引导序列 | | modem_dl_start | `0x6f28` | 开始下载模式 | | modem_boot_off | `0x6f23` | 完成引导,释放重置状态 | | get_state | `0x6f27` | 读取调制解调器状态 (0-8) | **构建:** ``` arm-linux-gnueabihf-gcc -static -o qnd_cbd cbd/qnd_cbd.c -O2 ``` **用法:** ``` # 启动带有 custom firmware 的 modem ./qnd_cbd /dev/block/platform/13540000.dwmmc0/by-name/RADIO /efs/nv_data.bin # 替换原厂 cbd (重启后持久保留 — stock ROM) mount -o remount,rw / cp qnd_cbd /sbin/cbd # or /vendor/bin/cbd on LineageOS ``` ### rfs_daemon — RFS 文件服务器 `cbd/rfs_daemon.c` — 独立的守护进程,可附加到已启动的调制解调器并通过 SIPC 提供文件请求服务。在调制解调器由原厂 CBD 启动但需要外部 RFS 处理程序时非常有用。 **SIPC RFS 协议:** ``` Packet Header (7 bytes): uint16_t len // total packet length uint8_t msg_seq // message sequence uint8_t ack_seq // acknowledgment sequence uint8_t main_cmd // 0x01 = RFS service uint8_t sub_cmd // operation code uint8_t cmd_type // command type Sub-commands (main_cmd = 0x01): 0x01 = OPEN (path -> status + handle) 0x02 = CLOSE (handle -> status) 0x03 = READ (handle, offset, length -> status + data) 0x04 = WRITE (data -> status, ack only) 0x06 = STAT (path -> status + mode + size + mtime) ``` ### diag_nv — DIAG NV 读写 `scripts/diag_nv.c` — 通过 `/dev/umts_dm0` 上兼容 Qualcomm 的 DIAG 接口读写 NV 项目的工具。 **DIAG 数据包格式:** ``` Byte 0: 0x75 (magic/start) Bytes 1-2: command (uint16 LE, 0x27 = DIAG_EXT) Bytes 3-4: subcommand (uint16 LE, 0x0038 = NV_READ, 0x0039 = NV_WRITE) Bytes 5-6: payload length (uint16 LE) Bytes 7+: payload Last 2: CRC16 (Modbus polynomial 0xA001) ``` **构建:** ``` arm-linux-gnueabihf-gcc -static -o diag_nv scripts/diag_nv.c -O2 ``` ## 固件分析 ### TOC 结构 调制解调器固件(`modem.bin`, 34MB)采用 三星 的 TOC(目录)格式: ``` Offset 0x00: magic "TOC\0" (4 bytes) Offset 0x10: entry count Offset 0x20: BOOT entry { name[12], offset=0x200, load=0x40000000, size=0x1820, crc, id } Offset 0x40: MAIN entry { name[12], offset=0x1A20, load=0x40010000, size=0x213BB88, crc, id } Offset 0x60: NV entry { name[12], offset=0x0, load=0x44900000, size=0x100000, crc, id } ``` - BOOT 在 Cortex-R CP 核心上运行,负责初始硬件初始化 - MAIN 包含完整的协议栈(GSM/WCDMA/LTE, USIM, 安全) - NV 是一个 1MB 的 RAM 区域,加载了来自 EFS 的非易失性数据 ### IDEX 注册表 位于 MAIN 段内的偏移量 `0x013BB824` 处。包含用作 EFS 为空/损坏时默认值的 NV 项目名称定义: | 偏移量 | 项目名称 | 用途 | |--------|-----------|---------| | `0x013E58EC` | `CAL.Common.USIM_LOCK_CODE_ENC` | 加密的 USIM 锁定代码 | | `0x013E5934` | `CAL.Common.CP_LOCK_CODE_ENC` | 加码的企业锁定代码 | | `0x013E5974` | `CAL.Common.SP_LOCK_CODE_ENC` | 加密的服务提供商锁 | | `0x013E59B4` | `CAL.Common.SUBSET_LOCK_CODE_ENC` | 加密的子集锁定代码 | | `0x013E59FC` | `CAL.Common.NW_LOCK_CODE_ENC` | 加密的网络锁定代码 | | `0x013E71E4` | `CAL.Common.LOCK_CODE_FLAG` | 锁定启用/禁用标志 | | `0x013E7200` | `CAL.Common.SECURE_LOCK_CODE_FLAG` | 安全(加密)锁定标志 | | `0x013E5B9C` | `CAL.Common.USIM_LOCK_KEY_ENC` | 加密的 USIM 锁定密钥 | | `0x013E5CA8` | `CAL.Common.NW_LOCK_KEY_ENC` | 加密的网络锁定密钥 | | `0x013E5CE8` | `CAL.Common.MASTER_KEY_ENC` | 主加密密钥 | ### CME 错误表 位于 VA `0x412B0F38` 处,包含 39 个将错误代码映射到 GSM/3GPP 标准错误字符串的条目。个性化错误跨越了代码 41-48: | 代码 | 字符串 | |------|--------| | 41 | network personalization PIN required | | 42 | network personalization PUK required | | 43 | network subset personalization PIN required | | 44 | network subset personalization PUK required | | 45 | service provider personalization PIN required | | 46 | service provider personalization PUK required | | 47 | corporate personalization PIN required | | 48 | corporate personalization PUK required | 每个条目都是一个 8 字节的结构体:`{ uint32 string_ptr, uint32 error_code }` ### NS_SIMLOCK 消息分发 Nucleus RTOS 消息分发系统处理个性化消息: - **消息名称:** `NS_SIMLOCK_ENABLE_REQ`,位于 VA `0x409B5D2C` - **消息 ID:** `0x00041662` - **处理函数:** VA `0x409B5DBA` (Thumb 代码) - **注册表:** VA `0x409B5CE0` ### 我们的固件补丁 ``` Function: NS_SIMLOCK enable message handler Location: VA 0x409B5DBA (Thumb mode) Patch at: VA 0x409B5DD0 → modem.bin offset 0x009A77F0 Disassembly (original): 0x409B5DBA: push.w {r0-r8, sb, sl, fp, lr} 0x409B5DC0: ldr r4, [pc, #0x3d8] ; load flag pointer 0x409B5DD0: ldrb r0, [r4] ; read lock enable flag 0x409B5DD2: cbz r0, #0x409B5DF0 ; if flag==0: skip 0x409B5DD4: adds r0, r0, #1 ; flag++ 0x409B5DDC: orr.w r0, r8, r0, lsl #18 ; combine with MSG_ID 0x409B5DEA: bl #0x40014ED4 ; send NS_SIMLOCK_ENABLE Disassembly (patched): 0x409B5DD0: movs r0, #0 ; always zero → skip 0x409B5DD2: cbz r0, #0x409B5DF0 ; always taken Hex: 0x7820 → 0x2000 (2 bytes changed) ``` ### 调制解调器状态机 ``` STATE_OFFLINE = 0 → modem powered off STATE_CRASH_RESET = 1 → crash recovery STATE_CRASH_EXIT = 2 → crash dump ready STATE_BOOTING = 3 → firmware uploaded, initializing STATE_ONLINE = 4 → fully operational, SIM accessible STATE_NV_REBUILDING = 5 → NV data reconstruction STATE_LOADER_DONE = 6 → bootloader phase complete STATE_SIM_ATTACH = 7 → SIM card attached STATE_SIM_DETACH = 8 → SIM card removed ``` 调制解调器必须达到 STATE_ONLINE (4),RIL 才能检测到 SIM 卡并尝试注册网络。 ## 构建 ``` # 交叉编译 ARMv7-A (static) arm-linux-gnueabihf-gcc -static -o qnd_cbd cbd/qnd_cbd.c -O2 arm-linux-gnueabihf-gcc -static -o rfs_daemon cbd/rfs_daemon.c -O2 arm-linux-gnueabihf-gcc -static -o diag_nv scripts/diag_nv.c -O2 ``` ## 分区参考 ``` # Samsung Galaxy J7 (SM-J700F) 分区布局 — mmcblk0 p3 = EFS (20MB, NV data, IMEI, certificates) p4 = CPEFS (8MB, NV core backup .nv_core.bak) p5 = m9kefs1 (4MB) p6 = m9kefs2 (4MB) p7 = m9kefs3 (4MB) p8 = CARRIER (1MB, carrier-specific data) p10 = BOOT (32MB, kernel + ramdisk) p11 = RECOVERY (32MB, recovery ramdisk) p13 = CDMA-RADIO (4MB, legacy CDMA firmware - unused on GSM model) p14 = RADIO (92MB, modem.bin CP firmware) p17 = PERSISTENT (512KB, DRK — Device Root Key) p20 = SYSTEM (2.1GB) p25 = USERDATA (~4GB) ``` **黄金备份**(成功解锁后): ``` for p in 3 4 5 6 7 8 14 17; do dd if=/dev/block/mmcblk0p$p of=backup_p$p.img bs=1048576 done ``` ## 未知事项与后续工作 1. **三星 IMEI 私钥** — 位于 Z3X/Samsung Tool PRO 硬件内部。如果被提取,将实现纯软件的 IMEI 证书生成,从而消除对捐赠者 EFS 的需求。 2. **RFS 写入完善** — 我们的 RFS 守护进程会确认 WRITE 操作,但不会写入 `/efs` 文件系统。实现完整的写入支持将允许修补后的固件 + 自定义 CBD 方案独立达到状态 4。 3. **Frida CBD Hook** — 通过 Frida 在 `/sbin/cbd` 中 hook `check_csc_sales_code` 或 `std_security_req`,而不是替换原厂 CBD 二进制文件,这将允许原厂 CBD 接受修补后的固件,从而在不重新实现的情况下提供完整的 RFS 支持。 4. **ShannonLoader Ghidra 12.x 移植** — ShannonLoader Ghidra 扩展 (grant-h/ShannonBaseband) 目前仅支持 Ghidra 9.2.2。将其移植到 12.x API 将为 Shannon 固件分析启用现代工具。 5. **ESP32 Z3X 盒子模拟** — Z3X 盒子使用 FTDI FT232R (VID `0403` PID `0011`)。如果对通信协议进行逆向工程,带有 TinyUSB 的 ESP32 可能会模拟此接口。 ## 参考资料 - [ShannonBaseband](https://github.com/grant-h/ShannonBaseband) — 用于 三星 Shannon 调制解调器固件的 Ghidra 加载器和分析工具 - [Original qnd_cbd.py](https://gist.github.com/tonyg/4ea14f4dfe414422c0648c6e0a8bcb5d) — 针对 Galaxy S7 (SS310) 的 Python CBD 实现,是我们 C 语言移植的灵感来源 - [FirmWire](https://github.com/FirmWire/FirmWire) — 三星基带模拟和模糊测试框架 - [Samsung Tool PRO](https://z3x-team.com/) — 商业 IMEI 修复和解锁工具 - [OpenGApps](https://opengapps.org) — 适用于自定义 ROM 的 Google 应用 ## 许可证 MIT — 仅供教育和研究目的使用。本项目与三星电子没有任何隶属关系。提供的工具和信息仅供在您合法拥有的设备上使用。在某些司法管辖区,修改 IMEI 可能是违法的。
标签:Android底层, Samsung, 云资产清单, 固件开发, 基带, 客户端加密, 移动开发, 逆向工程