12月末,一个朋友跟我说有个样本,让帮忙分析一下。花了一点儿时间分析了样本,发现这个样本来自一个通过修改永恒之蓝攻击脚本传播挖矿木马的攻击流程。准备投稿之前手贱搜索了一下样本中比较有特征的字符串 “password12” 和 “HSKALWOEDJSLALQEOD”,然后确认这个事件和火绒首先披露的驱动人生供应链攻击事件应该是同一事件。庆幸自己没有脑子一热直接提交之余,内心之中还是有点儿可惜。
拜读了火绒的分析报告,为他们比较迅速的响应速度点赞!同时,在已经对样本做了分析之后觉得:可能是事出仓促,有些技术点火绒以及后续腾讯的报告中没有体现。所以这里把整理的一些技术分析稍作补充。虽说是狗尾续貂,但是绝无蹭热度的想法。公开这部分内容的目的在于把分析所得转化有价值的信息,呈现给对此事关注的安全爱好者和研究人员,仅此而已。
拿到的第一个样本名称是svvhost.exe(也就是MS17-010
漏洞扫描的样本),样本大小4M多,所以看一下资源。
这样结果就很明了了,这是一个py2exe生成的样本。所以下一步工作是提取样本里的python脚本。
关于脚本提取的方法,可以用python的PEFile库去解析PE文件,提取PYTHONSCRIPT资源,也可以用工具把资源dump出来。提取过后,几行简单的脚本就可以还原出python代码了。下面的这个函数就可以完成PYTHONSCRIPT流的解析工作。
下面一段代码可以检测并提取Py2exe编译程序中的PYTHONSCRIPT对象。
class PythonExecutable_parse(object):
def __init__(self, filename, check_option = False):
self.python_version = 0.0
if os.path.exists(filename):
self.filename = filename
self.check = check_option
self.fptr = open(filename, "rb")
else:
raise Exception("File not found")
sys.exit(1)
def executable_check(self):
try:
pe_file = pefile.PE(self.filename)
except:
#check for PYTHONSCRIPT format
file_data = self.fptr.read()
if b'x12x34x56x78' == file_data[:4]:
return ("PYTHONSCRIPT", file_data)
#can not support for python 3.x currently
else:
return ("NOT_PE", None)
#check for py2exe foamrt file
if hasattr(pe_file, "DIRECTORY_ENTRY_RESOURCE"):
for entry in pe_file.DIRECTORY_ENTRY_RESOURCE.entries:
#get python script version from pythonx.x.dll
if str(entry.name).endswith(".DLL"):
self.python_version = int(str(entry.name)[6:8])
if str(entry.name) == "PYTHONSCRIPT":
script_resourse = entry.directory.entries[0].directory.entries[0]
if script_resourse != None:
pythonscript = pe_file.get_data(script_resourse.data.struct.OffsetToData, script_resourse.data.struct.Size)
return ("PY2EXE", pythonscript)
代码执行没有问题,解析出来的脚本也没有被混淆,谢天谢地。
这段代码显而易见,是几个此前公开的永恒之蓝利用代码修改而成的。
我们看一下check_ip()函数:
很明显代码获取主机所有网卡的IP地址以及所有和本机有网络连接的IP地址作为目标进行MS17-010 漏洞扫描。提取shellcode并分析,得出shellcode执行的操作和smb_pwn()代码的行为基本相同。
这个PE文件就是shellcode执行后下载的文件。仅看main函数的话行为比较简单:复制自身到系统目录下,并改名为svhost.exe;注册Ddriver服务并配置信息完成开机自启。而服务函数中又带有服务配置代码及注册服务的函数,为了防止程序意外退出,相比于直接调试服务函数,选择服务入口点设置死循环的方法进行调试比较稳妥。
服务函数中互斥量检查,信息采集,请求参数拼接,共享内存的部分火绒和腾讯威胁情报中心已经说的很明白了。分析过程也基本上印证了两份报告的内容。但两份报告对于通信过程和指令传递方法没有十分详细的说明。所以本文主要从通信过程中拆解这个蠕虫的自我复制和释放挖矿工具的过程。
为了文章结构完整,还是简单说一下服务函数的代码执行流程。
首先, 自身移动到C:\Windows\Temp目录下,重命名为svhhost后,拼接字符串”C:\Windows\Temp\svvhost.exe”为蠕虫的自我复制和版本升级做准备。
然后创建两个线程,一个线程用来检查自我复制是否成功,另一个线程则会检查系统当前是否有部分游戏进程,如果存在则结束svhhost进程。
接下来进入循环结构,每隔一段时间完成如下动作:
1 采集主机信息,包括主机名,系统版本,硬件设备信息,杀软信息等。
2 拼接URL,带参数请求C2地址(hxxp://i.haqo.net/i.png等)
3 请求成功时,拆解返回包的内容,并进行通信安全性校验
4 根据回包内容选择加载挖矿代码或完成蠕虫传播组件的版本更新。
由于此前的两篇分析报告并没有对通信过程加以详尽说明,所以本文提供以下补充内容:
过对通信过程的分析,现整理数据包解析方式如下:
上图就是实际调试过程中捕获的数据包,这段数据包两部分,$符分隔。首先第一部分数据包进行base64解码,然后对解码的数据利用password12进行rc4解密,得到一个带下载样本的md5 和一个url。
下面两张图分别为两次调试过程中服务器返回的数据包,它们也分别代表svhhost.exe的两种功能:下载蠕虫和挖矿。
而第二段则是客户端和服务端的通信校验,在代码执行下载动作前,需要对通信数据的有效性进行校验,大致流程是:首先对第二部分数据包进行base64解码,然后逆转字符数组作为私钥,和硬编码的公钥进行密钥对的验证。静态代码如下:
逆转字符串代码如下:
从目前该木马的活动情况来看,url 以mlz结尾时,下载的payload为挖矿木马,且木马下载后,直接把解压数据复制到共享内存中,再由主函数加载执行;如果url以exez结尾,则下载的样本为新版本的蠕虫,代码会将文件释放到本地,然后执行新的蠕虫样本(svvhost.exe)。
当新的svvhost.exe被执行时,也会重新对目标进行扫描和攻击,然后其他主机也会执行类似上面shellcode执行 -> 下载样本 -> 注册Ddriver服务 -> 释放svhost.exe -> 传播蠕虫|内存加载挖矿代码 这样的流程。
其他技术细节火绒和腾讯火绒和腾讯威胁情报中心已经说的很明白了。所以这里不做赘述了。
在调试过程中,我发现svvhost确实有更新:利用代码提取python脚本后,发现了数个版本的shellcode,有一部分shellcode在调试过程中可能会发生崩溃的情况。其中一个版本的shellcode 执行的是下载hxxp://dl.haqa.net/dll.exe的指令。 对这个样本进行分析发现除了部分样本加壳,样本移动自身的位置变为C:WindowsSystem32driverssvchost.exe,新调试的样本还会将hxxp://p.abbny.com 作为C2服务器外,就没什么其他变化了。
首先,重新声明:本文公开出来,绝不是为了蹭事件热度,技术分析部分也只是对两家报告不甚详尽的部分做了一点儿补充,另外,py2exe的脚本提取,也仅仅是给安全爱好者做一个参考。
再者,利用永恒之蓝搞成事儿,从WannaCry以来已经不少了,但是还是有很多人不去修复漏洞。尤其对于个人用户来说,很多隐私信息往往就是因为这样或者那样的不经心,不Care而泄露。另外,供应链攻击危害性还真的是比较大的,依稀记得去年也出现过一次利用网游加速器隧道进行永恒之蓝攻击传播挖矿蠕虫的事件。希望以后类似的事儿尽量不要发生吧,毕竟每一个人都有捍卫自己隐私和信息安全的权利。
74E2A43B2B7C6E258B3A3FC2516C1235
D2C775128228A11A361F41C42739CC12
F79CB9D2893B254CC75DFB7F3E454A69
F9144118127FF29D4A49A30B242CEB55