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 0x01或0x00 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设备的固件,里面有个加密通信模块。我按以下步骤分析:
- 搜索常量:先搜Base64表,没找到。再搜AES S盒前8字节,找到了!
- 验证完整性:检查找到的256字节,确认是完整的AES S盒
- 定位轮常量:在S盒附近搜索
01 02 04 08 10 20 40 80 1B 36,也找到了 - 确认算法:有S盒+轮常量+16字节分组,基本确定是AES-128
- 找密钥:在代码中追踪S盒的引用,找到了密钥扩展函数,最终定位到密钥
整个过程不到半小时。如果没有这些特征,我可能得花一整天去逆向整个加密流程。
20.5 知识体系图
下面这张图总结了加密算法识别的核心逻辑。你可以把它当作一个决策树来用:
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