写在前面的话
在我们之前的文章中,我们对一款恶意软件所使用的加密算法进行了分析,并使用了ShiOne勒索软件来作为加密技术演示,那么在今天的这篇文章中,我们将跟大家介绍如何去破解一个加密算法。
加密算法其实是非常强大的,为了破解一个加密算法,加密算法本身必须具备一定的设计缺陷。设计加密算法的人可能会忽略某个因素,而破解加密算法的难度就在于我们要去识别并分析程序员所使用的加密方法,然后寻找并利用开发人员在实现加密算法时意外出现的安全漏洞。这些漏洞可以是弱加密算法或弱密钥,也可以密钥泄露等等。
定位加密算法
在你尝试去寻找加密算法中的缺陷之前,你首先要知道它使用的是哪种加密算法。其实非常简单,在大多数情况下识别加密算法就跟查找API调用一样容易。下面给出的是我们之前在分析ShiOne时定位到的加密算法:
有的时候,加密算法是静态编译到恶意软件中的,甚至有些攻击者还会使用自己编写的加密算法。在这种情况下,你必须要了解加密算法的内部工作原理,才能够识别出加密代码。
一份文件的内容会在经过加密之后重新写回文件,所以定位加密算法最快的方法就是直接寻找ReadFile和WriteFile这两个API调用,而加密算法往往就会在这两个API调用之间去实现自己的加密功能。
识别加密代码
正如我们之前所提到的那样,在寻找静态编译的加密算法代码时,我们可以通过寻找某些API调用来定位加密算法的大概位置。当然了,对这些加密算法工作机制的基本了解还是必要的。
接下来,我们将跟大家介绍AES加密算法的工作流程。一般来说,大多数同步加密算法的工作流程都比较相似。不同的地方可能是执行的数学计算操作类型不同,但是核心思想都是一样的。因此,我们可以把了解AES加密算法的工作流程作为一个初始起点,然后再对现实世界中其他的加密算法进行分析。
AES是一种对称加密算法,它需要执行一系列数学计算和逻辑运算,其关键因素有下面这三个:
- 明文数据需要被加密;
- 静态字节是加密算法的一部分(查询表);
- 所使用的加密密钥;
一般来说,AES的加密过程是在一个4×4的字节矩阵上运作,这个矩阵又称为“状态(state)矩阵”,其初值就是一个明文区块(矩阵中一个元素大小就是明文区块中的一个Byte)。AES加密有很多轮的重复和变换。大致步骤如下:1、密钥扩展(KeyExpansion),2、初始轮(Initial Round),3、重复轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,4、最终轮(Final Round),最终轮没有MixColumns。
-AddRoundKey — 矩阵中的每一个字节都与该次轮秘钥(round key)做异或运算;每个子密钥由密钥生成方案产生。
-SubBytes — 通过非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
-ShiftRows — 将矩阵中的每个横列进行循环式移位。
-MixColumns — 为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每列的四个字节。
注:最后一个加密循环中省略MixColumns步骤,而以另一个AddRoundKey取代。
AES可以进行10-14轮运算,这也就意味着当你在查看代码中的加密算法时,它将会是一个拥有非常多重复代码的函数,这一点可以帮助你快速定位到加密代码的所在位置。
下面给出的是一轮加密计算的另一个样本,其实对称加密的实现逻辑都是差不多的:
你看恶意看到,运算操作的顺序可能会有不同,不过这不重要,我们又不是加密算法领域的研究人员。一般来说,我们不会去寻找AES算法本身的漏洞,我们要找的是程序在实现加密算法时出现的安全问题。我们之所以要介绍算法的运行细节,是为了帮助你快速识别并定位加密代码。
我们的样本代码是从之前分析Scarab勒索软件时获取到的,它使用了静态编译的AES来加密文件(不涉及API调用)。
我们可以从上面这个流程图中看到,它不仅会对文件加密,而且算法还会对之前的密钥进行加密,这也是我们寻找漏洞并破解加密的着手点。
理论上来说,我们可以一次性使用多种加密算法(结合使用),但是我们需要了解每一个加密算法在整个程序架构中所扮演的角色。只要有一个加密算法没有正确实现,我们就可以想办法破解它。
随机数生成器
在寻找加密算法的实现漏洞时,另一个切入点就是加密密钥生成器,大多数情况下使用的都是某种形式的随机数生成器。可能随机数生成器的重要性大家都知道,如果你可以让随机数生成器强制重新生成之前加密过程中所生成的数值,你就可以获取到原始的加密密钥了。
在下面这张图片中,一个弱随机数生成器使用了系统时间来作为随机数生成种子:
大多数情况下,计算机程序只能进行有限的一系列操作,如果一个函数的输入参数固定,输出也就是一样的。但是对于随机数生成器来说,由于随机数种子的存在,所以相同的输入并不会生成相同的输出。比如说,某些弱随机数生成器会使用时间来作为种子,所以很明显,这种条件是可以复制的。因此,我们要使用足够随机化的输入,才能得到足够的熵。
你可以看到,牛X一点的随机数生成器可以采集音频数据,并使用鼠标点击信息和其他因素来让输出数据尽可能的随机化。
破解弱RNG的理论过程
接下来我们分析一下如何破解RNG这样的弱生成器。我们假设一款勒索软件使用了RNG(以当前时间(毫秒级)作为种子),并使用了标准加密算法。下面就是展开攻击的基本操作步骤:
- 网络管理员分析了勒索软件,并看到了公钥,公钥是用来进行加密的,并作为勒索软件的目标用户ID。
- 网络管理员通过查看网络日志可以知道设备受感染的大概时间,比如说发生在上午10:00:00到10:00:10之间,大概有10秒钟的时间窗口。
- 由于RNG使用的是毫秒级时间,那我们就假设有10,000,000种可能的种子。
- 如果勒索软件使用时间作为随机数种子值-x,那加密代码就要生成密钥对-KEYx。
- 然后从10:00:00开始,利用软件逐个测试密钥对。
- 看看x(10:00:00)是否能够匹配公钥(目标用户ID);
- 如果不匹配,意味着RNG没有使用10:00:00作为种子。
- 接下来测试x+1,依此类推,直到测试到10:00:10。
- 最终,他会得到一个匹配的值。
- 接下来,私钥也是一样的。得到了公钥和私钥之后,就可以恢复被加密的文件了。
但是,如果我们增加了足够多的参数,那暴力破解可能就不太现实了:
实践中的解密
下面给出的是我们成功破解的勒索软件以及所使用的方法:
-7ev3、XORist和Bart:弱加密算法
-Petya:加密算法的实现存在漏洞
-DMA Locker和CryptXXX:弱密钥生成器
-Cerber:服务器端漏洞
-Chimera:密钥泄露
弱加密算法
DES算法诞生于1970年,并且自诞生之日起就得到了广泛使用,但由于其密钥大小的问题,DES已经被认为是一种弱加密算法了。密钥的长度是衡量一个加密算法是否健壮的因素之一,密钥位数足够长,破解所需的时间也就越多。
接下来,我跟大家分析一下如何定义一个安全性较弱的加密算法。一般来说,通过可视化的形式可以帮我们直观地了解加密算法的作用:
大家可以看到,这个加密算法的熵很低,加密后的数据看起来跟原始数据也很类似,典型的弱加密算法。
下面是另一个加密算法,这个加密算法的熵就很高了:
我们可以通过这种方式来迅速了解一个加密算法的健壮程度。
总结
在这篇文章中,我们简单介绍了如何识别并破解一个加密算法,从理论上来说,我们可以从本文所介绍的几个因素来着手,并尝试解密某个勒索软件。