20、加密算法识别:识别常见加密算法(AES, RSA, Base64)、在二进制中查找S盒与常量

加密算法识别,说白了就是逆向分析中的“读心术”。你拿到一个二进制文件,里面可能藏着各种加密逻辑。你得一眼看出它用的是AES还是RSA,或者只是简单的Base64编码。我个人习惯先看常量,再看结构,最后才去追数据流。这套流程我用了快十年,基本没翻过车。

20.1 为什么识别加密算法这么重要?

你想想看,逆向一个程序,如果连它用了什么加密都不知道,后面的分析全是白搭。我遇到过好几次这样的情况:花了两天时间跟踪一个数据变换流程,最后发现只是Base64编码——嗯,那种感觉就像你跑完马拉松发现终点线画错了地方。

识别加密算法能帮你:

  • 缩小分析范围——知道是AES,你就去找密钥和IV
  • 定位关键数据——RSA的话,公钥和模数就是核心
  • 节省调试时间——不用自己从头推导算法逻辑

核心观点:加密算法识别不是靠猜,而是靠特征匹配。每个算法都有它独特的“指纹”——常量、S盒、固定结构。找到这些,你就找到了答案。

20.2 常见加密算法的特征

20.2.1 Base64——最容易被忽略的“加密”

Base64其实不算加密,但很多新手把它当加密用。它的特征非常明显:

  • 字符表ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
  • 填充符:末尾的===
  • 输出长度:总是4的倍数

我在项目中遇到过有人把Base64表改成自定义顺序,但核心逻辑没变——还是6位一组映射到字符。你只要看到这种查表映射的结构,基本就能锁定。

// Base64 核心逻辑伪代码
function base64_encode(data):
    table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    result = ""
    for each 3 bytes in data:
        // 取3个字节,拼成24位
        // 每6位一组,查表
        result += table[ (byte0 >> 2) & 0x3F ]
        result += table[ ((byte0 & 0x03) << 4) | (byte1 >> 4) ]
        // ... 以此类推
    return result

20.2.2 AES——S盒就是它的身份证

AES的S盒是固定的256字节表。你在二进制里找到这个表,基本就能确认是AES。我建议你记住S盒的前几个字节:0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5

AES的其他特征:

  • 轮常量0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
  • 密钥扩展:有固定的轮数(10/12/14轮)
  • 分组大小:固定16字节

小技巧:在IDA Pro或Ghidra里,直接搜索S盒的字节序列。如果找到连续256字节且符合AES S盒的值,十有八九就是AES。我曾经用这个方法在5分钟内定位了一个恶意软件的加密模块。

20.2.3 RSA——大数运算的痕迹

RSA的特征不太一样,它没有固定的S盒,但有大数运算的痕迹:

  • 大数常量:模数n通常有128/256/512字节
  • 公钥指数:常见的是0x10001(65537)
  • 数学运算:模幂运算,通常用Montgomery乘法优化
  • PKCS#1填充:以0x00 0x010x00 0x02开头

我记得有一次分析一个固件,里面有个大数乘法函数调用了上千次。我一看参数长度——128字节,立马意识到是RSA。后来验证,果然是1024位的RSA签名验证。

20.3 在二进制中查找S盒与常量

查找S盒和常量,说白了就是模式匹配。我给你几个实用方法:

20.3.1 手动搜索法

用十六进制编辑器打开二进制文件,直接搜索已知的常量序列。比如AES的S盒前8字节:63 7C 77 7B F2 6B 6F C5

20.3.2 自动化工具法

用Python写个脚本,扫描整个二进制文件,查找匹配的字节序列:

import sys

# AES S盒
aes_sbox = bytes([
    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
    0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
    # ... 完整256字节
])

def find_sbox(data, sbox):
    """在二进制数据中查找S盒"""
    for i in range(len(data) - 256):
        if data[i:i+256] == sbox:
            return i
    return -1

with open('target.bin', 'rb') as f:
    data = f.read()
    
offset = find_sbox(data, aes_sbox)
if offset != -1:
    print(f"找到AES S盒,偏移: 0x{offset:X}")
else:
    print("未找到AES S盒")

20.3.3 启发式检测法

有时候S盒会被混淆或加密。这时候可以用统计方法:

  • 字节分布:S盒通常是双射(每个值出现一次)
  • 差分均匀性:AES S盒的差分均匀性有特定模式
  • 代数次数:可以通过代数关系判断

注意:有些恶意软件会把S盒拆成多段存储,或者用XOR加密。我曾经遇到一个样本,把AES S盒拆成4个64字节的块,每块用不同密钥加密。这种情况下,你得先解密再匹配。

20.4 实战案例:识别一个未知二进制中的加密算法

我给你讲个真实案例。有一次我拿到一个IoT设备的固件,里面有个加密通信模块。我按以下步骤分析:

  1. 搜索常量:先搜Base64表,没找到。再搜AES S盒前8字节,找到了!
  2. 验证完整性:检查找到的256字节,确认是完整的AES S盒
  3. 定位轮常量:在S盒附近搜索01 02 04 08 10 20 40 80 1B 36,也找到了
  4. 确认算法:有S盒+轮常量+16字节分组,基本确定是AES-128
  5. 找密钥:在代码中追踪S盒的引用,找到了密钥扩展函数,最终定位到密钥

整个过程不到半小时。如果没有这些特征,我可能得花一整天去逆向整个加密流程。

20.5 知识体系图

下面这张图总结了加密算法识别的核心逻辑。你可以把它当作一个决策树来用:

二进制文件 搜索已知常量/特征 Base64 字符表 + 填充符 AES S盒 + 轮常量 + 16字节分组 RSA 大数常量 + 模幂运算 验证:输出长度是4的倍数 检查填充逻辑 验证:S盒是双射吗? 检查密钥扩展函数 验证:找到公钥指数0x10001 检查大数乘法 确认加密算法类型 定位密钥/参数 → 解密

20.6 常见陷阱与避坑指南

搞加密算法识别,有几个坑我踩过,你注意避开:

  • 别把Base64当加密——它只是编码,没有密钥。我曾经见过有人把Base64解码后的数据当明文,结果发现还有一层AES加密。
  • S盒可能被修改——有些实现会用自定义S盒。这时候你得看整体结构,别死磕标准S盒。
  • 常量可能被混淆——比如把轮常量拆开存储,或者用XOR隐藏。我建议你搜一下常见的XOR密钥(如0xFF、0x55),说不定能还原。
  • 算法可能被组合——比如先用RSA加密AES密钥,再用AES加密数据。这种情况你得分层分析。

我的经验:遇到不确定的情况,先假设是标准算法,验证特征。如果特征对不上,再考虑自定义实现。80%的情况下,标准算法就够了。

20.7 总结

加密算法识别,说白了就是找特征。Base64看字符表,AES看S盒,RSA看大数。你只要记住这几个核心特征,再配合自动化搜索工具,大部分情况都能快速定位。

我个人建议你平时多积累一些常见算法的常量库。比如AES的S盒、DES的初始置换表、MD5的初始向量。这些常量就像指纹一样,看一眼就能认出来。嗯,今天就到这里,下次遇到加密算法,你应该知道怎么下手了。


公众号:蓝海资料掘金营,微信deep3321