为什么会遇到 SM4
逆向政务、银行、国企 App 时,加密算法会从 AES 换成 SM4——国家商用密码标准。合规要求(等保、密评)决定了这些领域的 App 必须用国密算法。遇到"结构像 AES 但常量对不上"的分组加密,就要想到 SM4。
SM4 与 AES 的结构对比
| 维度 | SM4 | AES |
|---|---|---|
| 分组长度 | 128 位 | 128 位 |
| 密钥长度 | 128 位(唯一) | 128/192/256 |
| 轮数 | 32 轮 | 10/12/14 轮 |
| 结构 | 非平衡 Feistel | SPN |
| S 盒 | 1 个 8×8 S 盒 | 1 个 8×8 S 盒(不同的表) |
识别:SM4 的特征常量
S 盒:SM4 的 S 盒开头是:
d6 90 e9 fe cc e1 3d b5 16 b4 14 c2 28 fb 2c 05IDA 搜 D6 90 E9 FE CC E1——和 AES 的 63 7C 77 7B 一样,这是 SM4 的指纹。
系统参数 FK(密钥扩展用):
A3B1BAC6 56AA3350 677D9197 B27022DC固定参数 CK(32 个轮密钥常量):
00070E15 1C232A31 383F464D 545B6269 ...三组常量搜到任何一组即实锤 SM4。Java 层更简单:搜 SM4 字符串、Sm4Util 类名、或 BouncyCastle 的 SM4Engine。
模式与填充:和 AES 相同的概念
SM4 同样有 ECB/CBC/CTR 等模式、PKCS7 等填充,判断方法和 AES 一样(见 AES 识别篇)。政务 App 的常见组合是 SM4-ECB-PKCS7(简单场景)和 SM4-CBC(传输场景)。
Python 实现与对拍
# 用 gmssl 库
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
key = b'0123456789abcdeffedcba9876543210' # 16 字节
cipher = CryptSM4()
cipher.set_key(key, SM4_ENCRYPT)
# ECB 模式
ciphertext = cipher.crypt_ecb(plaintext)
# CBC 模式(gmssl 的 crypt_cbc 需要 iv 参数)
cipher.set_key(key, SM4_DECRYPT)
plaintext = cipher.crypt_cbc(iv, ciphertext)对拍流程和 AES 相同:hook 拿 key/iv → 已知明文加密 → 和 App 输出对比。
精髓一:国密全家桶的联动
政务金融 App rarely 只用 SM4,通常是国密全家桶:
- SM2:非对称(替代 RSA),用于密钥交换/签名
- SM3:摘要(替代 SHA-256),用于完整性/签名
- SM4:对称(替代 AES),用于数据加密
识别到 SM4 后,顺带检查 SM2/SM3 的存在。SM3 的识别常量是 IV 7380166F 4914B2B9 ...,SM2 是椭圆曲线运算(识别曲线参数)。
精髓二:合规场景的密钥管理更规范
政务金融 App 的密钥管理比互联网 App 规范:
- 密钥很少硬编码(过不了密评)
- 常见做法是 SM2 加密 SM4 密钥(数字信封):SM2 公钥加密随机的 SM4 密钥传输,SM4 加密业务数据
- 逆向要点变成:找 SM2 的私钥/公钥体系 + hook SM4 密钥的生成点
hook 点选择:Sm4Util 类的 setKey/init 方法,或 BouncyCastle 的 SM4Engine.init——key 明文必经之地。
总结
- 政务金融 App 用国密,SM4 替代 AES
- 识别常量:S 盒
D6 90 E9 FE、FK 参数、CK 常量表 - 模式填充概念与 AES 相同,gmssl 库直接对拍
- 注意 SM2/SM3 联动,数字信封结构下 hook SM4 密钥生成点
交流微信:run1255