SUMMARY.md 8.0 KB

cpp_reversed/ 成果总览

996传奇客户端 C++ 反编译还原工程 — 阶段 1+2+3 全部交付 日期: 2026-09-21 起, 2026-09-23 阶段 3 完成


〇、一句话总结

将 9.6MB stripped arm64 二进制的 C++ 自研层 (mmoclient, 33 类 418 方法) 还原为 9 个可运行的 Python 模块 + 10 份伪 C + 1 个完整接口契约 + 158 项回归测试。

涵盖网络协议(头编解码/XXTEA/RSA 接口)、脚本密文、地图格式(.map 文件字节级 roundtrip)、寻路(A* 8 方向)、热更下载、批量文本渲染六大子系统。


一、产出物全景

1.1 Python 模块 (9 个, ~2.2k 行)

模块 行数 来源 验证 用途
hdr_codec.py 74 encode_header @0x10004b4e4 50 组随机 roundtrip 24B 头 ↔ 32B 编码
xxtea.py 193 LuaBridgeCtl::SetXXTEAKeyGM 第三方 xxtea 6.2.0 cross-verify 脚本密文加解密
frame.py 226 netClient::SendNetMessage 与 protocol_bot 字节级一致 36B 头 + body 帧装拆
rsa.py 151 LuaBridgeCtl::RsaEncryptPub/DecryptPri 接口预留 (密钥待提取) RSA 客户端本地接口
msg_codec.py 232 上述聚合 33 测试 协议编解码统一 API
map_parser.py 299 tileSceneManager:LoadMapData 7/7 .map 字节级 roundtrip WGS Mir2 地图解析
path_find.py 311 aiManager:FindPath + Lua A* 41 测试, 长直道 189 格代价 1890 A* 寻路 (8 方向)
http_downloader.py 321 httpDownloader:AsyncDownloadEx httpbin.org 1024B 实下载 热更/资源下载
label_batch.py 142 LabelBatchNode 22 tolua 方法 接口自测 批量文本渲染 (数据层)

1.2 r2 伪 C (10 个, ~1.4k 行)

文件 二进制地址 函数
tolua_SendMsg_binding.c 0x10007cd54 tolua 绑定层
LuaNetworkController_SendMsg.c 0x10005f8cc 消息组装
netClient_SendNetMessage.c 0x10003d408 加密+入队
encode_header.c / decode_header.c 0x10004b4e4/94 头编解码
netClient_recv_loop.c / recv_dispatch.c 0x100023df8 / 0x10003cd30 收包+分发
xor_deobfuscate.c 0x100043b34 XOR 0x10 字符串解混淆
init_keys_and_sign.c 0x100043bdc XXTEA 密钥初始化 (555 行)
LuaBridgeCtl_SetXXTEAKeyGM_impl.c 0x100044b88 GM 动态换 key

1.3 接口契约 (1 个, 577 行)

mmoclient_interfaces.h — 33 类 418 方法 .pkg 风格声明,带分组注释和 tolua 方法名

1.4 文档 (3 个, ~570 行)

文件 覆盖
README.md 总体说明 + 三档产物 + 用法示例
map_format.md .map 文件格式逆向报告 (含 0.map 额外区部分反推)
rsa_investigation.md RSA 探索全程记录: 7 次搜索失败 → r2 aaa 突破 → 空壳 stub 定论
box_data_passing.md 996盒子→游戏数据传递: env.json 双通道 + GN/NG 桥 + CS20 去向
SUMMARY.md (本文件) 阶段性成果总览

1.5 测试 (3 个新文件, 1180 行, 158 项)

文件 测试项 范围
tests/test_msg_codec.py 33 hdr/xxtea/frame/msg_codec/rsa 协议层
tests/test_map_parser.py 38 map_parser 全部 7 个 .map 样本
tests/test_path_find.py 41 A* 寻路 + 5 个 e2e 地图寻路
(原有 28 项无回归) 28 协议桥/调度器/网络桩
合计 158 (含 extra_areas 8 项 + header 语义 10 项)

二、按子系统的能力矩阵

子系统 接口契约 伪 C 可运行实现 字节级 roundtrip 真实 e2e
网络协议 (头) ✓ ✓ ✓ ✓ ✓ (pcap 兼容)
网络协议 (帧) ✓ ✓ ✓ ✓ ✓ (3 个调用方字节级一致)
XXTEA ✓ ✓ ✓ ✓ ✓ (第三方包 cross-verify)
RSA ✓ — △ (接口预留) — —
地图格式 ✓ — ✓ ✓ ✓ (7/7 文件)
寻路 ✓ — ✓ — ✓ (189 格长直道)
热更下载 ✓ — ✓ — ✓ (httpbin 1024B)
批量文本 ✓ — ✓ (数据层) — △ (需 cocos2d-x 渲染)

✓ = 完整还原 / △ = 部分还原 / — = 未涉及


三、关键算法速查

3.1 协议头 (24B → 32B)

明文字节 b → ENC_TABLE[b] ^ 9 → 8bit 窗口每次吐 6bit → +0x3C
24B 明文 → 32B 密文 (全 0x3C..0x7B 可打印)
ENC_TABLE: 256B, __DATA @0x1008ae5f4

3.2 XXTEA (脚本密文)

8B 块, 16B key, 32 轮, big-endian, delta=0x9E3779B9
padding 0x00 (与 lua lockbox/cipher/tea.lua 一致)
注: 已修正 xxtea-c 参考的 z 未初始化 bug, 严格按 Needham-Wheeler 论文

3.3 地图格式 (.map)

52B header (width/height/title/raw_tail) + (w*h × 12B cells)
cell 12B: bg_img(2) + mid_img(2) + obj_img(2) + ani_idx(2) + door_flag(1) + light(1) + area(1) + ani_tick(1)
扩展格式 (title_len=15, 仅 0.map): header + 980000B 2B/cell 稀疏索引 + cells
  额外区: 87% 零, 5% 0x8000 标志, 8% 真实 tile 索引 (slot 编码未解)

3.4 寻路 (A*)

8 方向, 直线 10 / 对角 14, 启发式 = 欧氏距离²
二叉堆优先队列, 对角穿越自动阻止 (防穿墙)
寻路范围限制 48×32 (与 Lua updateLimits 一致, 长距离需分段)

3.5 下载 (httpDownloader)

urllib + threading 模拟异步
限速: 令牌桶 (throttle)
进度: callback(downloaded, total)
SHA1 校验 (可选)
完整热更流程: download_manifest() + download_update_files(only_changed)

四、测试覆盖

# 阶段 1 算法库 (33) + 阶段 2 地图解析 (38+8 extra_areas+10 header语义) + 阶段 3 寻路 (41) + 原有 (28) = 158 总
cd /path/to/传奇
.venv/bin/python -m pytest tests/ -m "not live" -v

# 实时下载测试
python3 cpp_reversed/http_downloader.py
# 期望: saved 1024B to /tmp/httpdl_test/test.bin

# 字节级 roundtrip 验证
python3 -c "
import sys; sys.path.insert(0, 'cpp_reversed')
from map_parser import load
m = load('996传奇盒子资源包/03-游戏客户端/jycq_206923/scene/map/3.map')
out = m.to_bytes()
orig = open('996传奇盒子资源包/03-游戏客户端/jycq_206923/scene/map/3.map', 'rb').read()
print(f'roundtrip: {out == orig}  ({len(out)}B)')
"

五、未完成 / 已知缺口 (诚实记录)

缺口 难度 解法
客户端本地 RSA 密钥对 中-高 ✅ 已定论 (2026-09-23): r2 aaa 完整分析证实 RsaEncryptPub/RsaDecryptPri 是空壳 stub (返回空串), 密钥不存在于二进制。证据链见 rsa_investigation.md
0.map 额外 980000B 区 slot 编码 中 ⚡ 静态分析已到边界 (2026-09-23 二轮): 7 项一组宏图块结构 + V/0x8000 交替已实证; LoadMapData 调用链挖透, 完整槽映射在运行时渲染路径, 需抓内存对照。详见 map_format.md §四
header 18-51 字段精确含义 中 ✅ 已解 (2026-09-23): 7 样本逐字节统计 + 10 项语义测试锁定, 含字节序勘误 (update 时间戳 BE→LE), 详见 map_format.md §二
mapData2DRectGrid/Tile3/LightBuffer 中 与运行时内存表示有关,需场景运行时抓 dump
ObjC 壳层 (SDKController) 中 属另一文档范围,需 arm64 ObjC ABI 工具

六、给后续读者的建议

  1. 先用 msg_codec.py 做抓包分析 — 它 1 行能解出 msgId/recog/params
  2. 再用 map_parser.py 解析地图 — 7 个样本可立即分析
  3. 如果做 bot, 直接用 path_find.find_path() 替代手写 A*
  4. 要继续还原 RSA, 入口是 cpp_reversed/rsa.py 的 INSTALL_HINT 块
  5. 要继续还原 0.map 额外区, 入口是 map_format.md §四 "待精读" 段
  6. 要对比 .c 伪代码和 Python 实现, 任何 *.c 文件都对应一个 Python 模块

七、版本信息

  • 创建: 2026-09-21 (cpp_reversed/ 目录, 10 个 .c + hdr_codec.py + interfaces.h)
  • 阶段 1: 2026-09-23 (xxtea/frame/rsa/msg_codec 算法库)
  • 阶段 2: 2026-09-23 (map_parser + map_format.md 地图格式)
  • 阶段 3: 2026-09-23 (path_find + http_downloader + label_batch)
  • 收官: 2026-09-23 (SUMMARY.md + README.md 最终版)

最后修改: 2026-09-23 17:09