记一次详细的勒索病毒分析

第一次写病毒分析的文章,之前表哥丢给我一个样本断断续续分析了好几天才搞明白,如有任何错误,还请各位多加指点

0x01 样本概述

样本名: 1.exe

MD5: 612974dcb49adef982d9ad8d9cbdde36

SHA1: b817e361bd0cc1819d7f6a1189f0f5d56ed48721

样本下载:

https://pan.baidu.com/s/16TZDcJdgIS1gZWaUwzIfpg (解压密码 x-encounter)

分析环境及工具:

winxp sp3、IDA、OD

0x02 相关文件

1.exe: 样本主体

shellcode.txt: 主体解密后的 shellcode

dump.exe: shellcode 执行后的新 PE 文件

a.bat: dump.exe 释放出的批处理文件,用于善后工作

a.txt..doc: 加密后的文件样本

Read___ME.html: 勒索信息

0x03 行为预览

1.exe (样本主体行为):

1、简单的反调试技术,调用无效循环及无效的 API 迷惑分析人员

2、从数据段解密出 shellcode,并显式调用 VirtualProtect 使 shellcode 可读可写可执行,接着运行 shellcode

shellcode.txt(shellcode 行为):

1、获取 Kernel32.dll 的基址、获取函数地址、解密新 PE 文件

2、使用进程替换技术,将老 PE 文件的内存空间替换为解密后的新 PE 文件,修复新 PE 文件的 IAT,接着跳向新 PE 文件的 OEP

dump.exe:(新 PE 文件的行为):

1、解密数据,获取系统信息,释放到系统路径,打开注册表添加启动项

2、创建文件,保存用户 RSA 公钥以及 用户 ID,并生成勒索信息

3、遍历所有进程,如果发现指定进程 kill 掉

4、创建加密线程,遍历文件并加密文件并将文件的后缀名改为 ..doc,创建勒索信息文件

5、释放 bat 文件到临时目录,创建进程并执行

6、自删除

a.bat:(批处理文件的行为):

1、删除卷影副本

2、删除指定的注册表项,添加指定的注册表项

3、删除日志信息

勒索信息如下:

0x04 详细分析

1.exe (样本主体分析)

首先使用 PEid 查壳

将样本主体载入 IDA,定位到入口函数,发现有大量无关 API

并且在 0040127D 处会进入一个无关的循环,判断 var_8 的值等不等于 8B9A6F96h,可以 nop 掉,也可以在 0040133F 下断直接让程序执行过来。

紧接着调用 GlobalMemoryStatus,获取内存信息,在 004013EF 处调用 LocalAlloc 分配了 8700h 的空间

分配空间之后进入左边的条件分支,将偏移数据(加密的 shellcode )复制到刚刚分配的空间,之后进入右边的条件分支,对 shellcode 进行解密,解密函数如下

对加密的 shellcode 分组,通过一个循环,每 8 字节一组,对这 8 字节调用 sub_4015C0 进行解密,该函数的第三个参数为解密 key,解密后的 shellcode 如下

从内存中 dump 出来,保存为 shellcode.txt,接下来通过字符串拼接的方式,显式调用 VirtualProtect

OD 中查看参数,将 shellcode 的内存区域变为可读可写可执行

接着调用 shellcode

shellcode.txt(shellcode 分析)

IDA 载入 shellcode.txt,发现 shellcode 只有两个 Call。

进入第一个 call,该函数通过 fs 寄存器获取 Kernel32.dll 的基址

接着通过解析 PE 文件,获取 PE 头,接着获取数据目录第 0 项也就是导出表的地址,接着在导出表中获取 GetProcAddress 和 LoadLibrary 的地址,然后返回

我们进入 shellcode 第二个 call,如图,观察此处的 eax 所指向的地址的值

很明显这是一个经过加密处理的 PE 文件,那么在 MZ 字符之前的值是什么呢?

