|
|
пре 1 месец | |
|---|---|---|
| .. | ||
| LuaBridgeCtl_SetXXTEAKeyGM_impl.c | пре 1 месец | |
| LuaNetworkController_SendMsg.c | пре 1 месец | |
| README.md | пре 1 месец | |
| SUMMARY.md | пре 1 месец | |
| box_data_passing.md | пре 1 месец | |
| decode_header.c | пре 1 месец | |
| encode_header.c | пре 1 месец | |
| frame.py | пре 1 месец | |
| hdr_codec.py | пре 1 месец | |
| http_downloader.py | пре 1 месец | |
| init_keys_and_sign.c | пре 1 месец | |
| keys_inventory.md | пре 1 месец | |
| label_batch.py | пре 1 месец | |
| map_format.md | пре 1 месец | |
| map_parser.py | пре 1 месец | |
| mmoclient_interfaces.h | пре 1 месец | |
| msg_codec.py | пре 1 месец | |
| netClient_SendNetMessage.c | пре 1 месец | |
| netClient_recv_dispatch.c | пре 1 месец | |
| netClient_recv_loop.c | пре 1 месец | |
| path_find.py | пре 1 месец | |
| rsa.py | пре 1 месец | |
| rsa_investigation.md | пре 1 месец | |
| tolua_SendMsg_binding.c | пре 1 месец | |
| xor_deobfuscate.c | пре 1 месец | |
| xxtea.py | пре 1 месец | |
来源:
996传奇盒子主二进制(9.6MB arm64,符号strip) 工具:radare2 6.2.2 (af;pdc伪C)+ 人工反汇编精读 + roundtrip 验证 阶段:2026-09-21 起,2026-09-23 三阶段全交付 完整总览见SUMMARY.md
将 9.6MB stripped arm64 二进制的 C++ 自研层 (mmoclient, 33 类 418 方法) 还原为 9 个可运行 Python 模块 + 10 份伪 C + 1 个完整接口契约 + 158 项回归测试。
C++ 编译有损(无符号/无RTTI/内联优化),不可能还原可编译源码; 本目录产出四档:
.c 文件:r2 自动生成的伪C(寄存器名,供核对地址/调用关系)mmoclient_interfaces.h:从 tolua 注册表提取的 33 类 418 方法接口契约*.py 算法等价库:人工精读反汇编后重写的可运行等价实现(roundtrip 验证)*.md):数据文件格式 + 字段语义 + 验证样本mmoclient_interfaces.h — 33 类 418 方法 .pkg 风格声明hdr_codec.py — 24B 头 ↔ 32B 编码 (50 组随机 roundtrip ✓)xxtea.py — XXTEA 加解密 (第三方 6.2.0 cross-verify ✓)frame.py — 36B 头 + body 完整帧 (与 protocol_bot 字节级一致 ✓)rsa.py — 客户端本地 RSA 接口 (已定论: 二进制中两方法均为空壳 stub, 无密钥)msg_codec.py — 协议编解码统一 API (33 测试 ✓)map_parser.py — WGS Mir2 .map 解析 (7/7 文件字节级 roundtrip ✓)path_find.py — A* 寻路 (7/7 map e2e ✓, 189 格长直道代价 1890 完美)http_downloader.py — 热更下载 (httpbin 1024B 实下载 ✓)label_batch.py — 批量文本渲染 (数据层 ✓)map_format.md — .map 文件 52B header + 12B cell + 0.map 扩展格式rsa_investigation.md — RSA 探索全程记录 (7 次失败 → aaa 突破 → stub 定论)box_data_passing.md — 996盒子→游戏数据传递机制 (env.json 双通道 + CS20 握手去向)SUMMARY.md — 三阶段总览(必读)tolua_SendMsg_binding.c @0x10007cd54LuaNetworkController_SendMsg.c @0x10005f8ccnetClient_SendNetMessage.c @0x10003d408encode_header.c / decode_header.c @0x10004b4e4/94netClient_recv_loop.c / recv_dispatch.c @0x100023df8 / 0x10003cd30xor_deobfuscate.c @0x100043b34init_keys_and_sign.c @0x100043bdc (555 行,含全部密钥对)LuaBridgeCtl_SetXXTEAKeyGM_impl.c @0x100044b88from msg_codec import decode_captured
fields = decode_captured(pcap_packet[:48])
# {'msgId': 101, 'recog': 900000, 'p1': 12345, 'p2': 37504, ...}
from msg_codec import send, MSG_CS_CREATE_ROLE
body = b'{"chr":"\xe8\x90\x8c\xe6\x96\xb0","job":0,"sex":1,"server_name":"\xe6\xaf\x94\xe5\xa5\x87","sdkid":"37504"}'
sock.sendall(send(MSG_CS_CREATE_ROLE, 900000, 12345, 37504, 0, body))
from msg_codec import receive, frame_to_dict
buf = b""
while chunk := sock.recv(65536):
buf += chunk
frames, buf = receive(buf)
for f in frames:
print(frame_to_dict(f))
from map_parser import load
m = load("scene/map/3.map")
print(f"{m.header.title!r} {m.header.width}x{m.header.height}")
c = m.get_cell(500, 400)
print(f"bg={c.bg_img} obj={c.obj_img} walkable={c.is_walkable}")
print(m.stats()) # {'total': 800000, 'walkable': 703221, 'walkable_pct': 87.9, ...}
# 编辑并写回
m.get_cell(0, 0).bg_img = 999
with open("/tmp/modified.map", "wb") as f:
f.write(m.to_bytes())
from map_parser import load
from path_find import find_path, path_cost, path_is_valid
m = load("scene/map/3.map")
# 短距离 (≤48x32 包围盒) — 单次调用
path = find_path(m, 100, 100, 110, 100, dis_x=50, dis_y=50)
# 长距离 — 分段拼接
from path_find import find_path_extended
path = find_path_extended(m, 250, 200, 700, 600, chunk_size=20)
assert path_is_valid(m, path)
print(f"路径 {len(path)} 点, 代价 {path_cost(m, path)}")
import http_downloader as dl
dl.set_download_dir("/tmp/cache")
dl.set_download_url("https://patch.example.com/996/")
dl.set_timeout(30)
dl.set_speed_limit(1024 * 1024)
task = dl.async_download_ex("res/0.map", "scene/map/0.map", sha1="abc123...")
print(f"http={task.http_code} bytes={task.downloaded} ok={task.error is None}")
from label_batch import LabelBatchNode, LabelBatchString
node = LabelBatchNode(font_atlas_path="fonts/arial_14.png")
for i, dmg in enumerate([100, -50, 200, -75]):
s = LabelBatchString(text=f"{dmg:+d}", x=i*40, y=200,
color=(255, 80, 80, 255) if dmg < 0 else (80, 255, 80, 255))
node.add_label_string(s)
print(f"batch: {len(node.strings)} strings, 1 draw call")
from xxtea import encrypt, decrypt, SCRIPT_KEY_RAW
plain = decrypt(cipher_bytes, SCRIPT_KEY_RAW.ljust(16, b"\x00"))
from rsa import encrypt_pub, decrypt_pri
encrypt_pub(b"data") # NotImplementedError: 密钥未从二进制提取
明文字节 b → ENC_TABLE[b] ^ 9 → 位流重组(8bit 窗口每次吐 6bit) → +0x3C
24B 明文 → 32B 密文 (全 0x3C..0x7B 可打印)
ENC_TABLE: 256B, __DATA @0x1008ae5f4
52B header + (w*h × 12B cells)
header: width(2) + height(2) + title_len(1) + title(N) + tail(34 raw)
cell: 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
8 方向, 直线 10 / 对角 14, 启发式 = 欧氏距离²
二叉堆优先队列, 网格内最优, 对角穿越自动阻止
寻路范围限制 48×32 (与 Lua updateLimits 一致, 长距离需分段)
# 阶段 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
| 缺口 | 难度 | 解法 |
|---|---|---|
✅ 已定论: r2 aaa 完整分析证实两方法为空壳 stub (返回空串), 密钥不存在于二进制, 证据链见 rsa_investigation.md 与 rsa.py INSTALL_HINT |
||
| 0.map 额外 980000B slot 编码 | 中 | 精读 tileSceneManager3:LoadMapData 循环,确定 4 个图槽位布局 |
✅ 已解 (2026-09-23): 字段已语义化 (ambient_id/editor_build/format_id), 含字节序勘误, 详见 map_format.md §二 |
||
| mapData2DRectGrid/Tile3/LightBuffer | 中 | 与运行时内存表示有关,需场景运行时抓 dump |
| ObjC 壳层 (SDKController) | 中 | 属另一文档范围,需 arm64 ObjC ABI 工具 |
完整版本与上下文见 SUMMARY.md 和 map_format.md。
msg_codec.py 做抓包分析 — 它 1 行能解出 msgId/recog/paramsmap_parser.py 解析地图 — 7 个样本可立即分析path_find.find_path() 替代手写 A*rsa_investigation.md), encrypt_pub/decrypt_pri 保持 NotImplementedError 是正确终态map_format.md §四 "待精读" 段*.c 文件都对应一个 Python 模块最后修改: 2026-09-23 17:09