0x00 写在前面

部门早些时候,发布了一个关于该话题的文章:https://mp.weixin.qq.com/s/haCZK4m3JVpmgxXNMj30hQ
现在参照着这个文章,对里面提到的样本进行一个分析,学习一下真实环境中的攻击思路和溯源。

0x01 第一部分

这个事件是如此引出的,所以我们直接尝试去app.any.run下载对应的样本
image.png

样本hash:4f8091a5513659b2980cb53578d3f798
根据app.any.run上面的说明,该样本好像是一个安装器
image.png

样本下载到本地,进行查壳
image.png

行为检测

首先还是更名,然后行为检测一波
image.png

行为非常多,其中大部分是通过注册表收集信息的行为,还包括了遍历文件夹的行为
image.png

在xp下再跑一次:
image.png
通过cmd获取关键信息并且保存到指定路径
清除痕迹然后退出:
image.png

IDA静态分析

看到有两千多个字符串,所以决定之后再看
image.png
直接看Main函数:
image.png

Main函数sub_401000函数分析

查看第一个call sub_403080,该函数的功能主要是内存赋值,更名为Scw_memorySet
image.png

然后是通过lstrcpy将刚才赋值的内存,赋值给ecx

接着往下走,程序会在WaitForSingleObject之后call sub_401000 函数

Main-sub_401000函数分析

我们跟进sub_401000
image.png

仿佛是加载函数的,从该部分函数来看几乎全是网络相关的
并且全都调用了sub_48AFB0这个函数

Main-sub_401000-sub48AFB0

我们查看一下该函数:
image.png

从函数可以看到,如果传入进来的字符串开头是CCS,那么就从 a1+4 ,也就是字符串第五个位置开始的地方取函数名
如果开头不是CCS
,就从a[1]的位置开始取,也就是第二个字符开始并进行异或操作。
所以我把sub_48AFB0这个函数更名为Scw_getString
image.png

Main-sub_403040函数分析

然后发现该函数和父级函数都没有其他操作了,返回到Main函数继续往下看
image.png

查看sub_403040函数
image.png
函数很短,主要是通过之前Fenix的内存赋值函数给byte_4BEC80指向的内存赋值,然后作为参数传递到了sub_402960函数

Main-sub_403040-sub_402960函数

查看下sub_402960函数:
image.png

可以看到sub_402960函数最开始会通过memset设置内存,其中调用了GetComputerName获取计算机名,还调用之前分析的字符串提取函数提取
SOFTWARE\Microsoft\Windows NT\CurrentVersion
RegisteredOwner(获取最终用户的名称)
RegisteredOrganization(最终用户的组织名称)
InstallDate(安装时间)

根据提取的这几个字符串和上面部分的内容也可以猜到,样本这里应该是在获取计算机的一些基本信息。
image.png
然后程序是一大堆的计算函数,这里最后return的值与v18相关,所以查看v18的调用可以推测,这里是利用后去到的计算机信息进行计算生成以后唯一的ID并返回,根据这个功能,我将sub_402960函数重命名为Scw_getPCID
image.png
这里调用完成之后可以看到生成的ID为6C4F6D24

Main-sub_403040-sub_402F70函数

然后返回到父函数,还剩下一个call没有分析
image.png

进入到sub_402F70:
image.png
调试得到:
image.png

所以上面的函数可以修改为如下所示:
image.png

image.png

这里可以看到该函数的功能是使用socket,获取本机的IP地址。
所以修改sub_402F70为Scw_SocketGetIP

现在该函数(main函数的第二个调用)主要的三个函数已经分析完成了
image.png

lstrcpy调用完成之后,得到了获取的ip地址(由于我虚拟机卸载了网卡,gethostbyname的时候是触发了异常的,这里获取到的是127.0.0.1)
image.png

通过分析我们可以得知,这部分功能主要是获取PC的ID和PC的IP,所以更名此函数为Scw_GetPC_ID_IP

Main函数sub_4033B0分析

image.png
现在Main函数还有最后一个调用sub_4033B0
image.png

sub_4033B0首先获取tmp目录
image.png
然后通过函数取出如下字符串:
%s\temp
%s\%s
%s\browser.his
再分别拼接,结果如下:

image.png

image.png
image.png

拼接出路径名后又调用函数进行操作:
image.png

四个函数调用完后成功创建文件夹:
image.png

接下来是是调用四次了sub_403250这个函数
image.png

sub_403250函数如下:
image.png

又是一个取字符串,然后和传入进来的数据进行拼接的功能,直接拿结果
image.png
image.png
image.png
最后我可以看到,是调用cmd执行上面的命令。
所以我们可以知道sub_403250这个函数的功能是调用cmd执行参数1,然后将结果写入到tmp/参数2的文件中
image.png

四次调用完成后:
image.png

image.png
接下来是调用sub_401D10函数,通过动态调试得到了参数

Main-sub_4033B0-sub_401D10

进入函数:
image.png
可以看到,前面是路径拼接,然后将拼接好的路径传递到sub_401A80函数

Main-sub_4033B0-sub_401D10-sub_401A80

查看函数
image.png
很明显是一个获取主流浏览器配置和历史信息的函数。

接着往后看,是调用了sub_48B290函数,参数为v12
image.png

调试得知v12是一个内存地址的起始地址
image.png

查看了下sub_48B290函数,里面关键部分在sub_48B220
image.png

sub_48B220内容如下:
image.png

可以看到该函数首先是通过WSAStartup尝试建立socket,然后通过一个循环对172.22.22.156进行处理,循环调用的函数是sub_48B150,查看该函数:
image.png
动态调试解密:
image.png
实际上就是socket连接这一套API

第二次调用的时候,已经计算出了新的ip地址:10.2.114.1
image.png

第三次:172.22.22.5
image.png

第四次:10.2.4.1
image.png

4次循环执行完就返回了
image.png

如果上面四次有成功建立连接,就会执行中心的语句,否则就会执行return result,此时result = -1

所以该函数(sub_48B290)的功能应该是测试连接
接着往下看,有两个输出函数:
image.png
打印连接状态

然后调用sub_402770image.png
参数FileName如下
image.png

进入到sub_402770:
image.png
可以看到函数首先会设置RootPathName为C:\
获取成功后会继续获取磁盘类型
如果类型在2到4之间,则调用sub_4025A0
这里获取到的类型为3
image.png

说明会进入到sub_4025A0,查看该函数:
image.png
函数前面部分有一个fopen wb写入的操作
通过调试可以得知写入的路径是:
image.png

写入的内容在sub_401F10这个函数
image.png

如图:
image.png
看到最后的FindNextFile,猜测应该是遍历文件操作
写入完成后的文件内容如下
image.png

然后我跟进到sub_4991DA0函数
image.png

参数2应该是加密的压缩密码。
进来之后可以看到明文字符串
image.png

解密之后程序调用sub_490100,sub_490100函数为创建并写入文件
image.png

参数如下:
image.png

调用之后
image.png

解密之后,程序会调用sub_491E30
image.png
参数如下
image.png

调用完成之后可以看到文件已经被压缩了。
image.png

然后删除原始的文件
image.png

然后sleep,return
image.png

分析到这里就差不多下班了,后面的内容有点乱,明天重新分析一下
目前sub_402770函数:
image.png

接着往下看,程序先是两个sleep,然后取出了三个字符串,在sub_491DA0的地方又是一个数据写入
根据之前的经验,我在这猜测是写入一个明文MT.tmp的文件,加密秘钥为abcd@123

跟进到sub_491DA0函数
image.png
sub_491C70:
image.png
关键函数在sub_490100,调用时参数如下:
image.png

创建文件:
image.png

然后是sub_491F10函数
image.png
参数如下:
image.png
这里的v17是之前计算的用户id和ip的拼接值

在最里层找到了压缩函数:
image.png
文件写入:
image.png

文件遍历:
image.png

我们找到遍历的文件夹就行
image.png
image.png
这里就是在temp目录下查找所有文件
这里有一个递归调用,用于查找所有子文件夹
image.png

目前这部分函数功能如下:
image.png

第二次压缩写入的路径如下:
image.png

然后通过$IPC将文件传入到10.38.1.35这个机器上
image.png

0x02 DTrack Dropper

其实按道理来讲,这个才是第一部分,因为上面得那个木马是由这个样本释放出来的。
image.png

Dtrack Dropper的hash值是:b7c3039203278bc289fd3756571bd468
下载该样本到本地:

基础信息

文件查壳:
image.png

然后跑一下行为:
image.png
可以看到这里的行为都是上一个样本里面分析到的内容,包括最后的删除文件,清理痕迹:
image.png

代码分析

直接在IDA里面定位到Main函数:
image.png
好像有点不对..这里跟进来仿佛看不到具体的代码
调试试试
程序默认停留在004381f8,也就是start函数的地址:
image.png

image.png

尝试在Main函数入口点下断点0044AA55:
image.png

od设置断点运行后程序直接终止运行了
image.png

说明程序要么有反调试,要么根本就没有执行到main函数
现在检测od的进程,然后断点F9运行:
image.png
发现之前的行为还在,说明不是反调试,那就说明代码没有跑到main就结束了。

==我还是第一次遇到这样的情况,奇安信的报告里也提到了,这个是修改了CRT的,也就是编译器代码。
我们还是跳转到程序默认的入口点:
image.png
init可以不用管,直接查看__tMainCRTStartup:
image.png
这很明显和正常的CRT不同。
特别是在最后还return 了一个sub_438FE1,正常的CRT结尾应该如下:
image.png

可以看到__tMainCRTStartup进来最先是调用了sub_438F9C函数,跟进去看看:
image.png
现在在od里面跟进来
创建内存:
image.png

打开文件句柄
image.png

通过偏移读取文件填充分配的内存地址
image.png

然后在00438FFA这里call进去,就进入到了内存中那个文件:
image.png

image.png

再次分配内存:
image.png

call009A0710之后,在分配的内存中解密出了PE文件
image.png
有点感冒,这里分析的不是很清楚,但是这里面call进去 然后加载出来就是之前那个样本了,之后再补充一下。