逆向分析及识别恶意代码中的AES算法

1. 引言

AES算法,即高级加密标准,在密码学中又称为Rijndael加密算法。该算法已被用来替代原先的DES算法,并在世界范围内广泛使用。需要指出的是,AES算法不仅仅在合法的场合有着广泛的运用,在各种勒索软件等恶意程序中,同样有着广泛的应用。

本文将分为三部分介绍恶意代码中的AES算法,分别是:

1.基本AES算法的逆向识别; 

2.Locky勒索软件中的AES算法识别; 

3.TeslaCrypt勒索软件中AES算法的逆向识别。

还需要提醒各位读者的是,各种勒索软件的加密手法普遍比较复杂,AES加密仅仅是其全部加密过程中的某一个环节,不要误以为这些勒索软件仅仅这点手段而已。

2. 基本AES算法及其逆向识别

可以通过各种搜索引擎找打大量的基本AES算法介绍与实现,这里不再做深入探讨,仅仅介绍下本文需要用得到的内容。参考《现代密码学》一书,基本AES算法的流程可以用下图概括:

其中,轮函数包含四部分:1,字节替换;2,行位移;3,列混合;4,轮密钥加。识别基本AES算法的关键也就是识别该轮函数。

在github上可以找到Dani Huertas写的关于AES算法的简单实现,点击本文末尾“阅读原文”可查看。该项目中有很完整的注释信息,可以下载并编译,用来学习逆向识别AES算法。

逆向识别标准的AES算法最关键的是找到置换表s_box,在AES算法中该置换表为固定的256元素数字:

s_box的内容过长,这里不做展示。如果顺利找到该表,那么所用的加密算法很有可能就是AES算法。

此后,再查看一下是否存在形式如下的赋值语句:

mov     al  ,  [esi + eax] 

mov      [ecx + edx - 1]  ,  al

截图如下:

是否存在列混合矩阵的几个关键常量:0x02, 0x01, 0x01, 0x03:

以及是否存在与密钥的异或操作,并存储异或结果的操作:

当以上所有结果都判断为真,那么已经可以认定为基本的AES算法了。

3. Locky勒索软件中的AES算法识别

Locky勒索软件并非用受害者的文件内容作为明文进行AES加密,暂且不管其如何进行具体的细节操作,其加密的过程离不开AES算法。Locky中的AES算法识别相对比较简单,下面先介绍一下与之相关的基本知识。

2010年以后,Intel公司生产的大部分CPU包含了一些列用于处理AES加密和解密的指令,这些指令包括生成轮密钥的AESKEYGENASSIST,用于加密的轮函数AESENC,用于最后一轮加密的AESENCLAST等等。这些指令可以极大的提高该CPU处理AES算法的速率。而在Visual Studio中,其Visual C++编译器以内联函数的形式支持使用这些用于AES加解密相关的指令。

通过MSDN可以了解到,在wmmintrin.h头文件中_mm_aeskeygenassist函数、_si128_mm_aesenc_si128函数以及_mm_aesenclast_si128函数可以用于使用上述提到的AESKEYGENASSIST、AESENC以及AESENCLAST指令。借用MSDN中的样例,编译如下图中的代码:

通过调试器可以观察到结果如下:

其中,aesenc xmm0, xmmword ptr [ebp-60h]指令即为_si128_mm_aesenc_si128函数的编译结果。

当有了以上的基础知识之后,便可以考察勒索软件Locky的AES加密代码,如下图:

上图展示了Locky中用到的AES加密10次轮函数,很规范,也很清晰。

4. TeslaCrypt勒索软件中的AES算法识别

TeslaCrypt勒索软件的加密过程十分完善,本文并不打算分析其加密流程。只讨论其对用户文件进行加密的AES CBC算法,其中CBC为一种AES加密模式,这里也不做叙述,仅讨论AES算法本身。

在第2章和第3章中AES算法的实现是依据AES算法描述而来的。而在实际运用中,更多的是使用查表法进行AES加密的算法。用查表法实现AES算法可以以一种较快的速度完成AES加密和解密,是一种以存储空间兑换消耗时间的方法。但就目前的计算机存储空间来讲,查表法牺牲的存储空间也是微不足道的。

根据AES算法的轮函数,可以建立4张置换表,通过查询这4张表,并与该轮的密钥进行异或,可以直接得到该轮加密的结果。其伪代码如下:

t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[round*4]; 

t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[round*4+1];  

t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[round*4+2];  

t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[round*4+3];

上述代码中 ,t0、t1、t2、t3分别为本轮加密结果的第0个四字节,第1个四字节,第2个四字节,第3个四字节;s0、s1、s2、s3为上一轮加密对应的4个四字节。Te0、Te1、Te2、Te3为4张256元素的置换表;rk为轮密钥,round为当前轮数。

Te0、Te1、Te2、Te3这四张表可以通过展开“列混合”操作的数学表达式而得出,限于篇幅问题,这里略过。此外,这四张表互相之间有一些重叠覆盖的关系,通过这些关系可以有效地压缩存储空间。在TeslaCrypt勒索软件中,就建立了如下的一张表:

注意,截图中的表格内容不全,完整的表格总共0x800字节(即2048字节)。

仔细观察上表前8个字节:00 63 63 A5 C6 63 63 A5,其中:

后四个字节:C6 63 63 A5 构成了Te0表的第一项; 

中间四个字节:A5 C6 63 63 构成了Te1表的第一项; 

中间四个字节:63 A5 C6 63构成了Te2表的第一项; 

前四个字节:63 63 A5 C6构成了Te3表的第一项。

以后内容同理。

基于此,可以考察TeslaCrypt勒索软件的加密函数,提取其加密的轮函数如下:

如上图的轮函数中,进行了16次查表,与上文中的伪代码相吻合,最后结尾的两个xor是与该轮密钥进行的异或操作。识别此种AES算法的关键就是找到其置换表,如果能够找到该表,那再结合后续的判断就可以肯定所用算法为AES算法了。

5. 小结

鉴于AES的普及程度,有必要对基本的AES算法有所了解。本文结合最近比较横行的勒索软件逆向分析了几种常见的AES算法,并给出了一些简单的判断依据。笔者忠心希望本文能给读者一点启发和帮助,但由于笔者知识有限,才疏学浅,文中不当或错误之处还请各位读者包容和指正。


推荐

  • QQ空间

  • 新浪微博

  • 人人网

  • 豆瓣

取消