作者:苍酷02
稿费:300RMB(不服你也来投稿啊!)
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
0x01 构成要素和方法
通常,解密勒索程序需要深入了解其使用的算法和发现它勒索过程里的一些缺陷。不同的漏洞需要不同的思路编写破解工具。有时我们需要重写有漏洞的算法,然后编写工具进行密码猜解(比如在破解 Petya的时候)。有时,破解的的部分是对称密钥生成器(如DMA Locker 2.0的情况下)–或算法本身(见7ev3n勒索程序的自定义加密)。
但这次,我们几乎拥有所有现成的资料:
1.使用的密钥(泄露的)
2.奇美拉作者向受害者提供的原始的解密程序
不过有趣的是,我们必须从这些碎片之间找到它们的关系并且以某种方式重新组织它们。
0x02 逆向原始解密程序
正如我们前面介绍奇美拉的分析,受害者交了赎金,作者提供了一个链接,受害人可以下载外部工具解密,但是需要用户购买私钥,匹配对文件进行加密的公钥。
该工具是用.NET编写的并且解密文件解密操作发生在在外部组件—一个命名为“PolarisSSLWrapper.dll” 的dll,输出两个函数:
所以,我们没必要再去重新实现解密函数,可以利用现有的API。
首先我们先去逆向(.NET)的主要组件,来看看这个函数如何被调用以及它需要什么样的参数。我们可以看到外部函数的加载和调用的代码
正如我们在上面看到的,我们感兴趣的是decryptfilewrapper函数。它需要3个参数:要加密的文件的路径(ASCII字符串形式),私钥(以字节数组的形式)和私钥长度。它返回一个布尔值,告知解密文件是否成功。我们可以重建它的头:
bool _cdecl DecryptFileWrapper(char filePath, BYTE* privateKey, size_t privateKeySize);
私钥是从接收到的bitmessage读取,解码base64为字节数组:
奇美拉的基础设施(服务器之类的)几个月之前就死了,所以我们此时看不到真实生活中的流量是怎样的,但是感谢一项发表在 Bleeping Computer的研究,我们可以看到这种信息的结构。例如:
56209A92A96E9F96B0D9E6F962D0D9EF:5Zn9azBBDQQznI9znnHZBDs6+nQz6nB9/6DBa0nXbDz0aghs6fg62Rn9ZzxnDGEzRQ9tFdIZDfa05Lz+nlb6IGnzSDQz0tznrdUzGgq9Nibzx0Zusl2aHn6nzZZE6tbQQe/vzbASDuanTBL5SazSARe52QSq6BEzD5rGqzZhnaLaZrfbI6bN6A6nnnH5lgbeSAzXdz+6eNxqQt9ITziIxF+eDFBBBVZ+zHf6esQzzH2uBnQnaHzzi6tDna9Xngfh6bzQQZBfq+vFbZ9ZfvnTL6D2arAnBzb6A06Qzfn2zRD5hz5eLZzDIDR00/anblbU2bvRTH6ZGaXDeBQQ5NHGhQEAAdZBtx/VaVQsrrDZdasadBHi0RDeZz0Da6glNRz9/U59zXaaeAN0Di5eb2zQtvr5h6Fvb6tzB9THtRUGS6Qzt6BxAz/zTg6gs56h5xXzSnslBQRzngandHzFTaBHix692DLxDaziQnZBQDQRB/Zz5HXQfNzz5aad90+uHAsDBDDVzZsngtbgSHDTzA2X5zQs2tHba5z99qF66IQHqZaZD2erzuDQzzx9NlXaTZEiH2IrVGSZizxEFQzLBl6+BDDn5zuG6x6zBhfaNB56nDUXt6BnzzuvNVq2xzDTn2lSu/QrHzNbFdGSLazTh29z5Fx9D5Zt6QBBrQ+aFuNDhASgDDH20UDnQB00gBa2t6/i+Lq6eV9ZHzzDdEn2T6HXfg+BEnvr5tXB5zZL2zbtvBVxFX2QsBZ9ZrzzG6fIvnvnz6NZ5endiz0IzAQ2Dbqa6gnnsSnznsVIizznibdZIFvF/nsqbVQZB9Zn2nBQUDTQzzDT65NxHzLRvz6VzZsQV5bih+S+shaD6ASaDFzHNQD9ZVIi+ZrafBxes6zqQaBfEs6z+Igd6nZhEzDLZZN/9QbhQzlzfBf5IFL0nqt2qqnSeqgz0bzQgZ9Dq6r50SB6xHhn9DfnNa6hR0DUiubDH5z0+n60UD0Uzz6ti6faD5Sz99f6dtQN6LUfZn/RagfiqnzTXZrvBZv95a9aT9u9tE6qLH0BSNArn0I9rF2eBDQH92zFUBBBVs9e/ZrXZ2Qaz/zn6BzxQ05qtqNQTZ6AS22z6nBf/200L66zasDHrzZ9agHAx2qBNUlRaUDFszInzzaLD5IzGQeQaAU60zz6nZQvVe906uDTXGlaZDDfBQUzD/nRDrZUaa2h59Hf5gbeezTHNiHBaBDzzQBx0BX5Zz92Z2zanfSZZ/2BRnzzzQBzxa/iIxiDNb6Qdd9Bh6/FQnfeznSv5rZ6DZitTGZZUAdzgD5azVAn2G/G+EssFuhV5aBb0N/N2q+2656zgxBBDzn2+0NIZLudxTXRsDNDza0V/9gzzEaqBdZax6QDlfnQhAVIn9XZu/D+gr9+ZRqz5266IBST5E5LBZed/s0zS2QHeBrIHnznZtez+02+Q+50g+ZUD6nrbhR2f+NzB6NgZ6ID9e5hnEEQ99xlnSDZT2aQN6QBRueDRZzNaTz6bvQrGhaBaeFl96hZDZLUDIu6rAzB
这是 [victim ID]:[base64 encoded key]
我们解码key之后 得到了1155(0x483)字节的字节数组。
可以看出,那个DLL需要的私钥就是这些字节数组.
0x03 解析密钥
泄露的密钥是一个十六进制字符串。如果我们将其转换为raw格式,它们的长度都是0x483字节。这是一个好兆头,因为格式同上,并不需要额外的处理–只要完成从十六进制到原始二进制的基本解析。泄漏的文件有一个一致的格式。每一密钥都以一个新行结束。我们可以删除开头的信息并且使用这个文件作为输入:
确切的说:上面材料被称为一个私有密钥组(在公告由谁泄露了他们的个人以及在原始解密的代码),在现实中是一个键-值对。每一对都分布在一个连续的块,0x483字节。第一0x103字节包含公钥,然后0x380–私钥。使用的DLL API预计这满斑点作为“私钥”–但由于他们都过去了,它可以自动验证解密的结果。
0x04 寻找正确的密钥
我们可以看到,大部分的工作已经完成了。唯一剩下的就是寻找是否泄露的文件里存在可以解密我们文件的key。
在这种情况下我们必须使用类似于字典撞击的方法,我们的“词典”是一套泄露的密钥。作为验证我们将尝试解密其中一个加密的文件。大致思路用下面的伪代码描述:
while ((privateKey = getNextFromSet()) != NULL) {
if (DecryptFileWrapper(encryptedFile, privateKey, privateKeyLen) == true) {
printf("Hurray, key found!");
storeTheFounKey(privateKey);
return true;
}
}
printf ("Sorry, your key is not in the leaked set!");
return false;
你可以在这里找到所有的代码:https://github.com/hasherezade/chimera_decrypt
在找到匹配的key后,我们可以使用同一个DLL用它来帮助其他的文件进行解密。
0x05 测试
测试1
奇美拉在每一次执行开始时生成一个唯一的.随机的的keypair,然后和其他数据一起在 bitmessage 发送它到 C&C
为了测试,我用的key是原来奇美拉勒索样品产生的,我们可以清楚的看到key被传递给了一个用来通过biemessage上传递材料的函数(下方的截图中可以看到他被选中)
我将它转换成与泄露密钥相同的格式(连续的十六进制字符串)。
准备的解密工具工作了 测试文件已成功解密:
测试 2
由于在泄露的材料中我们有完整的密钥对,可以用于测试目的。在这个实验中我从泄露的blobs剪出了公钥。然后,我把它部署到原来的奇美拉样本。这一招可以让我们生成加密样本件,来模仿密钥泄露的受害者的文件。
下面–用泄露的密钥集里的密钥替代所产生的密钥的公钥:
我们可以尝试使用泄露的密钥集去准备解密文件。
本实验证明,所提供的材料里含有真正的密钥对,而不是垃圾数据。
0x06总结
泄露的文件包含的有密钥对,可以帮助我们解密文件,但是由于奇美拉已经死亡几个月,大多数受害者已经删除了加密文件,但是对于我们解密勒索程序提供一种新的思路。
还没有评论,来说两句吧...