常量定位法:密码学算法的"指纹鉴定"
SO 层逆向最高频的问题是"这段代码用的什么加密算法"。答案几乎总是同一个:搜特征常量。密码学算法的安全性来自密钥,不来自算法结构——所以标准算法内部都嵌着公开的数学常量,这些常量在二进制里就是独一无二的指纹。
本文把主流算法的识别常量汇总成一张速查表,配合搜索方法,30 秒识别一个算法。
速查表:算法 → 特征常量
对称加密:
| 算法 | 特征常量(hex 字节序) |
|---|---|
| AES | S盒 63 7C 77 7B F2 6B 6F C5;逆S盒 52 09 6A D5 |
| SM4 | S盒 D6 90 E9 FE CC E1;FK A3B1BAC6 |
| TEA 家族 | delta 0x9E3779B9 |
| DES | IP 置换表 58 50 42 34 26 18 10 02 |
| RC4 | 无固定常量(看 256 字节初始化循环结构) |
摘要算法:
| 算法 | 特征常量 |
|---|---|
| MD5 | IV 0x67452301;K表首项 0xD76AA478 |
| SHA-1 | IV 0x67452301 0xEFCDAB89 0x98BADCFE 0x10325476 0xC3D2E1F0 |
| SHA-256 | K表首项 0x428A2F98 0x71374491 |
| SM3 | IV 0x7380166F 0x4914B2B9 |
| HMAC | 无独有常量(看 ipad 0x36、opad 0x5C 的重复填充) |
非对称:
| 算法 | 特征 |
|---|---|
| RSA | 大数模幂运算结构;公钥 0x10001(65537) |
| ECC | 曲线参数(secp256k1 的 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) |
| SM2 | 曲线参数 FFFFFFFE FFFFFFFF ...(国密曲线) |
搜索方法:IDA 与命令行
IDA 里:Search → Sequence of bytes(Alt+B),输入 hex 字节串。32 位常量注意字节序——0x9E3779B9 在内存小端存储是 B9 79 37 9E,搜索时两种字节序都试。
命令行批量(分析大量 SO 时):
# 用 Python 批量扫
python3 -c "
import sys
data = open(sys.argv[1], 'rb').read()
sigs = {
'AES': bytes.fromhex('637c777bf26b6fc5'),
'SM4': bytes.fromhex('d690e9fecce1'),
'TEA': bytes.fromhex('b979379e'), # 小端
'MD5-K': bytes.fromhex('78a46ad7'), # 小端
'SHA256-K': bytes.fromhex('982f8a42'), # 小端
}
for name, sig in sigs.items():
off = data.find(sig)
if off >= 0:
print(f'{name} @ 0x{off:x}')
" libtarget.so精髓一:常量命中后干什么
命中只是起点,接下来要找到使用点:
- IDA 里对常量地址按
X查交叉引用 - 引用它的函数就是算法实现(或密钥扩展)
- 从算法函数再按
X往上追,找到业务调用层——那里才有 key 和数据的组装
精髓二:常量被隐藏的情况
高级防护会把常量做处理:
- 运行时计算:
0x9E3779B9不直接出现,而是(0x9E3779B8 + 1)或两条指令拼出来。对策:搜邻近常量(0x9E3779B8)、或动态分析(hook 内存写) - 表加密存储:S 盒加密存,运行时解密。对策:不静态找了,Frida 在算法运行时 dump 内存里的解密后表
- 自研算法无常量:回到"自定义加密还原"篇的方法论
精髓三:识别后的标准动作
识别出算法后的 checklist:
- 对拍验证:用标准实现 + hook 的 key 对已知输入加密,和 App 输出对比——确认算法、模式、key 三要素
- 记录证据:算法、常量地址、key 来源、模式,写进逆向笔记(下次版本更新对照用)
- 决策路径:标准算法 + 拿到 key = 本地复现;标准算法 + key 难拿 = Frida 直调;非标准 = 自定义加密方法论
总结
- 密码学常量即指纹,速查表覆盖主流算法
- 搜索注意字节序(小端存储),IDA Alt+B 或脚本批量
- 命中后按 X 追使用点,再追业务层拿 key
- 常量被隐藏就转动态分析,运行时 dump
交流微信:run1255