在逆向分析的过程中,我们经常会遇到一些常用的已公开的算法如md5、sha1、sha256、sm3、base64等,这些算法常用于数据计算或者转换;也经常会遇到另外一些常用的算法如rc4、aes等,而这些算法常用于数据加密,所有这些算法都是用于特定安全场景(保密性、完整性)的,今天我们要分享的主题是当逆向过程中遇到这些算法的时,我们如何快速的识别这些算法,特别是在分析汇编级别的程序时尤为有用(现在安全能力越来越强,即使是编译后的汇编程序也可能进行了各种加固,让我们不能直观的分析程序)。
抛开各种算法背后的数学和密码学原理(作为逆向工程师,我们不要陷入其中),快速识别算法才是最重要的,它能大大的节省我们分析应用逻辑的时间,今天我们着重介绍一下md5、sha1、sha256、sm3、aes这样算法的识别,对剩下的base64、rc4算法识别我们将放到下一篇文章中。
在陈述本篇文章前,我先介绍一下本篇识别算法的方法-常数识别法和S-box(inv-sbox)识别法。
或许这些方法早已在高级逆向工程师中传播(更多的是高级逆向工程师的自我发现和觉醒,形成的自我经验,或许他们不愿意传播),但对于刚刚研究和学习逆向或者中级逆向工程师来说它了解它们是有裨益的。
常数识别方法
已公开的通用的哈希算法,在程序运算的开始都会初始化固定数量的常数,考虑到算法的复杂性,一般这些算法不会被修改,因此识别这些常数就成了我们识别算法的关键。
S-box、inv-sbox识别方法
同样已公开的某些加密算法也具备这样的特征,如aes、des这样的算法,它们算法中通常包含一个固定的默认 S-box(Substitution box)。它是 字节替换(SubBytes)步骤 中使用的查表,用于把每个字节替换成另一个字节,从而实现非线性变换。识别S-box就成了识别这类加密算法的关键。
Inv-sbox同理。
md5算法识别
md5算法的识别属于常数识别范畴,它包含以下4个有且只有4个常数(区别于sha1),要仔细核对常数个数:
A = 0x67452301,B = 0xefcdab89,C = 0x98badcfe,D = 0x10325476
我手边有js实现的md5代码,我们来截取一部分看一下:

那我们看一下包含md5算法的汇编程序(利用反编译软件):
这幅图片是包含md5算法的4个常量的地方,通过交叉引用我们可以找到它们被引用的地方。

即下面这幅图,该程序是md5算法的主体,它包含了上面4个常数,并且它确实是md5。

