百趣云 百趣云的博客

TEA/XXTEA:手游与 IoT 协议里的轻量加密

TEA 家族为什么在这些领域流行

TEA(Tiny Encryption Algorithm)的设计目标是"用最少的代码实现分组加密"——核心加密循环不到 20 行 C 代码。这使它成为手游协议、IoT 固件、嵌入式设备的标配加密:代码量小、速度快、资源占用低。

逆向这些领域时,TEA/XXTEA 的识别率是 AES 之外最高的。

识别:黄金分割常量是路标

TEA 的灵魂常量是 0x9E3779B9(2^32/φ,黄金分割比的无理数近似):

void tea_encrypt(uint32_t* v, uint32_t* k) {
    uint32_t v0 = v[0], v1 = v[1], sum = 0;
    uint32_t delta = 0x9E3779B9;              // ← 看到这个常量,TEA 家族实锤
    for (int i = 0; i < 32; i++) {            // 32 轮
        sum += delta;
        v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
        v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
    }
    v[0] = v0; v[1] = v1;
}

IDA 里搜 0x9E3779B9(ARM 汇编里是 movw/movt 组合加载),命中即 TEA 家族。再凑近看循环结构确认变体:

  • TEA:32 轮,上面的结构
  • XTEA:轮数类似,但 key 的使用顺序变了(k[sum & 3] 这种索引方式)
  • XXTEA:轮数不固定(6 + 52/n),处理变长块,结构更复杂

还原:标准实现直接可用

TEA 家族没有魔改传统(常量就是算法的一部分),识别后直接用标准实现:

import struct

def tea_decrypt(v, k):
    v0, v1 = v
    delta = 0x9E3779B9
    total = (delta * 32) & 0xFFFFFFFF   # 注意 32 位回绕
    for _ in range(32):
        v1 = (v1 - (((v0 << 4) + k[2]) ^ (v0 + total) ^ ((v0 >> 5) + k[3]))) & 0xFFFFFFFF
        v0 = (v0 - (((v1 << 4) + k[0]) ^ (v1 + total) ^ ((v1 >> 5) + k[1]))) & 0xFFFFFFFF
        total = (total - delta) & 0xFFFFFFFF
    return v0, v1

Python 移植的唯一坑是 32 位回绕:C 的 uint32 溢出自动回绕,Python 要手动 & 0xFFFFFFFF,每个运算都不能漏。

密钥获取:老套路

TEA 的 key 是 4 个 uint32(16 字节)。获取路径:

  1. SO 里硬编码:IDA 搜密钥使用点附近的内存引用
  2. hook 加密函数:找到 encrypt 函数地址后 hook 参数,key 指针直接读
  3. 手游特有:很多手游把 key 分段藏在 so 的不同位置,运行时拼接——hook 使用点最稳

精髓:手游协议分析的完整链路

以手游协议为例,TEA 在其中的位置:

游戏逻辑数据 → 序列化(protobuf/自定义) → TEA/XXTEA 加密 → 自定义协议头 → TCP 发送

逆向链路:

  1. tcpdump 抓包拿到密文流(私有协议,参考"长连接抓包"篇)
  2. 识别协议头:长度、类型、序列号
  3. 识别加密层:搜 0x9E3779B9 确认 TEA
  4. 拿 key:hook 加密函数
  5. 解密后对拍:解密结果应该是结构化数据(protobuf 或自定义二进制),解出来是乱码 = key 错或模式错(ECB/CBC 类分组模式问题)

精髓:XXTEA 的长度陷阱

XXTEA 处理变长数据,但有个细节:它按 uint32 数组处理,明文长度不是 4 的倍数时的填充方式各实现不同(补 0、补长度字节、PKCS7 风格都有)。对拍时先用 4 的倍数长度的数据验证算法,再研究尾巴怎么处理。

总结

  1. TEA 家族识别靠 0x9E3779B9 黄金分割常量
  2. 变体区分:TEA 固定 32 轮,XTEA 看 key 索引,XXTEA 变长
  3. Python 移植的坑全在 32 位回绕
  4. 手游链路:协议头 → TEA 层 → 序列化层,逐层剥离

交流微信:run1255

By 百趣云 阅读量:26 On