AES 加密逆向思路

在逆向工程与协议分析领域,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) 四轮操作重复迭代构成。

对逆向而言,最重要的两个识别特征是:

  1. S 盒(Substitution Box):AES 标准 S 盒是一张固定的 256 字节查表,数值全局唯一,几乎所有软件实现都会直接硬编码这张表,这是静态识别最核心的指纹。
  2. 轮常数 Rcon:密钥扩展过程中使用的固定常量数组,同样具有强特征。
  3. 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_encryptAES_set_encrypt_key(OpenSSL)、rijndaelaes_encrypt
  • 系统库:Windows 上的 BCryptEncryptCryptEncrypt;iOS/macOS 的 CCCrypt;Android 的 javax.crypto.Cipher
  • 静态编译的 OpenSSL、mbedTLS、LibTomCrypt 等库,可通过特征码匹配对应版本的 AES 实现。

三、动态逆向:抓取密钥与明文密文

静态定位只能找到函数位置,真正还原加密链路需要动态调试,核心目标是拿到密钥、IV、明文、密文四要素

1. 函数入口下断法

这是最常规的操作流程:

  1. 通过静态分析找到 AES 加密函数入口;
  2. 在函数开头下断点,运行程序触发加密;
  3. 从调用约定中读取参数:通常包含输入缓冲区指针、输出缓冲区指针、密钥指针、IV 指针、数据长度;
  4. 直接从内存中 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.doFinalCipher.init,直接打印密钥、IV、明文、密文;
  • Native 层 :Hook OpenSSL 的 AES_encryptAES_cbc_encrypt 等导出函数;
  • Windows 层 :使用 Detours、MinHook Hook BCryptEncryptCryptEncrypt 等系统 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 逆向步骤,适用于绝大多数客户端场景:

  1. 初步判定:抓包或提取本地数据,观察数据长度是否为 16 的倍数,熵值是否接近随机,初步判断是否为 AES。
  2. 静态定位:在二进制中搜索 S 盒、Rcon 特征,或搜索 AES 相关字符串、导入函数,圈定候选函数。
  3. 动态验证:在候选函数下断,传入已知明文,确认输出是否与预期密文一致。
  4. 提取要素:从栈 / 寄存器中取出密钥、IV、模式、填充方式。
  5. 复现验证:用 Python(PyCryptodome)或 OpenSSL 按相同参数加密,与程序输出逐字节比对。
  6. 处理变体:若比对不一致,排查是否有自定义填充、变形 S 盒、额外异或、字节序问题。
  7. 写脚本还原:将完整逻辑写成解密 / 加密脚本,接入后续协议分析或数据处理流程。

七、常用工具与速查清单

  • 静态分析: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 逆向最稳妥的学习路径。

相关推荐
Buke..1 天前
【APP 逆向】哔哩哔哩 sign 参数逆向(下):OLLVM 混淆还原 sign 算法
java·javascript·爬虫·python·算法
Buke..1 天前
【APP 逆向】哔哩哔哩 sign 参数逆向(上):Frida 反调试绕过与 unidbg 调用
java·开发语言·爬虫·python·安卓
归去来 兮1 天前
Python爬虫爬取数据案例
开发语言·爬虫·python
大鹏说大话2 天前
从爬虫到决策引擎:大数据下自媒体如何用Python挖掘用户痛点
开发语言·爬虫·python
Minner-Scrapy2 天前
Scrapy 2.17 源码解析:Scheduler 调度器与磁盘/内存双队列
java·爬虫·python·scrapy·网络爬虫·twisted
陈皮波比茶2 天前
Python项目实战-网络机器人(爬虫)
开发语言·网络·爬虫·python·机器人
不叫猫先生2 天前
2026 Web Scraping 实战:页面改 class 就归零?用 Bright Data 搭稳定的 Agent 爬虫
爬虫·agent
tang777892 天前
Scrapy框架动态IP自动轮换集成配置教程
爬虫·tcp/ip·scrapy·架构·爬虫代理·动态ip
深蓝电商API2 天前
ECC 加密简介
爬虫·ecc