sha1算法识别
sha1算法的识别属于常数识别范畴,它包含以下5个有且只有5个常数,它的前4个常数和md5算法常数完全相同,因此在识别该算法的时候一定要仔细查看常数的个数:
H0 = 0x67452301,H1 = 0xEFCDAB89,H2 = 0x98BADCFE,H3 = 0x10325476,H4 = 0xC3D2E1F0
识别方法同md5,这里就不再给大家演示了。
sha256算法识别
sha256算法的识别属于常数识别范畴,它包含以下8常数:
H0 = 0x6A09E667
H1 = 0xBB67AE85
H2 = 0x3C6EF372
H3 = 0xA54FF53A
H4 = 0x510E527F
H5 = 0x9B05688C
H6 = 0x1F83D9AB
H7 = 0x5BE0CD19
识别方法同md5,这里就不再给大家演示了。
sm3识别算法
sm3算法的识别属于常数识别范畴,它包含以下8常数(很容易和sha256混淆):
A=0x7380166F
B=0x4914B2B9
C=0x172442D7
D=0xDA8A0600
E=0xA96F30BC
F=0x163138AA
G=0xE38DEE4D
H=0xB0FB0E4E
识别方法同md5,这里就不再给大家演示了。
Aes识别方法
S-box识别
所有标准 AES(AES-128 / AES-192 / AES-256)都使用同一个 S-box。它是固定的,不会在算法运行时“随机生成”或“动态变换”。
S-box如下(固定的 16×16 表):
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
0x0 | 63 | 7C | 77 | 7B | F2 | 6B | 6F | C5 | 30 | 01 | 67 | 2B | FE | D7 | AB | 76 |
0x1 | CA | 82 | C9 | 7D | FA | 59 | 47 | F0 | AD | D4 | A2 | AF | 9C | A4 | 72 | C0 |
0x2 | B7 | FD | 93 | 26 | 36 | 3F | F7 | CC | 34 | A5 | E5 | F1 | 71 | D8 | 31 | 15 |
0x3 | 04 | C7 | 23 | C3 | 18 | 96 | 05 | 9A | 07 | 12 | 80 | E2 | EB | 27 | B2 | 75 |
0x4 | 09 | 83 | 2C | 1A | 1B | 6E | 5A | A0 | 52 | 3B | D6 | B3 | 29 | E3 | 2F | 84 |
0x5 | 53 | D1 | 00 | ED | 20 | FC | B1 | 5B | 6A | CB | BE | 39 | 4A | 4C | 58 | CF |
0x6 | D0 | EF | AA | FB | 43 | 4D | 33 | 85 | 45 | F9 | 02 | 7F | 50 | 3C | 9F | A8 |
0x7 | 51 | A3 | 40 | 8F | 92 | 9D | 38 | F5 | BC | B6 | DA | 21 | 10 | FF | F3 | D2 |
0x8 | CD | 0C | 13 | EC | 5F | 97 | 44 | 17 | C4 | A7 | 7E | 3D | 64 | 5D | 19 | 73 |
0x9 | 60 | 81 | 4F | DC | 22 | 2A | 90 | 88 | 46 | EE | B8 | 14 | DE | 5E | 0B | DB |
0xA | E0 | 32 | 3A | 0A | 49 | 06 | 24 | 5C | C2 | D3 | AC | 62 | 91 | 95 | E4 | 79 |
0xB | E7 | C8 | 37 | 6D | 8D | D5 | 4E | A9 | 6C | 56 | F4 | EA | 65 | 7A | AE | 08 |
0xC | BA | 78 | 25 | 2E | 1C | A6 | B4 | C6 | E8 | DD | 74 | 1F | 4B | BD | 8B | 8A |
0xD | 70 | 3E | B5 | 66 | 48 | 03 | F6 | 0E | 61 | 35 | 57 | B9 | 86 | C1 | 1D | 9E |
0xE | E1 | F8 | 98 | 11 | 69 | D9 | 8E | 94 | 9B | 1E | 87 | E9 | CE | 55 | 28 | DF |
0xF | 8C | A1 | 89 | 0D | BF | E6 | 42 | 68 | 41 | 99 | 2D | 0F | B0 | 54 | BB | 16 |
Inv-sbox识别
AES 中存在一个默认的 InvSBox(逆 S 盒),它与 SBox 是一一对应的逆映射关系。
也就是说:对 SBox 中的任意字节 x,如果 SBox[x] = y,那么 InvSBox[y] = x。
InvSBox 不是随机生成的,也不是每次运行动态变化的,它是根据 SBox 算出的一个 固定常数表,同样由 AES 标准(FIPS-197)定义。
Inv-sbox如下(固定的 16×16 表):
x\y | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
0x0 | 52 | 09 | 6A | D5 | 30 | 36 | A5 | 38 | BF | 40 | A3 | 9E | 81 | F3 | D7 | FB |
0x1 | 7C | E3 | 39 | 82 | 9B | 2F | FF | 87 | 34 | 8E | 43 | 44 | C4 | DE | E9 | CB |
0x2 | 54 | 7B | 94 | 32 | A6 | C2 | 23 | 3D | EE | 4C | 95 | 0B | 42 | FA | C3 | 4E |
0x3 | 08 | 2E | A1 | 66 | 28 | D9 | 24 | B2 | 76 | 5B | A2 | 49 | 6D | 8B | D1 | 25 |
0x4 | 72 | F8 | F6 | 64 | 86 | 68 | 98 | 16 | D4 | A4 | 5C | CC | 5D | 65 | B6 | 92 |
0x5 | 6C | 70 | 48 | 50 | FD | ED | B9 | DA | 5E | 15 | 46 | 57 | A7 | 8D | 9D | 84 |
0x6 | 90 | D8 | AB | 00 | 8C | BC | D3 | 0A | F7 | E4 | 58 | 05 | B8 | B3 | 45 | 06 |
0x7 | D0 | 2C | 1E | 8F | CA | 3F | 0F | 02 | C1 | AF | BD | 03 | 01 | 13 | 8A | 6B |
0x8 | 3A | 91 | 11 | 41 | 4F | 67 | DC | EA | 97 | F2 | CF | CE | F0 | B4 | E6 | 73 |
0x9 | 96 | AC | 74 | 22 | E7 | AD | 35 | 85 | E2 | F9 | 37 | E8 | 1C | 75 | DF | 6E |
0xA | 47 | F1 | 1A | 71 | 1D | 29 | C5 | 89 | 6F | B7 | 62 | 0E | AA | 18 | BE | 1B |
0xB | FC | 56 | 3E | 4B | C6 | D2 | 79 | 20 | 9A | DB | C0 | FE | 78 | CD | 5A | F4 |
0xC | 1F | DD | A8 | 33 | 88 | 07 | C7 | 31 | B1 | 12 | 10 | 59 | 27 | 80 | EC | 5F |
0xD | 60 | 51 | 7F | A9 | 19 | B5 | 4A | 0D | 2D | E5 | 7A | 9F | 93 | C9 | 9C | EF |
0xE | A0 | E0 | 3B | 4D | AE | 2A | F5 | B0 | C8 | EB | BB | 3C | 83 | 53 | 99 | 61 |
0xF | 17 | 2B | 04 | 7E | BA | 77 | D6 | 26 | E1 | 69 | 14 | 63 | 55 | 21 | 0C | 7D |
注意:以上方法并不总适用,有些aes的实现S-box(inv-sbox)是通过程序计算出来,而不是默认直接给出的。
常数识别
仿射变换矩阵
有些人自己实现aes算法S-box 仿射变换(我们不关注背后的逻辑),我们会看到仿射变换矩阵 A 的8行,用字节形式存储,如下:
{ 0xF1, 0xE3, 0xC7, 0x8F, 0x1F, 0x3E, 0x7C, 0xF8 }
同上,如果自实现了inv-sbox则会看到以下逆仿射矩阵:
{0xA4, 0x49, 0x92, 0x25, 0x4A, 0x94, 0x29, 0x52}
如果我们在逆向分析过程中看到一个复杂的算法包含(特别是同时包含)以上形式的数组就要特别注意了,它可能大概率是aes算法。
轮常数
位置: 密钥扩展(Key Expansion)阶段使用。
作用: 保证每一轮的密钥都不同,破坏对称性。
生成规则
Rcon 是 8 位的常数序列,定义在有限域 GF(2⁸) 中。
第一个常数是:
之后的每个常数都通过在 GF(2⁸) 上乘以 2 得到(模多项式
)
该常数序列如下:{01, 02, 04, 08, 10, 20, 40, 80, 1B, 36}
如果我们在逆向分析过程中看到一个复杂的算法包含该形式的数组就要特别注意了,它很有可能是aes算法。
总结
关于以上算法的识别今天我就介绍这么多,相信掌握了该技巧的你在后续逆向中会大大的节约时间,有更多的精力集中在应用功能的还原上,而不是深陷在这些公开的密码学算法分析的迷雾中(另外沉浸在迷雾中完全没有意义)。
补充:
我开通了微信公众号,以后会时不时更新内容,欢迎大家扩散!!认准AngelToms!

谢谢!!!
[培训]科锐软件逆向54期预科班、正式班开始火爆招生报名啦!!!
最后于 2025-10-15 14:33
被angelToms编辑
,原因: