白盒AES破解案例

背景

去年遇到一个 js 版本的 aes加密算法,这个算法有一个巨大的表(4* 256), 基本可以断定是一个白盒aes 算法了, 然后我手工使用 DFA,发现并不能将白盒 aes 的密钥还原,由于当时还原 key 并不是一个强需求,所以在尝试了两次之后我就放弃了。 今年机缘巧合,为了排查线上的问题数据,需要对数据解密,还原key就变成了强需求。我本身是不太想搞的,感觉会投入很多时间并且最终还没有分析出来,但本着事不过三的原则,我还是决定试一下。本文主要是分享一下我的分析过程

已知信息

js经过了强混淆和一定的优化, 原始逻辑无法看清。 知道了一些关键的数据,比如有一个256字节的表,和4个256*4字节的表,另外, 加密的中间过程也能够观察到。

js转c

由于我想使用Deadpool尝试自动化攻击,所以将 js 转换成 c 是一个必经之路。 这块没有技巧,就是直接翻译。翻译的过程中,发现代码也是有规律的,特别是Tboxlookup 和addRoundKey 这块能够很明显的感觉到是一个 for 循环,只是之前的混淆把for 循环展开了。 确认循环之后,代码中每个循环都会用到4 个 int 值, 这些数据刚好组成了roundkey, 另外,之前提到的256个字节的表实际上sbox。 明确roundkeysbox 对于后续排查问题很重要。

编写完c代码之后,我使用DFA进行攻击,但是跑了多次始终没有出结果。 另外,我也尝试了使用DCA进行攻击,这个攻击方式也没有能够得到key。

标准VS非标准

鉴于 Deadpool 无法获取key, 我开始怀疑是不是我做的不对或者 Deadpool 代码有坑,然后我做了几个测试:
1. 我们知道roundkey 是通过 key 变化而来的,那么我们可以使用 aes_key_schedule 进行还原,还原后发现发现密钥不对。
2. 对标准白盒AES 使用 Deadpool 的DFA 攻击,发现可以获取到原始的 key, 但是如果是替换了sbox,则无法获取到key。 这个时候,我开始意识到问题可能在于 sbox 上。分析代码,发现 sbox 涉及到 roundkey 生成和加解密。
3. 替换aes_key_schedule中的sbox, 替换标准AES中的sbox, 生成的roundkey 可以解密, 但是js里的 roundkey 仍然对不上,开始怀疑是不是 key expand 算法被修改了,如果被修改了的话,那就无法拿到key,也就无法解密了!!!
4. 已知算法被修改了过了,我需要确认那些点还被修改过,于是我使用标准的白盒AES代码,逐步转换成js里的AES, 最终确认加密函数中也有小幅的修改(替换字节顺序)

确认改动点

  • sbox经过了改动,我们可以通过sbox 计算出invSbox。
  • roundkey 的生成只和 sbox 有关,修改sbox 仍然无法通过aes_keyschedule 获取正确的key, 说明 keyExpand 算法被更改过。
  • roundkey 由key 衍生,即使没有key,使用roundkey也能进行加解密。
  • TeBox 和TdBox 的生成只和Sbox,invSbox 有关,我们也可以计算出。
  • 结合手头已知的东西(roundkey, sbox, 加密算法), 可以知道,我们已经具备了生成解密算法的原料。那么还差一个完整的白盒demo

白盒破解

找一个 白盒AES demo 花了不少时间, github 上要么只有加密算法, 要么就是看不懂的算法,能够使用的代码很少。

开始我找了link, 只有加密算法,但代码质量不错(我看得懂且跟非标准的aes 相近)。我的想法就是补齐解密算法,这里有个风险点,我并不知道我能否完成解密算法,所以我又找了好些个白盒解密算法(go ,c,java),经过一番尝试,我发现这个 Tboxlookup 大家写的都不一样,我没有办法一下子解决问题。 到这个时候,有点小慌,如果解决不了,可能前面的工作就白费了,要么就直接放弃,要么再找找别的代码看看能不能解密。

最后我找了link,首先确认了加密结果没问题,是一个标准aes。 然后开始改tbox, 这个时候发现代码里的生成方式有bug, 修了bug之后终于把结果跑通了。

总结

针对非标准的AES或白盒AES加密,首先要确认的是算法是否标准。目前只能通过人工对比的方式,将变动的部分找出,然后实现出对应的解密算法。由于改算法的人一般不会把整体框架改掉,所以我们对算法也只要有一定了解就行了。

想要自己尝试一些破解的可以找我要一份demo。