引言
随着网络安全威胁的日益复杂,恶意软件与反病毒软件(杀毒软件,简称“杀软”)之间的对抗愈发激烈。现代杀软不仅依赖传统的静态查杀技术,还结合了流量分析、动态行为监控等手段,形成了多层次的防御体系。然而,攻击者也在不断进化,通过流量伪装、内存对抗、行为隐藏等技术绕过杀软的检测。本文将从流量对抗、行为对抗、杀软的查杀特点以及相关技术四个方面,系统分析现代杀软对抗的核心策略和技术手段,旨在为安全研究人员提供参考。
一、流量对抗
在网络安全领域,流量分析是杀软和端点检测与响应(EDR)系统的重要查杀手段之一。通过分析网络流量,杀软可以检测到异常的通信模式、已知的恶意域名或IP地址,以及可疑的数据包结构。为了对抗流量查杀,攻击者通常会利用以下技术来伪装或改造流量:
1.1 OSS与CDN改造C2流量
命令与控制(C2,Command and Control)服务器是恶意软件与攻击者通信的核心。传统的C2流量特征明显,容易被杀软的流量分析模块识别。为了规避检测,攻击者常利用对象存储服务(OSS)和内容分发网络(CDN)来改造C2流量。
- OSS(对象存储服务):攻击者将C2服务器的通信数据存储在云服务提供商的OSS中,例如AWS S3、阿里云OSS等。通过将恶意指令伪装为普通的云存储访问流量,攻击者可以有效隐藏C2通信的真实目的。例如,恶意软件可能通过GET/POST请求从OSS中获取加密的指令文件,杀软难以从这些流量中直接识别出恶意行为。
- CDN(内容分发网络):CDN被广泛用于加速合法网站的访问,但攻击者可以利用CDN的高信誉性来掩盖C2流量。通过将C2服务器隐藏在CDN节点之后,恶意软件的通信流量会被伪装成对知名CDN提供商(如Cloudflare、Akamai)的访问流量,从而降低被拦截的概率。
1.2 流量加密与协议伪装
为了进一步隐藏C2流量,攻击者还会采用加密技术和协议伪装。例如,使用TLS/SSL加密通信,或者将C2流量伪装成HTTP/2、WebSocket甚至DNS流量。这些协议在合法网络通信中广泛使用,杀软难以直接区分合法流量与恶意流量。此外,攻击者还可能利用域名生成算法(DGA)生成动态域名,进一步增加流量分析的难度。
二、行为对抗
行为对抗是现代杀软对抗的核心领域,攻击者通过在内存中执行恶意代码、隐藏危险行为以及绕过动态检测机制来规避杀软的查杀。以下是行为对抗的主要技术:
2.1 内存对抗
内存对抗是行为对抗的核心,攻击者通过在内存中直接执行恶意代码(Shellcode)来避免在磁盘上留下痕迹,从而绕过杀软的静态查杀。以下是内存对抗的常见流程:
- 申请可执行内存:攻击者通常使用
VirtualAlloc函数申请一块可执行内存(具有PAGE_EXECUTE_READWRITE权限),用于存储解密的Shellcode。 - 解密与拷贝:将加密的Shellcode解密后,使用
memcpy等函数将其拷贝到申请的内存中。 - 执行Shellcode:通过函数指针(例如
((void(*)())exec)())直接执行内存中的Shellcode。
为了规避杀软对VirtualAlloc等高危函数的监控,攻击者可能采用以下技术:
- 间接系统调用(Syscall):通过直接调用
ntdll.dll中的NT函数(如NtAllocateVirtualMemory),绕过kernel32.dll的API调用链,从而隐藏函数调用行为。 - 堆栈欺骗(Spoof Call):通过修改调用堆栈,伪装调用者的返回地址,使杀软难以追踪实际的函数调用链。
- 动态调用:通过解析进程环境块(PEB)并结合哈希算法动态加载API地址,避免直接在导入表(IAT)中暴露危险函数。
2.2 隐藏危险行为
攻击者还会通过隐藏危险行为来规避杀软的动态查杀。例如:
- 绕过Shell命令检测:传统的C2框架(如Metasploit、Cobalt Strike)可能通过启动
cmd.exe或powershell.exe执行命令,但这些行为容易被杀软检测。攻击者可以通过开发自定义插件(例如Beacon Object File,BOF),使用C语言和Windows API实现类似功能,绕过AMSI(反恶意软件扫描接口)保护。 - 进程注入:攻击者通过
OpenProcess获取目标进程的句柄,并使用WriteProcessMemory和CreateRemoteThread将Shellcode注入目标进程。然而,OpenProcess是一个高危函数,容易触发杀软报警。为此,攻击者可能使用无文件执行(Fileless Execution)或内存加载技术,减少对目标进程的直接修改。 - 注册表操作与计划任务:通过修改注册表或创建计划任务实现持久化,但这些操作也可能被杀软监控。为此,攻击者可能使用加密的注册表键值或伪装成合法服务的计划任务。
2.3 绕过CFG保护
控制流保护(CFG,Control Flow Guard)是Windows系统的一种安全机制,用于保护进程免受恶意修改。攻击者通过以下方式绕过CFG:
- 间接调用:避免直接修改目标进程的代码段,而是通过劫持合法线程或修改内存中的函数指针实现控制流转移。
- 无文件执行:在内存中直接执行Shellcode,避免触发CFG的检测机制。
三、杀软的查杀特点
现代杀软的查杀机制主要分为三类:流量查杀、静态查杀和动态查杀。攻击者需要针对每种查杀机制设计相应的对抗策略。
3.1 流量查杀
流量查杀通过分析网络通信的特征(如域名、IP、协议、数据包内容)来识别恶意行为。杀软通常会关注以下特征:
- 已知的恶意域名或IP地址。
- 异常的流量模式,例如高频次的短连接或不寻常的加密流量。
- 可疑的数据包内容,例如包含特定Shellcode片段的HTTP请求。
攻击者的对抗策略包括使用OSS/CDN、加密流量、DGA等方式,前面已详细讨论。
3.2 静态查杀
静态查杀通过分析可执行文件的结构和内容来判断其是否为恶意软件。以下是静态查杀的几个核心方面:
3.2.1 IAT(导入地址表)分析
杀软会检查程序的IAT,寻找是否存在高危函数(如VirtualAlloc、CreateRemoteThread)。攻击者可以通过以下方式隐藏危险函数:
- 动态调用:通过解析PEB(进程环境块)并结合哈希算法动态加载API地址,避免在IAT中直接暴露危险函数。
- 加密IAT:将IAT中的函数名称加密,加载时动态解密。
3.2.2 签名检测
杀软会验证可执行文件的数字签名。Windows 11引入了更严格的签名检查机制,包括对过期签名的检测。攻击者的对抗策略包括:
- 白+黑组合:使用合法签名的可执行文件(白程序)作为Loader,加载加密的Shellcode或恶意DLL(黑程序)。
- DLL劫持:通过劫持合法程序的DLL加载过程,将恶意DLL注入到目标进程。
3.2.3 熵值分析
高熵值通常表示文件包含大量加密字符串或混淆代码,容易被杀软标记为可疑。攻击者可以通过以下方式降低熵值:
- 分段加密:将加密字符串分散存储,避免单一文件的高熵特征。
- 动态解密:在运行时动态解密字符串,减少静态文件中可疑内容的比例。
3.2.4 Hash分析
杀软通过计算文件的哈希值(如MD5、SHA256)来识别已知的恶意文件。攻击者可以通过以下方式规避Hash检测:
- 多态代码:每次生成不同的代码变种,改变文件的哈希值。
- 白+黑分离:将恶意代码与合法代码分离,降低白程序被标记的概率。
需要注意的是,国外的EDR(如CrowdStrike、Carbon Black)更注重动态行为分析,而国内的杀软(如360、火绒)对静态查杀的依赖较重。
3.3 动态查杀
动态查杀通过监控程序的运行时行为来检测恶意活动。以下是动态查杀的几个关键点:
3.3.1 函数调用链监控
杀软会监控高危函数的调用链,例如VirtualAlloc -> memcpy -> 函数指针执行的典型Shellcode执行流程。攻击者的对抗策略包括:
- Syscall:通过直接调用NT函数,隐藏
kernel32.dll的调用链。 - Spoof Call:通过堆栈欺骗伪装调用者的返回地址。
- VEH(异常处理机制):通过注册异常处理程序(Vectored Exception Handler)拦截杀软的监控行为。
3.3.2 危险操作检测
杀软会监控以下高危操作:
- Shell命令执行:如启动
cmd.exe或powershell.exe。攻击者可通过BOF或自定义API实现类似功能,绕过AMSI保护。 - 进程注入:如使用
OpenProcess获取目标进程句柄。攻击者可通过无文件执行或内存加载技术减少注入痕迹。 - 注册表操作:如修改启动项或创建计划任务。攻击者可使用加密键值或伪装合法服务。
- Hook检测:杀软(如Bitdefender)会在用户态(R3)设置函数钩子(Hook)来监控API调用。攻击者可通过Unhook技术移除这些钩子,或者通过汇编指令(如
jmp)直接跳转到目标函数。
四、技术实现
以下是一些现代杀软对抗中常用的技术手段,涵盖动态调用、PEB+Hash、VEH、Syscall、Hook等。
4.1 动态调用(PEB+Hash)
动态调用通过解析PEB动态加载API地址,避免在IAT中暴露危险函数。以下是一个简单的动态调用示例:
#include <windows.h>
#include <winternl.h>
typedef FARPROC (WINAPI *GetProcAddress_t)(HMODULE, LPCSTR);
typedef HMODULE (WINAPI *LoadLibraryA_t)(LPCSTR);
void *GetFuncAddress(const char *funcName) {
PPEB peb = (PPEB)__readgsqword(0x60); // 获取PEB地址(64位系统)
PPEB_LDR_DATA ldr = peb->Ldr;
PLIST_ENTRY moduleList = &ldr->InMemoryOrderModuleList;
// 遍历模块列表,查找kernel32.dll
for (PLIST_ENTRY entry = moduleList->Flink; entry != moduleList; entry = entry->Flink) {
PLDR_DATA_TABLE_ENTRY module = (PLDR_DATA_TABLE_ENTRY)((BYTE *)entry - sizeof(LIST_ENTRY));
if (wcsstr(module->FullDllName.Buffer, L"kernel32.dll")) {
HMODULE hModule = (HMODULE)module->DllBase;
GetProcAddress_t pGetProcAddress = (GetProcAddress_t)GetProcAddress(hModule, "GetProcAddress");
return pGetProcAddress(hModule, funcName);
}
}
return NULL;
}
上述代码通过解析PEB查找kernel32.dll的基址,并动态获取目标函数的地址,避免在IAT中直接引用。
4.2 Syscall与Hook
通过直接调用ntdll.dll中的NT函数,攻击者可以绕过杀软的API监控。例如,调用NtAllocateVirtualMemory替代VirtualAlloc。以下是一个简单的Syscall示例:
#include <windows.h>
#include <winternl.h>
typedef NTSTATUS (NTAPI *NtAllocateVirtualMemory_t)(
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG_PTR ZeroBits,
PSIZE_T RegionSize,
ULONG AllocationType,
ULONG Protect
);
void SyscallVirtualAlloc() {
NtAllocateVirtualMemory_t pNtAllocateVirtualMemory =
(NtAllocateVirtualMemory_t)GetFuncAddress("NtAllocateVirtualMemory");
PVOID baseAddress = NULL;
SIZE_T regionSize = 0x1000;
NTSTATUS status = pNtAllocateVirtualMemory(
GetCurrentProcess(),
&baseAddress,
0,
®ionSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
}
4.3 360对抗
360杀软在国内市场以其强大的静态查杀和熵值分析而闻名。针对360的对抗策略包括:
- 降低熵值:通过分段加密和动态解密减少静态文件中高熵字符串的比例。
- 白+黑分离:使用合法签名的白程序作为Loader,加载加密的Shellcode或DLL。
- 内存对抗:在内存中执行Shellcode,避免在磁盘上留下痕迹。
4.4 卡巴斯基对抗
卡巴斯基(Kaspersky)对内存行为的监控较为严格,特别是在Shellcode执行频率和内存操作方面。攻击者的对抗策略包括:
- 延迟执行:在执行Shellcode前加入长时延(如Sleep 10分钟以上),降低执行频率。
- 无文件执行:通过内存加载技术直接在内存中运行恶意代码,规避文件扫描。
五、总结
现代杀软对抗是一场技术和策略的博弈。攻击者通过流量伪装、内存对抗、行为隐藏等手段,试图绕过杀软的流量查杀、静态查杀和动态查杀机制。流量对抗利用OSS、CDN和加密技术隐藏C2通信;行为对抗通过动态调用、Syscall、堆栈欺骗等技术规避动态监控;针对360、卡巴斯基等杀软的特定对抗策略则需要更精细的优化。
未来,随着杀软和EDR技术的不断发展,攻击者需要持续创新,开发更隐蔽的对抗技术。同时,安全研究人员也需要深入理解这些对抗手段,以设计更有效的防御机制。在这场攻防对抗中,技术的快速迭代和情报的及时共享将成为决定胜负的关键。
原文 https://blog.csdn.net/2301_79518550/article/details/148146524