经过后续的分析,我们可以了解到,这一段内存实际上是以 "新 PE 的参数+加密的新 PE" 这样的结构存储的,结构的详细分析如下图

然后通过之前获取的 GetProcAddressLoadLibrary 的地址,来动态获取其他函数的的地址

函数地址获取完后,调用 GetVersionExA,判断 dwMajorVersion 等不等于 6

接着分配内存,并调用解密函数,该函数的两个参数是通过 "新 PE 的参数" 这个结构获得的,解密函数大概是通过分组的形式,逐步对 PE 进行解密的,解密的关键一个是索引值,一个是 key 都在 `"新 PE 的参数" 这个结构中,解密后的 PE 文件如下图

紧接着调用 VirtualProtect,目标地址是 400000,也就是老 PE 文件的加载基址,将其属性改为可读可写可执行,为后面的替换做准备。然后将 400000 处的值清零,开始复杂的 PE 操作。

首先通过 DOS 头的 e_lfanew 获取 PE 头的偏移,找到 PE 头之后将 PE 头偏移四个字节的数据(也就是 Machine)存到局部变量中,然后通过 PE 头偏移 14h 处也就是 SizeOfOptionalHeader 获得 OptionalHeader 的长度,之所以计算各个段的长度是为了获取最后一个节区的偏移,通过偏移把解密后的新 PE 的 DOS 头,PE 头和节表头复制到 400000 的内存空间中,之后从 "新 PE 的参数" 中获取新 PE 的 EP,修正 EP,最后解析节表头获取节表的 pointerToRawData,准备进行节表数据的复制。

右边分支为复制节区数据,由于新PE文件只有一个节区所以循环只有一次,这里不做过多的解释,重点在 IAT 的修复上,当右边分支执行完后,会执行左边的分支,首先会释放掉解密后的新 PE 文件,通过 PE 头的偏移获取 DataDirectory 数据目录表,在表中接着获取 DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_IMPORT] 的 RVA 也就是导入表的 RVA 和 Size,进行修复,而且还对 DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] 资源目录项的 RVA 和 SIZE 也进行了修复,由于 DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_IMPORT] 的 RVA 指向 IMAGE_IMPORT_DESCRIPTOR 结构体,接着比较该结构体的 Name字段是不是等于零,如果不为零,如下图

调用 LoadLibrary 载入导入的 DLL,之后判断 IMAGE_IMPORT_DESCRIPTOR 结构体中第一个字段,也就是 OriginalFirstThunk 是否为零,如果不为零,接着获取 IMAGE_IMPORT_DESCRIPTOR 结构的第 5 个字段,也就是 FirstThunk,通过 FirstThunk找到 IMAGE_THUNK_DATA32 结构体的 AddressofData 字段,通过 AddressofData 找到获得 _IMAGE_IMPORT_BY_NAME 结构体中的 Name字段,也就是该 DLL 导出函数的名称,之后调用 GetProcAddress 对其进行修复。修复 IAT 的操作一共有两层循环,外层循环遍历所有的导入的 DLL,内层循环对 DLL 导出的函数进行修复,在 OD 中如下

修复完 IAT 之后,调用 atexit 注册终止函数,最终跳转到新 PE 的 OEP

折腾了半天终于见到了病毒的真身

dump.exe:(新 PE 文件的分析)

我们通过 LoadPE 将此时病毒的内存,转存下来命名为 dump.exe,载入到 IDA 中,由于 dump.exe 可能用了一些对抗反汇编的技术,导致 IDA 无法判别哪些是数据哪些是代码,我们可以手动将其转换,但即使转换成功后也无法正常反编译,加大了我们的分析难度,只能通过 OD 一点一点的单步进行分析。

我们进入函数入口处,步入第一个 call,先分配了 5 个堆空间,接着获取病毒文件的完整地址和系统的临时目录

之后进行对相关字符串进行解密的操作

大概算法是解密了一个 256 位的 key (怀疑是黑客的 RSA 公钥),用对 key 进行操作然后与加密的字符串进行异或,两次解密后的字符串如下

接着调用 00409FE7 处的 call sub_409CB8 解密函数,将解密后的数据(一些 windows 上常用的软件名称)以.为分割符分为 43 个字符串的首地址存放在分配的内存地址中。

以同样的方式解密 401430 处的数据(系统环境之类的参数),之后通过系统环境变量获取 appdata 的目录,进行字符串拼接,之后调用 CopyFile 将该病毒复制到 appdata 目录,这两次解密的目的是对某些特殊字符的文件夹进行绕过

C:\Documents and Settings\Administrator\Application Data 下可以找到该病毒的副本,接着在 0040A088 调用与注册表有关的函数,为了常驻系统。

继续获取系统目录 C:\Documents and Settings\All Users,并通过一个加密函数生成一个固定的 Hash 值,接着进行字符串拼接,最终调用 0040A11A 处的函数创建文件

进入 0040A11A 处的函数,创建文件,写入文件,文件内容是通过复杂的加密算法生成的用户 ID,这里我们只要了解一下病毒的行为,具体加密流程在加密部分会详细介绍,创建的文件如下图

之后对勒索文档的内容进行解密,勒索文件的组合分为三部分

第一步先将解密后的数据前64E部分复制到分配好的缓冲区中

第二步将之前提到过的用户 ID的部分数据复制到第一部分的后面

第三步将剩下的勒索信息复制到第二部分后面,如图

0040A1FA 处调用 call sub_402354,该函数功能如下,

该函数用来关闭一些进程,如 word,excel,防止后面加密函数运行时,由于文件占用导致加密失败。

在最后连续调用了 3 个 call

第一个 call 寻找盘符,加密文件,这里不做过多分析,放到加密部分细讲

第二个 call 创建 bat,创建进程并运行,用于善后工作,从内存中 dump 出批处理文件,内容如下

  @echo off..vssadmin.exe Delete Shadows /All /Quiet  reg delete "HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default" /va /f  reg delete "HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers" /f  reg add "HKEY_CURRENT_USER\Software\Microsoft\Terminal ServerClient\Servers"  cd %userprofile%\documents\                                     attrib Default.rdp -s -h                   del Default.rdp                                 for /F "tokens=*" %1 in ('wevtutil.exe el')DO wevtutil.exe cl "%1"  

vssadmin.exe 删除卷影副本,wevtutil.execl 命令删除日志信息

第三个 call 用于自删除

0x05 加密部分

本人入逆向时日不长所以对各个加密算法( RSA,AES,SHA256 )比较生疏,如果有分析不当的地方还请各位大佬们多多指点。

目前主流的勒索软件使用的加密算法为 RSA 和 AES。AES 属于对称密码体制,RSA 属于非对称密码体制,一般来讲 RSA 有两对,黑客有一对,用户生成一对,黑客的 RSA 私钥自己保留,将 RSA 公钥以硬编码(或加密)的方式存储在病毒中,用来加密用户的 RSA 私钥,用户的 RSA 公钥则用来加密 AES 密钥,AES 密钥用来加密文件。视病毒的情况而定,有些病毒每一个加密文件对应一个 AES 密钥,有些病毒所有加密文件只对应一个 AES 密钥。

之前已经提到过,该病毒主要有两次加密,第一次是写入 Hash 文件和勒索文档的用户 ID,第二次就是对文件进行加密

用户 ID 生成分析

在之前的分析中我刻意回避了一个函数 00409F43 处的 call sub_408F24,该函数的功能如下

a1 也就是第一个参数是 256 位的字符串(应该是未被加密),个人推测应该是黑客的 RSA 公钥,如下图

该函数内出现了 SHA256_K,ROL4 和 ROR4 的字样,推测该函数的目的是对黑客的 RSA 公钥进行 SHA256 加密,加密后的内容如图

是不是很熟悉……在对加密的字符串进行解密的时候作为解密的 key入栈,在创建 Hash 文件的时候作为文件名。转到生成用户 ID的函数空间,进入 sub_40A534,首先分配了 1024 大小的内存空间,在 sub_40A3DD 函数中的 sub_404336 函数生成了用户 RSA 的密钥,之后将该密钥写入 Hash 文件中。

接来下调用两次 sub_4024E8 生成 128 位的明文(该明文应该是与用户 RSA 私钥有关系的,不然用黑客 RSA 公钥加密就没有意义了,不过我没有分析出来这个拼接的 128 位明文是什么),在 sub_40A3F4 处用黑客的 RSA 公钥对明文进行加密,返回给 V26 变量,如图

最后调用 sub_40267E 将 V26 中的十六进制数据转换为 ASCII 数据,如图

回到原来的函数中,接着调用 SetFilePoint 定位到 Hash 文件的末尾,使用 WriteFile 将上图的值写入 Hash 文件末尾(之后合成勒索文档时,中间插的那一段数据也是上图所示的数据)

至此用户 ID分析完毕

文件加密部分

来到 0040A20A 处的 call sub_409B9C 进入文件加密函数,注意调用该函数时的参数,第一个参数为之前生成的用户 RSA 的公钥。

首先会调用 GetLogicalDrivers 函数判断宿主主机有几个盘,将返回值转换为二进制 10000000000000000000000100 从右向左数,一共有两个盘,C 盘和Z 盘,调用 GetDriveTypeA 获取相应磁盘的类型,接着进行判断如果属于硬盘驱动器、远程(网络驱动器)和移动驱动器中的一种,则对每一个符合要求的磁盘调用 CreateThread 创建一个加密线程,回调函数为 sub_40994F,回调参数为指向相应的盘符的指针,在回调函数处下断点,顺便在c盘根目录下创建 a.txt,内容为 123,以便分析加密方式

接着对各种字符串的操作,调用 FindFirstFileW,先寻找 C 盘根目录的文件,找到之后会进行一系列的判断

比较后缀名是不是 ..doc 判断是否被加密

比较文件名是不是 Read__ME.html(生成的勒索文档),比较文件名是不是 Hash 文件

比较文件名是不是比较是不是复制到 C:\Documents and Settings\Administrator\Application Data 目录的病毒副本

如果全部判断失败则进入 00409B01 处的 call sub_409081 文件加密函数,这里要留心该文件加密函数的三个参数

第一个参数为要加密的文件名称,也就是 a.txt

第二个参数是用户 RSA 的公钥

第三个参数是用户 ID的第二部分

该函数会调用 UuidCreate 创建一个全世界独一无二的 uuid 值,uuid 的值如下

之后调用 CreateFile 打开要加密的文件,获取文件大小,计算 uuid 的长度,调用 sub_407009 分配了两块内存空间,之后将要加密的文件大小与文件名称进行运算

之后将运算后的结果与 uuid 进行加密运算(应该是 SHA256 加密),而且加密了 2000h 次,如图

经过运算之后的值为下图,从 D1BB98D1BBB8,我们可以设这个值为 A

紧接着调用 004092EF 处的 call sub_402780D1BB70 的值进行扩充,该函数有一个参数为 A,通过 A 的值生成 AES 加密的密钥,后面的分析也验证了这一点,扩充的数据中包含一个 256 位的 AES 密钥,从 D1BC10D1BD20,设这个值为 B。

接着调用 ReadFile 将文件内容读取到缓冲区中,并在 00409489call sub_408F7F 对文件内容进行加密,其中该函数的参数包含 B

这里可以推测一下 00409489 处的函数应该为 AES 加密,而该函数的第四个参数也就是 B (位于扩展数据中)作为 AES 的 key 进行加密。加密后的文件数据如下(该勒索病毒对每一个文件创建一个 AES 的密钥)

接着将加密后的文件数据复制到 D1BBB8 处,然后调用三次 WriteFile,分别将数据复制到文件中,使用用户 RSA 公钥将 uuid 进行加密,并写入文件,最后将用户 ID的第二部分写入文件中,加密后的 a.txt 如图

分析完毕

通过上面的分析,我们可以了解到该病毒对每个文件的 uuid 进行运算,通过运算结果生成 AES 密钥,并使用用户 RSA 公钥对 uuid 进行加密放在了文件中,从用户的角度考虑要解密文件数据首先要获得 uuid 的值,由于 uuid 被用户 RSA 公钥进行加密了,所以我们要获得用户 RSA 的私钥,而用户 RSA 的私钥又被黑客 RSA 的公钥进行加密后写入用户 ID 中,所以我们要获得黑客 RSA 私钥,但是黑客的 RSA 私钥只有黑客一个人拥有,所以用户只能向黑客支付赎金并提供被加密的文件和在机器上生成的 Hash 文件才能解密

0x06 小结

1、加密技术掌握的不熟练,外加上该病毒是自己实现 RSA 和 AES 的加密的,没有调用微软提供的 CSP 容器,所以对分析造成很大的困难。

2、分析病毒要有耐心,切记分析加密部分的时候要一口气分析完,由于表哥只给了一个样本所以我们并不知道该病毒是如何传播的。

3、写文不易,且看且珍惜。

原文发布于微信公众号 - 信安之路(xazlsec)

原文发表时间:2018-04-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Albert陈凯

2018-10-31 代码中的敏感信息加密方案

https://juejin.im/post/5bd79dc4f265da0acb13df0d

18440
来自专栏逸鹏说道

常见Flash XSS攻击方式

0x01 HTML中嵌入FLASH 在HTML中嵌入FLASH的时候在IE和非IE浏览器下嵌入的方式有所不同,可以使用embed标签和object标签,使用如下...

1.3K50
来自专栏小樱的经验随笔

破解Zip加密文件常用的几种方法

从网络上下载了一个zip文件,最后却发现它是用密码保护的,或者自己用密码加密了一个很重要zip文件,但是一段时间后忘记了密码,无法打开。这个时候,我们就可能就需...

2.3K40
来自专栏向治洪

彻底搞清楚 RxJava 是什么东西

其实从rxjava14年出现到现在,我是去年从一个朋友那里听到的,特别是随着现在app项目越来越大,分层越来越不明确的情况下,rxjava出现了,以至于出现了r...

7.3K80
来自专栏听雨堂

.Net中DES加密的细节问题

一般的做法和MSDN都差不多,都是这种方式   加密:byte[]--write-->ms   解密:ms--read-->byte[]   即创建CryptS...

19490
来自专栏FreeBuf

直面冥王:最新爆发的C#敲诈木马HadesLocker解读

近日哈勃分析系统捕获到一类由C#语言编写的新的敲诈勒索木马。之前出现 的C#语言编写的木马只是简单地调用了一些C#库来辅助开发。与之相比,这次的变种增加了多层嵌...

31760
来自专栏安恒网络空间安全讲武堂

WriteUp分享 | LCTF的一道padding oracle攻击+sprintf格式化字符串导致的SQL注入

0x00题目 http://111.231.111.54/ 泄露了两个源码 .login.php.swp .admin.php.swp 源码丢在最下面,可用vi...

25180
来自专栏大内老A

[WCF安全系列]实例演示:TLS/SSL在WCF中的应用[SSL over TCP]

在接下来的系列文章中我们正是讨论关于身份认证的主题。在前面我们已经谈到了,WCF中的认证属于“双向认证”,既包括服务对客户端的认证(以下简称客户端认证),也包括...

27870
来自专栏叔叔的博客

SpringCloud config配置文件加密

? 一、前言 配置文件中,有些敏感数据需要加密处理。 SpringCloud config server可以结合jce实现这个功能。 二、配置 下载jce ...

41960
来自专栏程序猿DD

JSON Web Token - 在Web应用间安全地传递信息

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

9620

扫码关注云+社区

领取腾讯云代金券