0x00 写在前面
部门早些时候,发布了一个关于该话题的文章:https://mp.weixin.qq.com/s/haCZK4m3JVpmgxXNMj30hQ
现在参照着这个文章,对里面提到的样本进行一个分析,学习一下真实环境中的攻击思路和溯源。
0x01 第一部分
这个事件是如此引出的,所以我们直接尝试去app.any.run下载对应的样本
样本hash:4f8091a5513659b2980cb53578d3f798
根据app.any.run上面的说明,该样本好像是一个安装器
样本下载到本地,进行查壳
行为检测
首先还是更名,然后行为检测一波
行为非常多,其中大部分是通过注册表收集信息的行为,还包括了遍历文件夹的行为
在xp下再跑一次:
通过cmd获取关键信息并且保存到指定路径
清除痕迹然后退出:
IDA静态分析
看到有两千多个字符串,所以决定之后再看
直接看Main函数:
Main函数sub_401000函数分析
查看第一个call sub_403080,该函数的功能主要是内存赋值,更名为Scw_memorySet
然后是通过lstrcpy将刚才赋值的内存,赋值给ecx
接着往下走,程序会在WaitForSingleObject之后call sub_401000 函数
Main-sub_401000函数分析
我们跟进sub_401000
仿佛是加载函数的,从该部分函数来看几乎全是网络相关的
并且全都调用了sub_48AFB0这个函数
Main-sub_401000-sub48AFB0
我们查看一下该函数:
从函数可以看到,如果传入进来的字符串开头是CCS,那么就从 a1+4 ,也就是字符串第五个位置开始的地方取函数名
如果开头不是CCS,就从a[1]的位置开始取,也就是第二个字符开始并进行异或操作。
所以我把sub_48AFB0这个函数更名为Scw_getString
Main-sub_403040函数分析
然后发现该函数和父级函数都没有其他操作了,返回到Main函数继续往下看
查看sub_403040函数
函数很短,主要是通过之前Fenix的内存赋值函数给byte_4BEC80指向的内存赋值,然后作为参数传递到了sub_402960函数
Main-sub_403040-sub_402960函数
查看下sub_402960函数:
可以看到sub_402960函数最开始会通过memset设置内存,其中调用了GetComputerName获取计算机名,还调用之前分析的字符串提取函数提取
SOFTWARE\Microsoft\Windows NT\CurrentVersion
RegisteredOwner(获取最终用户的名称)
RegisteredOrganization(最终用户的组织名称)
InstallDate(安装时间)
根据提取的这几个字符串和上面部分的内容也可以猜到,样本这里应该是在获取计算机的一些基本信息。
然后程序是一大堆的计算函数,这里最后return的值与v18相关,所以查看v18的调用可以推测,这里是利用后去到的计算机信息进行计算生成以后唯一的ID并返回,根据这个功能,我将sub_402960函数重命名为Scw_getPCID
这里调用完成之后可以看到生成的ID为6C4F6D24
Main-sub_403040-sub_402F70函数
然后返回到父函数,还剩下一个call没有分析
进入到sub_402F70:
调试得到:
所以上面的函数可以修改为如下所示:
这里可以看到该函数的功能是使用socket,获取本机的IP地址。
所以修改sub_402F70为Scw_SocketGetIP
现在该函数(main函数的第二个调用)主要的三个函数已经分析完成了
lstrcpy调用完成之后,得到了获取的ip地址(由于我虚拟机卸载了网卡,gethostbyname的时候是触发了异常的,这里获取到的是127.0.0.1)
通过分析我们可以得知,这部分功能主要是获取PC的ID和PC的IP,所以更名此函数为Scw_GetPC_ID_IP
Main函数sub_4033B0分析
现在Main函数还有最后一个调用sub_4033B0
sub_4033B0首先获取tmp目录
然后通过函数取出如下字符串:
%s\temp
%s\%s
%s\browser.his
再分别拼接,结果如下:
拼接出路径名后又调用函数进行操作:
四个函数调用完后成功创建文件夹:
接下来是是调用四次了sub_403250这个函数
sub_403250函数如下:
又是一个取字符串,然后和传入进来的数据进行拼接的功能,直接拿结果
最后我可以看到,是调用cmd执行上面的命令。
所以我们可以知道sub_403250这个函数的功能是调用cmd执行参数1,然后将结果写入到tmp/参数2的文件中
四次调用完成后:
接下来是调用sub_401D10函数,通过动态调试得到了参数
Main-sub_4033B0-sub_401D10
进入函数:
可以看到,前面是路径拼接,然后将拼接好的路径传递到sub_401A80函数
Main-sub_4033B0-sub_401D10-sub_401A80
查看函数
很明显是一个获取主流浏览器配置和历史信息的函数。
接着往后看,是调用了sub_48B290函数,参数为v12
调试得知v12是一个内存地址的起始地址
查看了下sub_48B290函数,里面关键部分在sub_48B220
sub_48B220内容如下:
可以看到该函数首先是通过WSAStartup尝试建立socket,然后通过一个循环对172.22.22.156进行处理,循环调用的函数是sub_48B150,查看该函数:
动态调试解密:
实际上就是socket连接这一套API
第二次调用的时候,已经计算出了新的ip地址:10.2.114.1
第三次:172.22.22.5
第四次:10.2.4.1
4次循环执行完就返回了
如果上面四次有成功建立连接,就会执行中心的语句,否则就会执行return result,此时result = -1
所以该函数(sub_48B290)的功能应该是测试连接
接着往下看,有两个输出函数:
打印连接状态
然后调用sub_402770
参数FileName如下
进入到sub_402770:
可以看到函数首先会设置RootPathName为C:\
获取成功后会继续获取磁盘类型
如果类型在2到4之间,则调用sub_4025A0
这里获取到的类型为3
说明会进入到sub_4025A0,查看该函数:
函数前面部分有一个fopen wb写入的操作
通过调试可以得知写入的路径是:
写入的内容在sub_401F10这个函数
如图:
看到最后的FindNextFile,猜测应该是遍历文件操作
写入完成后的文件内容如下
然后我跟进到sub_4991DA0函数
参数2应该是加密的压缩密码。
进来之后可以看到明文字符串
解密之后程序调用sub_490100,sub_490100函数为创建并写入文件
参数如下:
调用之后
解密之后,程序会调用sub_491E30
参数如下
调用完成之后可以看到文件已经被压缩了。
然后删除原始的文件
然后sleep,return
分析到这里就差不多下班了,后面的内容有点乱,明天重新分析一下
目前sub_402770函数:
接着往下看,程序先是两个sleep,然后取出了三个字符串,在sub_491DA0的地方又是一个数据写入
根据之前的经验,我在这猜测是写入一个明文MT.tmp的文件,加密秘钥为abcd@123
跟进到sub_491DA0函数
sub_491C70:
关键函数在sub_490100,调用时参数如下:
创建文件:
然后是sub_491F10函数
参数如下:
这里的v17是之前计算的用户id和ip的拼接值
在最里层找到了压缩函数:
文件写入:
文件遍历:
我们找到遍历的文件夹就行
这里就是在temp目录下查找所有文件
这里有一个递归调用,用于查找所有子文件夹
目前这部分函数功能如下:
第二次压缩写入的路径如下:
然后通过$IPC将文件传入到10.38.1.35这个机器上
0x02 DTrack Dropper
其实按道理来讲,这个才是第一部分,因为上面得那个木马是由这个样本释放出来的。
Dtrack Dropper的hash值是:b7c3039203278bc289fd3756571bd468
下载该样本到本地:
基础信息
文件查壳:
然后跑一下行为:
可以看到这里的行为都是上一个样本里面分析到的内容,包括最后的删除文件,清理痕迹:
代码分析
直接在IDA里面定位到Main函数:
好像有点不对..这里跟进来仿佛看不到具体的代码
调试试试
程序默认停留在004381f8,也就是start函数的地址:
尝试在Main函数入口点下断点0044AA55:
od设置断点运行后程序直接终止运行了
说明程序要么有反调试,要么根本就没有执行到main函数
现在检测od的进程,然后断点F9运行:
发现之前的行为还在,说明不是反调试,那就说明代码没有跑到main就结束了。
==我还是第一次遇到这样的情况,奇安信的报告里也提到了,这个是修改了CRT的,也就是编译器代码。
我们还是跳转到程序默认的入口点:
init可以不用管,直接查看__tMainCRTStartup:
这很明显和正常的CRT不同。
特别是在最后还return 了一个sub_438FE1,正常的CRT结尾应该如下:
可以看到__tMainCRTStartup进来最先是调用了sub_438F9C函数,跟进去看看:
现在在od里面跟进来
创建内存:
打开文件句柄
通过偏移读取文件填充分配的内存地址
然后在00438FFA这里call进去,就进入到了内存中那个文件:
再次分配内存:
call009A0710之后,在分配的内存中解密出了PE文件
有点感冒,这里分析的不是很清楚,但是这里面call进去 然后加载出来就是之前那个样本了,之后再补充一下。