WannaCry(又叫Wanna Decryptor),一种“蠕虫式”的勒索病毒软件,大小3.3MB,由不法分子利用NSA(National Security Agency,美国国家安全局)泄露的危险漏洞“EternalBlue”(永恒之蓝)进行传播 。勒索病毒肆虐,俨然是一场全球性互联网灾难,给广大电脑用户造成了巨大损失。最新统计数据显示,100多个国家和地区超过10万台电脑遭到了勒索病毒攻击、感染。勒索病毒是自熊猫烧香以来影响力最大的病毒之一。WannaCry勒索病毒全球大爆发,至少150个国家、30万名用户中招,造成损失达80亿美元,已经影响到金融,能源,医疗等众多行业,造成严重的危机管理问题。中国部分Windows操作系统用户遭受感染,校园网用户首当其冲,受害严重,大量实验室数据和毕业设计被锁定加密。部分大型企业的应用系统和数据库文件被加密后,无法正常工作,影响巨大。——百度百科
1)分析环境:Win7 x64(虚拟机) 2)调式环境:Win7 x64(测试虚拟机) 3)分析工具:IDA、微步云沙箱、x64dbg、PE.Tools、010Editor、Exeinfo PE、Resource Hacker、Hash & Crypto Detector
1.基本信息: 样本名称:wcry.exe 样本类型:PE32 executable (GUI) Intel 80386, for MS Windows 样本大小:3514368 MD5:84c82835a5d21bbcf75a61706d8ab549 SHA1:5ff465afaabcbf0150d1a3ab2c2e74f3a4426467 SHA256:ed01ebfbc9eb5bbea545af4d01bf5f1071661840480439c6e5babe8e080e41aa 2.节区表: 4.导入表: 3.资源表:
这个样本我怀疑不是完整的,应该是将恶意部分的关键代码去除了(防止被二次利用)。下图是主程序wcry.exe的执行情况: 主要执行流程: 1)使用计算机名求出一个随机的唯一ID。 2)判断是不是有“/i”参数 如果有: 1>创建一个临时目录,这个目录的选取是经过很多兼容处理的。如果手动查看的话可以到以下几个目录中寻找: C:\Windows\ProgramData\ComputerRid C:\Windows\Inter\ComputerRid C:\Windows\ComputerRid C:\Users\Administrator\AppData\Local\Temp\ComputerRid 这里面的ComputerRid就是第一步中生成的计算机唯一ID 2>然后将自身复制到临时目录中 3>创建自启动服务(临时目录中的自己)服务名:ComputerRid,参数:cmd.exe /c "%s" 4>创建新的进程(临时目录中的自己) 3)保存自身的运行目录到注册表中: HKEY_LOCAL_MACHINE/Software/WanaCrypt0r 创建失败则 HKEY_CURRENT_USER/Software/WanaCrypt0r 键值:wd->SelfDir(自身所在目录) 4)释放核心资源2058(0x80A),该资源是一个zip压缩包,解压密码:WNcry@2017 5)随机选取一个比特币账号,并更新到c.wnry文件中。 最终会显示到界面上 6)隐藏文件命令:attrib +h . 7)增加everyone用户权限:icacls . /grant Everyone:F /T /C /Q 8)从Kernel32中动态载入CreateFileW那一套API接口 9)解密t.wnry文件,该文件内汇聚了核心功能。且导出接口为:TaskStart t.wnry使用的是Rijndael S-Box(AES)的一种加密算法,可以使用Hash & Crypto Detector工具来检测加密算法。但这里AES所使用的key是包含在t.wnry中的,结构如下: 结构如下:
AES解密用的Key也需要解密,使用的是系统自带的解密API,也就是之前载入过的那一套解密API,如下图所示: 这里的解密密钥是保存在进程内存中的,如下图:
当到这里的时候发现,加密Key的是一个RSA2的算法,上面的数据应该就是一个私钥。但这里并不能确定t.wnry.dll的加密用的就RSA,因为RSA加密是很慢的,所以通常都不会直接对内容加密的,而是像类似的https一样,将key用私钥解密,然后再用key进行对称加密。这样不但可以起到保护作用,而且也不会影响传输速度。 RSA解密之后得到的是一个16字节的Key,如下:
而且到了下面的t.wnry的解密明显更换了解密函数,大致猜测应该是一个AES的对称加密算法。接下来将这个Key导入到AES中,最后解密t.wnry。 10)解密t.wnry后,会在内存中直接动态加载解密后的t.wnry。 11)最后启动t.wnry导出的TaskStart接口
这里为了分析方便,所以先将内存中的t.wnry.dll文件dump出来。dump的方法如下: 1)使用x64dbg动态调试至解密后的地方,然后记录解密内容的首地址和长度。 2)使用PETools工具将wcry.exe进程的内存dump下来(右键菜单Dump Partial)。
t.wnry.dll的内容很多,大致可分为以下几类: 1) 在本地生成一组“密钥对”,公钥为00000000.pky和私钥00000000.eky(被加密)。 2)生成一组随机字节,保存至00000000.res文件中 3)检测00000000.dky的有效性。这个dky应该就是和解密有关系的key。 4)监控新磁盘的插入,并加密。 5)启动taskdl.exe尝试删除文件。 6)对全盘进行加密。 IDA反编译代码如下: 可以看到,后面会创建很多的线程并发的跑一些任务。
核心的流程在最后面的全盘加密这里,下面分析一下里面的流程: 1.将u.wnry文件复制一份为@WanaDecryptor@.exe文件。 2.生成一个用来创建@WanaDecryptor@.exe快捷方式的批处理: 几个参数:当前目录,@WanaDecryptor@.exe.lnk,当前目录,@WanaDecryptor@.exe 3.从r.wnry中读取提示信息,并且将其中的变量替换为本机信息。并且生成一个@Please_Read_Me@.txt的提示文本。 4.优先将桌面和我的文档进行加密,并在加密的文件夹中放置三个文件: 1)@Please_Read_Me@.txt 2)@WanaDecryptor@.exe 3)@WanaDecryptor@.exe.link
5.关闭一些特定进程,防止这些进程占用文档,导致加密失败。 6.枚举所有磁盘,对一些主要的办公文档进行加密。
这里可以看到,勒索病毒并不会对exe和dll进行加密的,所以电脑还可以正常运行,仅仅是对你的办公文档进行加密。 7.将你的桌面壁纸改成加密提示语: 8.使用垃圾文件塞满你的磁盘 以上就是t.wnry.dll中的一些关键流程。下面看一下病毒的运行效果: 可以看到桌面上的文档已经被加密,并且后缀名也被改为了.WNCRY。
其实对于勒索病毒的行为分析,网上类似的文章很多,这里就不再进行过细的分析了。 经过这次分析,我们可以获得两个关键的信息: 1.如何第一时间阻止病毒。 2.如何清除病毒。 以下操作可能会为你挽回部分损失: 1.当你看到桌面上的文件被加密后第一件事就是关机!因为这个病毒是优先加密桌面和我的文档。之后才会去加密全盘,这个时候你还是有机会抢救自己文档的,尽可能的避免损失。关机就是中断病毒运行的最直接方式。 2.记住当你看到那个窗口弹出来的时候就已经迟了。 3.进入计算机的安全模式,然后到注册表:HKEY_LOCAL_MACHINE/Software/WanaCrypt0r中寻找病毒所在位置。这里专门记录了病毒位置。 也可以在HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run中寻找自启动项。查看病毒的启动文件。 4.找到病毒所在目录后,把里面的文件都清理了,尤其是那些个exe。 5.然后找一个安装有PE系统的U盘,再找一个大一点的移动硬盘。开机进入PE系统,这里不要挂载你自己的系统,因为病毒可能有容错处理,不一定都放在上面的地方。而且也会存在变种病毒。进入PE后将重要的文件备份到移动硬盘中。 6.这样下来,也还能抢救一些资料吧。
其实大家非常关心的就是加密的文件到底怎么办,除了给钱还有没有别的办法。其实理论上没有作者的私钥是永远无法解密的,下面就来详细分析一下勒索病毒的加密过程。
1.在本地生成一组密钥对:私钥A和公钥B 2.然后作者使用自己的公钥C对本地的私钥A进行RSA加密 3.加密文件前再生成一个16位的随机Key来 4.使用本地公钥B对随机Key进行RSA加密,然后再保存到加密文件的头部。注意:每个文件的加密Key都是随机不同的。每次加密都会重新生成key。所以同一个文件的两次密文是不同的。 5.然后使用随机Key对文件内容进行AES对称加密。 下图是密文结构: 下图是同一个文件的两次加密对比: 以上就是勒索病毒的加密的大致过程。现在看一下这个过程可不可逆,有没有可能解密。
1.首先被加密的文件使用的是一个对称加密算法,这里通过检测是一个AES算法。AES对称加密使用的是一个随机key,而AES的解密只需要拿到这个随机Key就可以了。 2.这个随机key是保存在加密文件头部的。也就是说这个key是可以直接读出来的。但关键是这个key是被加密过的 。 3.而加密这个Key使用的是RSA算法,这是一种非常强大的算法。类似的https就是这样的算法。他采用的是公私钥进行加密的,这种算法被称之为非对称加密算法。顾名思义,加密Key和解密Key是不一样的。RSA的加密使用的是公钥,而解密使用的却是私钥。这里的公钥是无法直接对密文进行解密的,只负责加密,所以公钥本身是可以对外公开的。这也就是https为什么安全的原因了。我们通常看到的网站证书中就包含了一个公钥,而私钥只保存在服务器上。 4.现在这个随机Key就是被本地生成的公钥所加密。也就是说,想要解密这个Key,必须使用本地私钥才行。但真正的问题出现了,这个私钥同样也被加密了。而加密他的正是作者的公钥。也就是说,想要解密这个本地私钥,就必须拿到作者的私钥才能解密。而作者的私钥显然只能打钱获得。 5.这就是为什么勒索病毒无法破解,只能割肉的原因了。
作者公钥->本地私钥->本地公钥->随机Key->加密文档 整个过程都是环环相扣的。如果想要解密你的文档,可能只有将你的私钥提供给作者,然后作者再使用自己的私钥将你的私钥解密。然后在发送给你一个未加密的私钥。最后你使用这个私钥来解密自己的文档。
所以没有作者的私钥就永远无法解密文档。但本着探索的精神,再次深入分析加密过程: 1.为什么这个算法会同时出现RSA和AES两种算法,而不是直接使用RSA呢?既然真正安全的是RSA,那为什么又需要使用AES来加密呢。 2.根本原因就是RSA的非对称加密非常慢。为了弥补这个缺陷,所以通常非对称加密都是配合对称加密进行的。 3.而AES对称加密的速度就非常快,但AES的加密本身是不安全的,原因就出在Key上,因为加解密的key是相同的。所以被截获了Key就等于完全破解了AES。所以为了弥补AES的不足,就使用RSA对这个key进行加密,这样别人就无法破解key,也就无法破解AES。类似的https就是采用这样的方案进行传输加密的,即安全又快速。 4.但这里似乎有个问题,那就是每一步的加密都是在我们的眼皮底下进行的。也就是说明文一定在我们的电脑上出现过。如果我们在内存中拦截AES的加密Key,是不是就可以拿来解密呢?现实总是残酷的,作者非常聪明。每一次AES的加密Key全部都是随机。也就是说你拦截到的Key不具有通用性,只能解密拦截的文档。 5.那能不能再往上拦截一层,去拦截本地的私钥明文呢。很不幸,依旧不可以。因为私钥对一旦生成,就是唯一的一对,如果你尝试将上一对删了,重新生成一对。那这两对是完全不一样的。所以这个过程是不可逆的。也就是说只有在他生成第一次密钥对时拦截才有可能。而第二次重新生成就没有意义了。 6.那我们就尝试拦截第一次密钥对的生成,可这个生成是在病毒刚刚发作的时候进行的。我们是不可能预知这个操作的。但这里可能存在一个漏洞,就是生成的明文私钥,还可能残留在内存中,只要原来的明文内存没有被覆盖掉,那就有可能在内存中找到。这就是一个希望,类似于磁盘恢复一样,在内存中恢复私钥。但现实依旧是残酷的,作者再次证明了他的智慧,细节简直令人咂舌。如下图: 他居然在用完后还会故意清空这块内存T.T!GG。。。如果有什么问题请不要@我,直接上香就好了。
逆向的世界竟是如此美丽,甚至看着看着就落泪了。。。作为一个码了7年的程序猿,如果把虚拟世界比作游戏的话,那么编程敲代码就像是人机,自己和自己玩。而逆向工程就是排位赛,你永远都不知道自己的对手是怎样的人,只有强者才配站在顶点! 虽然之前也有很多人分析过勒索病毒,但依旧发出来的原因有以下几点考虑: 1)分析细节不同 逆向分析本就是一个不断猜测的过程,所以对任何一处的分析都有可能产生错误。而此时如果能有多方参考,则会大大提高分析的准确率。尤其是一些新型的病毒,分析文章越多,这个病毒就会越透明。逆向工程从来不是一个人的工作,也不应该是一个人的工作。就像一个成熟的产品,都是由无数程序猿铸建而成,逆向此类产品无异于大海捞针。当我们面对一个庞大组织时,就需要更多的逆向者参与进来。每个人分析一部分,每个人修正一部分,与那个从未谋面之人共同努力。这也许就是属于逆行者的默契吧。。。 2)分析工具的不同 工欲善其事必先利其器。逆向工程的捷径就是拥有大量趁手的神兵利器。每个人分析时所用的工具可能都会有所差异。这就像地摊淘宝一样的刺激,更何况是白嫖呢[狗头]。 3)记录成长的过程 作为一个7年的程序猿没有写过一篇文章,而现在回首过去,曾经研究过无数的技术也逐渐随着时间而遗忘。这可能就是职业生涯最大的悲剧了吧T.T。。。所以,骚年们,拿出你的笔,说出你的故事,这样的回忆才能更精彩,这样的论坛才能生生不息。
typedef struct _EncryptFile{
char szFlags[
8
];
/
/
WANACRY!
DWORD dwKeyLen;
/
/
key秘钥长度
char szEncryptKey[dwKeyLen];
/
/
被公钥加过密的key
DWORD dwType;
/
/
一个类型
DWORD dwLowLength;
/
/
内容长度
-
低
4
位
DWORD dwHigLength;
/
/
内容长度
-
高
4
位
char szContext[];
/
/
AES加密密文
}EncryptFile,
*
PEncryptFile
typedef struct _EncryptFile{
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-5-14 17:01
被musilintan编辑
,原因: 格式整理
上传的附件: