# 恶意传播之——社工+白+黑

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2016-05-31T02:34:00Z
Canonical: https://wepostx.com/topics/283

> 乌云历史资料归档
>
> **原始作者：** 卫士通攻防实验室
> **原始编号：** superkieran-wooyundrops:1227
> **原始发布时间：** 2016-05-31 10:34
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

# 0x00 背景

日前实验室捕获一个样本。远远望去，像是搜狗输入法，在测试机中点开一看，弹出一款游戏的物价表，再看PE文件属性，还带正常着数字签名，一副人畜无害的样子。经过一番认真分析后。发现远没有这么简单，这里就分析过程记录一下，希望其他安全工作者有些许帮助。
先介绍一下所谓白名单免杀。随着病毒与杀软之间的斗争，杀软的手段不断地增多、增强，由早期传统的特征码匹配算法发展到目前虚拟机技术、实时监控技术等流行的查杀算法。但始终存在一种最直接也最根本的免杀方式——白名单免杀。病毒就安安静静地躺在杀软的白名单中，谁闲的没事会去查水表呢？
当了解了白名单免杀的基本含义之后，就可以针对样本进行深入的研究，本文以下内容就是笔者拿到样本之后，逐步分析样本主要功能的完整过程，其分析环境如下：

- 分析环境：win 7 x86 VMware

- 分析工具：IDA、CFF、OD

# 0x01 样本概述

样本包含5个文件：
File namesizeMD5attribute
nvvsvc1.exe.exe451.50 KB (462336 bytes)4D9B3A508BC2402A86E10F7907022263hidden
HWSignature.dll48.50 KB (49664 bytes)85F50E1D2DE076079D98F09416E4C710hidden
HanziSort.dat158.75 KB (162557 bytes)4FB42CBC7ADD3CF2AB3F0A99B9E7CE25hidden
图1Shortcut linked to cmdcmd /c nvvsvc1.exe & exitShortcut
01.jpg.jpg99.07 KB (101446 bytes)78501660AD39494A7248BA0C96989494hidden

- nvvsvc1.exe：即为搜狗输入法的更新工具，用virusbook查看后可判定完全没有问题。此外，该文件有正常的数字签名，见下图。

![原文图片](/media/2016/06/47cb0daf2a1fa25cbc8a55e03314327d)

- HWSignature.dll：这个DLL原本是搜狗输入法的硬件签名DLL，该样本中被劫持为恶意劫持。

- HanziSort.dat：原本为搜狗输入法与汉字相关的数据文件，该样本中被替换为其他数据文件。

- 01.jpg.jpg：一副jpg图片，内容为《怪物猎人官方最新价格表》，后文有展示。

- 图1：指向cmd的快捷方式，其参数为cmd.exe /c nvvsvc1.exe & exit
其中，nvvsvc1.exe为主程序，其目的是加载HWSignature.dll，而HWSignature.dll会加载并解码HanziSort.dat， 进一步的，HanziSort.dat会再次解码自身并在内存中释放svchost2.dll，此后手动加载svchost2.dll，该DLL为包含恶意程序的主要功能。
传播方式：以《怪物猎人官方最新物价表》为鱼饵进行钓鱼，下载解压后，其他文件隐藏，只能看到名称为“图1”的文件，点开后确实会展示图片，但木马也会加载。笔者建议广大游戏玩家，下载的攻略要先看清是什么东西，再点开查看内容。

# 0x02 主程序分析

拿到样本之后，首先放到virusbook查了查，主程序想必没问题，而除此之外的一个DLL就被查出有问题了。很明显，这是一个通过DLL劫持加载自己的木马样本，这种通过DLL劫持的木马，可以算是白名单免杀吗？这个问题先放一放，后文（0x8 结语）会给出笔者的看法。
IDA分析主程序，绝大部分都是输入法相关的操作，中规中矩。值得注意的是，此处创建了8个线程。

![原文图片](/media/2016/06/ff58bee986572b65e4cf14c29da535d5)

这其中第4个线程，即执行sub_427C80的线程会进一步调用sub_42F090函数，在该函数的子函数中，会加载HWSignature.dll，但此处被样本劫持，用来执行其恶意功能。

![原文图片](/media/2016/06/159f6280798dc1845eb8224cfa01c805)

# 0x03 DLL分析

跟进这个DLL，进一步分析该DLL的行为。无关行为不说，该DLL会打开HanziSort.dat文件：

![原文图片](/media/2016/06/3998fd281788ceaf56ad96edebc65adf)

读取其内容，并解码：

![原文图片](/media/2016/06/5fd1dee5189f7b92bb37ab6cecee0764)

其解码方式很简单，只是把读取到的文件内容逐字节的与0x56做异或运算。解码之后，成为包含可执行指令的程序段：

![原文图片](/media/2016/06/d54c19050191320f1a918c2de392634f)

此后，程序会通过retn的方式跳到解码的代码段执行。

# 0x04 DAT分析

在DAT解码的代码中，首先会寻找解码内容为0xDDCCBBAA的位置：

![原文图片](/media/2016/06/63915a458c4d4b0484e93bc6b5ba5ab9)

通过该地址，可以辅助完成一些列的定位操作，具体内容不做介绍。进而会调用VirtualAlloc函数分配内存空间，然后通过memcpy函数将指定数据拷贝到申请的内存中：

![原文图片](/media/2016/06/85b2fe3ae0996e47493a21fdbeb90630)

![原文图片](/media/2016/06/ec9cddc872b5bdb9e790092b272bb77f)

而拷贝过去的内存段，会再一次进行解码：

![原文图片](/media/2016/06/b5fda78fb3166cc08d5c31df97b02131)

其解码方式同样比较简单，是逐字节与0xCC进行异或运算。当完整所有解码工作之后，可以发现解码之后的内存为一个完整的PE文件：

![原文图片](/media/2016/06/4df95d151c1e9f0eb4c933800d0bcbea)

将该PE文件dump出来，用查看CFF看下，可以确认是个完整的DLL：

![原文图片](/media/2016/06/8ce42c6c5ff80898f08c81a1848a7cbc)
 (忽略一些细节吧。笔者懒得打码了。)
这个DLL叫做svchost2.dll，后面的代码可想而知，新申请一块内存

![原文图片](/media/2016/06/4b47b35688790aab39c53566d3a1bf11)

然后手动完成PE的加载流程：

![原文图片](/media/2016/06/26613e8addb0a658bdccc92eb91265f8)

以及根据导入表和重定位表做一些修复工作，并加载所需的各种DLL，最后调用VirtualProtect更改页保护。

![原文图片](/media/2016/06/d785a5e0017eab346e412ea4516528e9)

完成以上操作之后，调用DLL main函数：

![原文图片](/media/2016/06/f7f4878d3833916cf7d1c2e5cbe8c03c)

DLL的主函数并没有什么需要深入分析的地方，这里略过。DLL main返回后，会查找DLL导出的mystart函数：

![原文图片](/media/2016/06/fe41ce2ce3330b3f3f2a7fe777283716)

最后调用mystart：

![原文图片](/media/2016/06/cc8c3cd05dadcc96d80a7cce265fbe12)

# 0x05 mystart分析

在该函数中，首先会获得当前仅进程的名字，并判断名字中是否包含”1.exe”字符串。

![原文图片](/media/2016/06/0f2c6ad7bc468c8af41f89ce3cf6db0d)

获得的样本中，当然是包含该字符串的。接下来，会进行一些有意思的事。首先会调用WinExec执行”taskkill /f /im cmd.exe”命令，然后创建一个互斥体。

![原文图片](/media/2016/06/aa432dea52e2701e25405c020917a26e)

进一步的，该样本会在C:\Users\zzz\AppData\Roaming创建一个文件夹，其名字随机：

![原文图片](/media/2016/06/e85eefec92434ca81d9f15337738ee42)

在本次分析中为：C:\Users\zzz\AppData\Roaming\dptpbzwoztxwrh，并将样本所在的文件夹中所有文件都复制到该目录下，包括ida生成的几个文件，但排除01.jpg.jpg。对于这幅图片，该样本会调用cmd执行rundll32.exe shimgvw.dll imageview_fullscreen 01.jpg.jpg，其作用就是把样本中的01.jpg.jpg展示出来：

![原文图片](/media/2016/06/d4b5359d2e03e70ee9fff383a71b0d2a)
 （01.jpg.jpg ：什么仇什么怨？）
如此一来，受害者看到了想了解的《价格表》，也不会怀疑该文件是木马了。此外，复制到Roaming的主程序会重命名为MSUpdateXXXXXXXX.exe，XXXXXXXX表示8位随机字母。注意，IDA生成的几个文件也会被复制过去并重命名。

![原文图片](/media/2016/06/521a6777c0913a97834ba4177832b4bf)

拷贝完成之后，释放互斥体，并Sleep(0x2EE0)的时间。

![原文图片](/media/2016/06/10b74a4c2d44d4e97d21d833e0887ce4)

并注册表增加一些键值：

![原文图片](/media/2016/06/ef8b4542e8fd32230ad9c10234bb741d)

最后，通过shellexecute执行刚刚复制到Roaming的样本文件。

![原文图片](/media/2016/06/40397bb85c2ed0966da732405a9d2628)

# 0x06 第二次执行分析

当第二次执行时，之前的行为都是类似的，只有在mystart函数中，出现了变化。由于当前进程是复制到Roaming下的镜像文件，重命名之后不包含”1.exe”字符串（参考上文）。所以会执行到另一个分支，调用Fi函数。

![原文图片](/media/2016/06/c9b3d066714297ce2183090ea2548575)

该函数为svchost2.dll的另外一个导出函数。该函数会隐藏自己的进程名以及其他的信息：

![原文图片](/media/2016/06/f0e07dd8aa285d18de416177b7623df1)

隐藏结果使自己的进程名变为csrss.exe的，如图：

![原文图片](/media/2016/06/36c46d6d6d64806d8be5f9854381b4da)

但这种隐藏手段并不高级，随便一个工具就能识别出来。
进而，会调用Fa函数，该DLL的另一个导出函数。在该函数中出现了一些网络行为。首先，会连接139.196.184.116:34176

![原文图片](/media/2016/06/6f5f66f11cebe2ca38553d43e298ab78)

并发送数据：

![原文图片](/media/2016/06/92b64fb7653135c51e1e37610999b129)

该数据是怎么来的，暂时没有必要追究。有需要时，可以进一步分析，不过，可以肯定的是，对于同一台机器，每次发送的数据是一样的，应该是作为机器的ID标识。发送之后，会接收到如下内容：

![原文图片](/media/2016/06/86559cbc520ed1ae24031e6905869cbc)

针对返回的内容，会判断是否含有”Set-Cookie:”字符串，如果有，则取出：

![原文图片](/media/2016/06/06752cdcce1904ddeee47f30b0b12309)

接下来，会用该Cookie作为机器的标识。
进而，会连接139.196.184.116:35131地址：

![原文图片](/media/2016/06/a28f0b3b5f70fbe20c4e8b934fa324b3)

但是该端口已经挂掉了，无法连接上。所以，笔者只好重新定向到自己的IP，并模拟其通信。 连接上IP之后，会发送一些随机生成的数据：

![原文图片](/media/2016/06/2748853bb1b8e0cc17fc2707fc98a722)

本机的监听结果如下：

![原文图片](/media/2016/06/3033454c6f310f704b172b7c63ebdac7)

发送3次随机生成的数据之后，会创建新线程用于接收返回数据：

![原文图片](/media/2016/06/995d9fa9fa113af056650d961dd98b5a)

该线程会接收来自139.196.184.116:35131回复的数据，但是由于该端口已经挂掉了，笔者只能随意的回复点什么东西，[email protected]

![原文图片](/media/2016/06/b1a31f1866698b3fdef31bfaa5195809)

接收到回复之后，会在sub_12A50F0中做解码工作。其解码工作首先会将受到的数据逐比特与0xE9异或。

![原文图片](/media/2016/06/f8197827b705868c1c6b582e91051607)

进而会对长度进行判断，然后对几个关键位置的内容进行判断，如果出现不符合的情况就会结束该线程；如果全部满足条件，则调用zlib 1.2.8版的库函数解压接收到的数据。

![原文图片](/media/2016/06/e5a284d21bc48ddfdfa59cb84e884ed0)

最后根据解压缩出来的内容选择初始化某个对象，并调用该对象的成员函数，实现恶意功能。

![原文图片](/media/2016/06/e06fe52392727885b207eff38e271eb1)

执行完毕后，该线程会进入循环接收新的数据，并执行相应功能。此外，主线程创建了上述之后，会统计当前系统的各种信息：

![原文图片](/media/2016/06/ddd126350e484a7f99529c805ffec725)

其中sub_100010F0实现捕获摄像头信息的相关操作。当获取了所有的信息之后，发送给目标地址，目标地址同样挂掉了。最后同样进入发送和接收的循环中。

# 0x07 恶意功能分析

该样本的恶意功能比较多，现随机展示一个通过匿名双管道实现远程CMD的功能。该功能由编号0x31的分支实现。

![原文图片](/media/2016/06/e398963a0f319277858216284df8474e)

详情参考sub_10007DC0函数，该函数首先会调用sub_10004C00 初始化socket，进而调用sub_1000F060创建管道并启动CMD进程：

![原文图片](/media/2016/06/daeb8f3011ec1dc6909fb2af3ca9363b)

![原文图片](/media/2016/06/5bf58a872b44304a14515068369e835b)

# 0x08 结语

这个样本并不复杂，但是能够实现较为全面的木马功能，另外通过游戏攻略进行传播，利用白+黑的方式过杀软。哪怕现在HWSignature.dll会被查杀。但有白名单宿主进程的话，绕过杀软并不困难（基本瞬间就能想到好几种绕过检测的方式）。因此这种模式是值得我们警惕的。

## Replies
