在逆向工程与协议分析领域,AES(Advanced Encryption Standard)是目前最常见的对称加密算法,广泛应用于客户端通信加密、本地数据保护、License 校验、固件加密等场景。与自定义异或、简单置换不同,AES 具有严格的数学结构和固定的算法特征,这也为逆向识别与还原提供了明确的抓手。本文从实战角度系统梳理 AES 加密的逆向分析思路,覆盖静态识别、动态抓包、密钥提取、变体对抗等完整链路。
一、逆向前的基础认知:AES 的可识别特征
AES 本质是一种分组密码,标准分组长度 128 bit(16 字节),密钥长度支持 128 / 192 / 256 bit,对应 AES-128、AES-192、AES-256。其核心运算由字节代换(SubBytes)、行移位(ShiftRows)、列混合(MixColumns)、轮密钥加(AddRoundKey) 四轮操作重复迭代构成。
对逆向而言,最重要的两个识别特征是:
- S 盒(Substitution Box):AES 标准 S 盒是一张固定的 256 字节查表,数值全局唯一,几乎所有软件实现都会直接硬编码这张表,这是静态识别最核心的指纹。
- 轮常数 Rcon:密钥扩展过程中使用的固定常量数组,同样具有强特征。
- 16 字节分组对齐:明文、密文长度通常为 16 的整数倍,不足时会按 PKCS7 / PKCS5 方式填充。
常见工作模式包括 ECB、CBC、CFB、OFB、GCM,其中 ECB 和 CBC 在客户端逆向中出现频率最高;GCM 因同时支持加密与校验,在现代 HTTPS、即时通讯协议中越来越常见。
二、静态逆向:从二进制中定位 AES 代码
静态识别是 AES 逆向的第一步,核心目标是在不运行程序的前提下,定位加密函数位置、判断算法类型与密钥长度。
1. S 盒特征匹配法
这是最直接也最可靠的识别方式。标准 AES S 盒的前 16 字节为: 63 7C 77 7B F2 6B 6F C5 30 01 67 2B FE D7 AB 76
在 IDA、Ghidra、Cutter 等反汇编工具中,可以直接搜索这串字节序列。只要程序使用了标准查表实现的 AES,几乎必然能命中。命中后向上追溯调用链,通常就能找到 AES 加密 / 解密的入口函数。
需要注意两点:
- 部分实现会同时存放正向 S 盒与逆 S 盒(InvSBox),逆 S 盒同样可作为特征。
- 嵌入式或高度优化的实现可能用 T 表(4 张 256×4 字节表)合并 SubBytes + MixColumns 运算,此时搜索完整 S 盒会失败,需要识别 T 表特征。
2. 常量与指令特征辅助判断
- Rcon 常数 :密钥扩展使用的轮常数,前几个值为
01 02 04 08 10 20 40 80 1B 36,可作为辅助识别依据。 - 循环轮数:AES-128 共 10 轮、AES-192 共 12 轮、AES-256 共 14 轮。反汇编中若看到固定次数的循环,且循环体内包含查表、移位、异或操作,可辅助判断密钥长度。
- 最后一轮无列混合:标准 AES 最后一轮省略 MixColumns,这是汇编层面的典型结构特征。
3. 导入函数与符号识别
如果程序未做符号剥离,可直接搜索关键词:
- 开源库:
AES_encrypt、AES_set_encrypt_key(OpenSSL)、rijndael、aes_encrypt - 系统库:Windows 上的
BCryptEncrypt、CryptEncrypt;iOS/macOS 的CCCrypt;Android 的javax.crypto.Cipher - 静态编译的 OpenSSL、mbedTLS、LibTomCrypt 等库,可通过特征码匹配对应版本的 AES 实现。
三、动态逆向:抓取密钥与明文密文
静态定位只能找到函数位置,真正还原加密链路需要动态调试,核心目标是拿到密钥、IV、明文、密文四要素。
1. 函数入口下断法
这是最常规的操作流程:
- 通过静态分析找到 AES 加密函数入口;
- 在函数开头下断点,运行程序触发加密;
- 从调用约定中读取参数:通常包含输入缓冲区指针、输出缓冲区指针、密钥指针、IV 指针、数据长度;
- 直接从内存中 Dump 出密钥、IV、明文和密文。
对于 Windows 程序(x86),常见调用约定为 __cdecl 或 __stdcall,参数从右向左压栈;x64 程序前四个参数通过 RCX、RDX、R8、R9 传递。对于 ARM 架构(Android /iOS),前四个参数一般在 R0-R3 / X0-X3 中。
2. 内存搜索法
当无法定位加密函数时,可以直接在内存中搜索已知明文或密文。
例如,如果你知道某段明文 "abcdef1234567890" 会被加密,就在程序内存中搜索该字符串,找到后对该内存页下硬件写入断点。当 AES 函数读取明文或写入密文时,断点会命中,从而回溯到加密函数本体。
同理,若已知一段固定密文,也可反向搜索密文地址,向上追溯解密函数。
3. 密钥特征搜索
AES 密钥在内存中通常以连续 16 / 24 / 32 字节的形式存在。如果密钥是硬编码的固定字符串,还可以结合字符串引用交叉定位。
更进阶的做法是:AES 运算过程中,轮密钥会被扩展成 11 / 13 / 15 组 16 字节密钥。在加密执行瞬间,内存中会存在完整的轮密钥序列,可通过特征扫描批量捕获。
4. Hook 框架批量拦截
对于 Android、iOS 或大型桌面程序,直接调试困难时,使用 Hook 框架是效率最高的方式:
- Android 层 :使用 Frida Hook
javax.crypto.Cipher.doFinal、Cipher.init,直接打印密钥、IV、明文、密文; - Native 层 :Hook OpenSSL 的
AES_encrypt、AES_cbc_encrypt等导出函数; - Windows 层 :使用 Detours、MinHook Hook
BCryptEncrypt、CryptEncrypt等系统 API。
这种方法对标准实现几乎通杀,也是协议分析中最常用的手段。
四、常见工作模式的逆向区分
找到 AES 函数后,还需要判断具体工作模式,才能正确复现加密逻辑。
- ECB 模式:每个 16 字节分组独立加密,无 IV 参数。相同明文分组产生相同密文分组,肉眼可见密文重复性。
- CBC 模式:需要 IV(16 字节)作为参数,每个分组加密前与上一组密文异或。函数参数中比 ECB 多一个 IV 指针。
- GCM 模式:除密钥、IV 外,还会输出认证标签(Tag,通常 16 字节),支持附加认证数据(AAD)。现代协议中遇到带校验的加密,优先怀疑 GCM。
- CFB / OFB / CTR:这三种都是流密码模式,不需要填充,输入输出长度相等,逆向时注意区分。
一个实用经验:如果函数参数里出现 16 字节的 "非密钥、非输入输出" 的缓冲区,大概率是 IV 或 Tag,基本可以排除 ECB。
五、对抗与变体:非常规 AES 的逆向思路
实际逆向中,标准 AES 越来越少,大量程序会对 AES 做变形以对抗分析,常见变体及应对思路如下。
1. 变形 S 盒
部分程序会对标准 S 盒做仿射变换、字节置换或索引偏移,导致常规 S 盒搜索失效。
逆向思路:
- 不要死磕静态特征,改用动态手段:构造全 0、全 1、单字节变化的明文输入,观察输出规律;
- 若满足 16 字节分组、雪崩效应明显、单比特输入变化影响约一半输出比特,则高度疑似 AES 变体;
- 逐轮 Dump 中间状态,反推自定义 S 盒与变换规则。
2. 白盒 AES
白盒 AES 将密钥和查表深度融合,运行时内存中不存在完整明文密钥,专门用于对抗动态密钥提取。
逆向思路:
- 白盒实现通常体积巨大,包含大量查找表(几十 KB 到上百 KB),静态上可作为初步判断;
- 常规 Hook 拿不到原始密钥,需通过差分分析、代数攻击等方法提取密钥,或直接 Dump 加密 / 解密表进行等价移植;
- 工程上更简单的做法是:直接调用原程序的加密函数,而不是强行还原密钥。
3. 硬件加密与系统密钥链
Windows TPM、iOS Secure Enclave、Android Keystore 等场景下,密钥存在硬件安全区,CPU 内存中不可见。
逆向思路:
- 放弃提取原始密钥,改为 Hook 加密结果、Hook 明文输入;
- 分析调用流程,找到加密前后的业务数据处理逻辑,在明文进入加密模块前拦截。
4. 多轮 AES 与级联加密
有些程序会做 AES 多重加密(如 AES-256 两层级联),或 AES + 异或 / Base64 混合编码。
逆向思路:
- 先剥离外层编码(Base64、Hex、自定义映射);
- 再通过分组长度、熵值判断加密层数;
- 从密文向明文逐层回溯,每一层单独识别。
六、实战逆向的标准流程
总结一套可复用的 AES 逆向步骤,适用于绝大多数客户端场景:
- 初步判定:抓包或提取本地数据,观察数据长度是否为 16 的倍数,熵值是否接近随机,初步判断是否为 AES。
- 静态定位:在二进制中搜索 S 盒、Rcon 特征,或搜索 AES 相关字符串、导入函数,圈定候选函数。
- 动态验证:在候选函数下断,传入已知明文,确认输出是否与预期密文一致。
- 提取要素:从栈 / 寄存器中取出密钥、IV、模式、填充方式。
- 复现验证:用 Python(PyCryptodome)或 OpenSSL 按相同参数加密,与程序输出逐字节比对。
- 处理变体:若比对不一致,排查是否有自定义填充、变形 S 盒、额外异或、字节序问题。
- 写脚本还原:将完整逻辑写成解密 / 加密脚本,接入后续协议分析或数据处理流程。
七、常用工具与速查清单
- 静态分析:IDA Pro、Ghidra、Binary Ninja
- 动态调试:x64dbg、OllyDbg、LLDB、GDB
- 移动端 Hook:Frida、Objection、Xposed、Frida-il2cpp-bridge
- 加密验证:Python + PyCryptodome、CyberChef、OpenSSL 命令行
- 辅助工具:010 Editor(十六进制分析)、Detours / MinHook(Windows Hook)
结语
AES 逆向的核心矛盾在于:算法是公开的,密钥和参数是隐藏的。绝大多数场景下,逆向工程师不需要重新发明 AES,只需要找到密钥、确认模式、补齐参数,就能完整还原加密逻辑。标准 AES 逆向门槛很低,真正的挑战在于各类变体、白盒、硬件加密与混淆保护。从标准实现入手,建立特征直觉,再逐步向变体延伸,是 AES 逆向最稳妥的学习路径。