在对称加密中,遇到最多的就是DES,AES,其次国内也经常能够看到SM4算法。今天主要对AES进行一个简单分析, 以及一种称之为白盒AES的算法。本文部分内容是从别的博客摘抄。
以AES128
为例,算法如下图:
整个流程分为以下几部分:
其中最后一轮的加密是不需要经过列混合的。 在我们逆向分析中,只要能够想办法识别出这几个过程的特征,基本就能够知道这个算法是不是aes了。
在 Key Init
过程中,根据算法可以知道这个扩展后的密钥是一个 16 * 11 的大小,根据这个特征基本可以判定这个算法是AES算法, 另外扩展后的密钥,第一个16个字节其实是包含了原始密钥的,只不过这个时候,密钥是每4个字节翻转的。 比如ABCDABCDABCDABCD
是密钥, 那么扩展之后的密钥,前16个字节就是 DCBADCBADCBADCBA
。
SubBytes
过程中,需要注意的是, 这个时候会有一个Sbox 参与进来, 在二进制中,通常这就是一个全局变量,可以查看Sbox中的内容来确定是不是AES。 比如,正常 AES 的 Sbox 为
ShiftRows
中,需要知道这个位移的关系
MixColumn
中,会存在一个 4 * 4 的数组, 你可以当作是第一行的4个字节,每次都右移一个字节得到下一行。通过这个特征就能够发现是AES.
1 | 0x02, 0x03, 0x01, 0x01, |
最后是AddRoundkey
, 这个就是输入和最开始的扩展密钥进行抑或的过程,比较简单。
另外在AES中还又一个称之为GaloisMultiplication
的乘法运算, 这个也是一个特征。
上面主要讲到了如何识别 AES 算法,你可以发现,其实 AES 的特征非常多,只要识别出一个点,基本上剩下的工作就是去找key,或者是加密模式(ecb, cbc),从我的经验看,业内基本都是清一色的使用cbc模式,所以需要额外在找一个 iv,不过这个基本就是小菜一碟。 那么如何对AES进行防御呢?
对于一个比较有经验的逆向工程师来说, 混淆已经不能够对识别算法造成太大的影响了,比如可以通过模拟执行,直接不管内部算法,或者通过hook,观察输入输出,大致确定算法属于哪一类。本文不讨论如何对抗模拟执行,只要是一个纯算法,基本都没办法对抗。
对于一个攻击者来说,最重要的是识别出一个算法的类型,一个算法的 key,iv,其他完全不需要 care。
那么如何把一个AES算法改成不是AES算法呢? 这就需要魔改 AES 了,比如密钥扩展阶段,你可以再增加一点别的操作,让前16个字节变异,或者故意更改密钥扩展的长度来迷惑攻击者。再比如,把 Sbox 里的内容随机改动一下,确保生成的结果和标准结果不一致。这种魔改的方式,有一定的效果,但是配套起来就比较麻烦,比如需要给SDK写一套,给后台写一套。
另外对于 key 的保护, 通常就是把 key 用另一个算法保护起来, 需要用到的时候再解密。 见过很多把 key 藏在图片里的,然后不断用key 解密key, 虽然一顿操作猛如虎,但是关键点hook
一下, 关键数据全部出来了。
接下里谈谈 一种AES的变种,白盒AES。
这个算法其实接触过好几次,但是以前一直不知道还能这么玩。
白盒AES的核心是直接把 key 融入到一个表中,这样,AES 算法就变成了一个查表的过程, 攻击者很难拿到原始的key,自然也就无法攻破AES。
在白盒算法中 AddRoundKey
和 SubBytes
可以 和原始的 Sbox
进行合并,构成一个新的Tbox, 每一轮16个表,10轮就会生成160
个表。
最终算法就变成了
1 | state <- plaintext |
从安全性上考虑, 这个算法是优于AES的,因为某种程度上,他都可以不算是一个AES了,只不过他的结果刚好和 AES 一致。 攻击者能够想办法拿到160个表,但是无法拿到原始的密钥(实际有办法拿到:)),这就是一种保护。
从性能上来说,白盒AES将运算转变成了查表,性能上确比原来的 AES要 慢不少了。
从我目前的观察来看,目前大部分应用都是在用普通的 AES 算法,基本上密钥都会使用固定字符串或者是通过 RSA + 随机密钥的方式。 白盒 AES 变种可以很多,但需要对算法本身比较了解,能做白盒的人比较少,所以整体上,更加安全些。