原文:https://medium.com/walmartlabs/evasive-vba-advanced-maldoc-techniques-1365e9373f80
简介
在VBA中,创建进程的方法有很多,但每一种都有其优缺点。例如,如果使用Shell$、Shell或CreateObject(“WScript.Shell”).Run的变种创建进程的话,当显示这些进程时,会发现其父进程为office应用程序进程。在目标环境中,如果这种情况很少见的话,就很可能会引起用户的怀疑。
利用WMI创建进程的好处是,这些进程都是由wmiprvse.exe(WMI服务进程)创建的,除非WMI的活动正在被监视,否则防御者是不会将进程的创建与maldoc联系起来的。
Shell$
业务进程通常使用Shell$、Shell或CreateObject(“WScript.Shell”).Run的变体来运行reg.exe、ping.exe、cmd.exe和其他实用程序,从stdout读取信息或进行相应的修改,从而使进程能够得以运行。这种做法可能会给防御者带来麻烦,因为他们无法自动判断是否应该将办公产品的进程创建视为恶意行为,或是否应该阻止该行为。
无论您选择上述方法中的哪一种,创建powershell.exe进程的办公进程都是防御者始终密切观察的一个关键对象。因此,哪怕能够与它的关系远一步,也能显著降低被标识为恶意代码的可能性。例如,必要时可以调用cmd.exe/c powershell.exe命令,而非直接调用powershell.exe命令。
WMI
使用Shell$创建进程的好处是,防御者很难确定其是否合法,但是,如果使用WMI来创建进程的话,则没有这方面的优势。因为业务进程很少会使用WMI来创建进程,所以,一旦发现这种情况,那就非常可疑。此外,使用WMI创建进程时,其明显的缺点在于,总是三个VBA元素,分别是GetObject()、Get()和.Create,通常可以将其用于嵌入式OLE文件的“签名”。
以Empire为基准
以下是借助默认的PowerShell Empire VBA构建器,通过WMI创建进程的VBA代码。Empire是一个后续利用框架,提供了相应的恶意VBA宏构建器,以及各种其他功能。Empire代码中的变量名和字符串不仅会出现在文档的嵌入式OLE文件的P-Code部分中,同时,还会出现在压缩的VBA源代码中。其中,用于以Office 2007+文件格式存储VBA宏的默认嵌入式OLE文件是vbaProject.bin。由于其中的许多元素都是静态的,从而极大地减少了创建和检测签名的工作量。
含有使用默认Empire构建器的VBA代码的文档检出率。
ec4159c93ece699a4e381505321880cd329492cd1792ed8aaeeb6d23bfbe5daa
虽然利用Empire完成WMI进程创建的代码有点冗长,但这种方法也有其优点:WMI进程的创建可以在目标系统中“悄无声息”的进行(可以通过objConfig.ShowWindow=0来实现这个效果)。如果没有设置该属性的话,创建的进程会任务栏上短暂出现,所以,仍然有可能被发现。
如果选择更少的VBA代码,同时愿意承担由于进程在任务栏上短暂出现而被攻击目标发现的风险的话,WMI进程的创建完全可以通过一行代码来完成,具体如下所示。
在该示例中,以同样的方式创建了两个进程。在第二次创建进程时,VBA已经被化整为零,并进行了模糊处理。借助于StrReverse(),我们可以将字符串存储在VBA中的任何位置,并且不必以GetObject()所需的形式进行存储。请注意,GetObject()、.Get() 和.Create仍然会出现,所以,防御者仍然可以借助它们来完成相应的检测工作。
在这种情况下,未定义的变量可以用作Null,从而减少了可以用来确定正在运行哪些方法的线索的数量。
即使是这种简单的混淆处理,也忽悠了4种AV软件,如果进一步反转字符串的话,甚至能够绕过7种防病毒软件的检测:
e3987c7a322c52ba095bdad9feced318e9098b380717df8595cc046034c3922b
e9d02b2ed484cd1c944dc553a342e3166ce080205beb19d8132352beede8524c
有效载荷的混淆和重组
对于混淆技术来说,上面的StrReverse()是很好的一个例子,但这是一种众所周知的方法,很容易被检测出来。在防御者那里,有些混淆技术是重点怀疑对象,而另一些则不然。此外,对有效载荷进行何种程度的模糊处理和重组处理,在很大程度上取决于其大小。
我们的目标是,引入的代码要尽可能少,同时,力求有效载荷的表示形式更加难以被检测。
有效载荷的大小至关重要
尺寸较小的有效载荷,通常无需太多的重组处理(即使需要的话)。在定义变量时,VBA的最大字符串长度为1024,因此,如果混淆过的有效载荷的长度大于该值,则可能需要借助字符串连接操作进行重组。
字符串连接可以提高AV的检出率,因为这种操作常见于像Emotet之类的maldoc活动中。
Emotet在创建进程之前重新组装有效载荷
使用构建器支持更大有效载荷的好处是,能使第二阶段的攻击更加强大。
无论有效载荷是大是小,通过对有效载荷进行混淆处理而实现非标准编码或加密,并尽可能少地使用字符串操纵函数,就能够显著降低被静态分析和AV软件检出的可能性。
需要避免大量使用的函数包括Left()、Right()、Mid()、Chr()、ChrW()等,严格来说,凡事与字符串操作或字符解码有关的函数,都应该尽量少用。对于某些简单的去混淆方法,例如“Chr(115) + Chr(116) + Chr(117)”,由于在各种maldoc过程中会经常用到,因此,很容易被检出。
就本例来说,由于我们使用的有效载荷非常小,所以,完全可以将其放到一行代码中,因此,完全不必进行重新组装。
对于ASCII的解码工作,是通过一组函数来完成的,而这些函数都是通过各个月份和工作日的名称来进行命名的,这使得它们非常难以指纹化。
为了浏览存储的有效载荷并对其进行解码,我们提供了一个函数June,而它就用到了上述函数。
为了尽可能地隐藏我们的意图,我们对所有的字符串都进行了编码处理,而June就是用于解码的。在创建进程的时候,由于我们是使用未初始化的变量来表示Null和0值的,因此,用于查找WMI进程创建参数的签名通常很难奏效。
经过上述处理之后,我们的代码仍会被7种防病毒软件检出,虽然看上去没有任何改进,实则不然——我们的代码更有弹性了,换句话说,可以添加任意数量的有效载荷,但是检出率并没有上升。
在这个示例中,我们通过Rot9方式对字符串进行了模糊处理。这仅需要对VBA代码进行字面上的处理即可。现在,我们的字符串是很难通过字面来了解其含义,不仅无法在仿真或沙箱环境中使用,而且也无法利用签名来查找特定的有效载荷字符串。但是,这里的VBA代码的结构仍然可以用于签名,不过,由于我们使用的大部分内容都存在于实际业务进程的VBA中,因此,我们的代码已经变得更有弹性。
就本例来说,为了对输入到VBA中的ASCII码进行Rot9处理,我们可以通过一个简短的PowerShell脚本来完成这项任务。ASCII码总是使用3位数表示,这不仅便于解码,同时,我们也不必将有效载荷存储到一个数组中,这样的话,就不会因为数组太大而引起怀疑了。
Anti-Sandbox(离线)与Anti-FakeNet功能
我们可以利用VBA实现沙箱检测功能以防止代码在沙箱环境中执行,重要的是,这并不会显著提高被AV检出的可能性。
实际上,https://github.com/joesecurity/pafishmacro
页面是一个启发灵感的好地方,但我不建议原封不动的照搬这里的解决方案。我们希望通过WMI来摆脱与WINWORD.EXE进程相关的各种行为,为此,可以使用WMI方法Win32_PingStatus来绕过沙箱和FakeNet。这样的话,wmiprvse.exe就会成为与DNS和ICMP流量相关的进程,相反,如果流量来自WINWORD.EXE进程的话,那就可能引起人们的怀疑。
第一项检查,是看看能否解析location.microsoft.com。如果它可以解析,或者我们可以ping主机的话,说明当前位于FakeNet中——因为location.microsoft.com是一个根本不存在的域。
第二项检查,是看看环境变量userdomain和computername的值是否相同。如果相同的话,则说明该系统未加入域。
只有当两者都返回True时,我们才会继续运行有效载荷。事实证明,上述方法能够绕过自动化的沙箱系统,并且在基于沙箱的行为报告中,该样本也能够撇清与ICMP和DNS流量之间的瓜葛。
如果同时使用上一节中的方法来混淆字符串的话,该样本的检出率会降至3。
badbf30a710a65e12bb0dad3b92d6a1938466cc6eca6110d63e909f305a824f1
总之,如果您希望降低VBA的检出率的话,应该:
•避免直接使用来自攻击模拟框架中的代码(安全公司喜欢从这些代码中提取指纹)
•对于静态分析期间可见的有效载荷,可以进行非标准加密或编码处理
•如果需要使用某些(例如Chr()等)函数,但是又不想引起怀疑的话,最好将其化整为零
构建高质量的VBA代码非常重要,为此,我们还有许多工作要做。在下一篇文章中,我们将继续为读者介绍其他混淆技术,以及相关的Office内部运行机制,从而最大限度地降低AntiVirus产品的检出率。