# TDX 协议逆向工程全景 本文记录通达信 (TDX) 私有二进制 TCP 协议的逆向研究过程,帮助理解 easy-tdx 项目中各层协议实现的设计原理。 ## 第一层:抓包 — 发现帧结构 通达信客户端和服务器之间是裸 TCP(端口 `7709`),没有 HTTP 包装。研究者通过 Wireshark 抓包发现了一个固定的帧格式: ``` 响应帧 = 16字节固定头 + 可变长度 body ``` `codec/frame.py` 记录了这个发现: ``` 偏移 0: I (4字节) — 未知 偏移 4: I (4字节) — 未知 偏移 8: I (4字节) — 未知 偏移 12: H (2字节) — zipsize(body 实际长度) 偏移 14: H (2字节) — unzipsize(解压后长度) ``` 关键发现:**当 zipsize == unzipsize 时 body 未压缩,否则需要 zlib 解压**。这是通过对比抓包数据和 zlib 解压结果验证的。 ## 第二层:握手 — 三条神秘命令 `commands/setup.py` 中的三条握手命令是硬编码的原始字节: ```python SETUP_CMD1: "0c0218930001030003000d0001" SETUP_CMD2: "0c0218940001030003000d0002" SETUP_CMD3: "0c031899000120002000db0f..." # 30字节,含GBK编码的"申银万国" ``` 注释写得很清楚:"从 pytdx 源码移植,已在真实服务器验证"。这说明握手命令不是这个项目原创的,而是从开源项目 [pytdx](https://github.com/rainx/pytdx) 继承来的。pytdx 的作者 rainx 通过**逆向通达信 Windows 客户端**(用 IDA Pro 等反汇编工具)得到了这些字节序列。 第三条命令特别有意思,里面包含了 `d5d0c9ccd6a4a8af`,这是 GBK 编码的"申银万国"(一家券商名),说明这条握手命令里包含了**客户端标识信息**。 ## 第三层:请求构造 — 猜解命令格式 每个命令的请求都是一个固定格式的二进制包。以 `security_list.py` 为例: ```python header = bytes.fromhex("0c0118640101060006005004") payload = struct.pack("> 24) & 0xFF # 指数 hleax = (ivol >> 16) & 0xFF # 高精度 lheax = (ivol >> 8) & 0xFF # 中精度 lleax = ivol & 0xFF # 低精度 ``` 这个格式完全不是 IEEE 754,是通达信自创的。逆向方法:拿到已知成交量的 hex dump,用不同的拆分方式穷举,直到找到能还原正确数值的公式。 ## 第六层:未知字段 — 逆向的痕迹 代码中大量保留了 `unknown_0` 到 `unknown_8` 的字段,这本身就是逆向过程的痕迹——解析出格式但不确定含义的字段。比如: - `unknown_0` 后来被发现是服务器时间戳("小时 + 百万分之一小时"编码) - `unknown_1` 推测等于 `-price_raw` - 指数 K 线比股票 K 线多 4 字节(上涨/下跌家数),是通过对比同一市场的指数和股票响应长度差异发现的 ## 总结:逆向方法论 这个项目体现的逆向研究路线是: 1. **抓包** (Wireshark) → 发现 TCP 帧结构、握手序列 2. **反汇编** (IDA Pro) → 得到请求构造函数、编解码算法 3. **黑盒验证** → 修改参数发请求,对比响应确认字段含义 4. **差分分析** → 利用已知数据(如已知价格)反推编码公式 5. **对比分析** → 指数 vs 股票、不同市场、不同周期的响应差异 6. **开源传承** → pytdx 打下基础,easy-tdx 在此之上修复 bug 并重构 核心依赖是 **pytdx 项目**做的基础逆向工作(反汇编通达信客户端),easy-tdx 则是在已有协议知识上的高质量 Python 重写。