Anti-Analysis Techniques
Evasion
Malware authors use anti-analysis techniques to hinder reverse engineering. Understanding these techniques helps analysts bypass them during investigation.
Isolate Before You Analyse
Nothing on this page is safe to try on a working machine. Never analyse an unknown sample on a production
or networked host. Work inside a dedicated virtual machine with no shared folders or clipboard, and with a
host-only adapter or no networking at all; snapshot the VM before every execution and revert to it
afterwards. Assume any sample may be evasive enough to detect your tooling and destructive enough to
encrypt or wipe the guest — the checks below are exactly what a sample uses to decide whether to detonate.
Anti-Debugging
anti-debug.c
// Common anti-debugging techniques
// 1. IsDebuggerPresent (Windows API)
if (IsDebuggerPresent()) {
exit(1);
}
// 2. CheckRemoteDebuggerPresent
BOOL debugged = FALSE;
CheckRemoteDebuggerPresent(GetCurrentProcess(), &debugged);
// 3. PEB.BeingDebugged flag (manual check)
// fs:[0x30] points to PEB, offset 0x2 is BeingDebugged
mov eax, dword ptr fs:[0x30]
movzx eax, byte ptr [eax+0x2]
test eax, eax
jnz debugger_detected
// 4. Timing checks
DWORD start = GetTickCount();
// ... some code ...
DWORD end = GetTickCount();
if ((end - start) > 1000) { // Too slow = debugger
exit(1);
}
// 5. Hardware breakpoint detection
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(GetCurrentThread(), &ctx);
if (ctx.Dr0 || ctx.Dr1 || ctx.Dr2 || ctx.Dr3) {
exit(1);
}
// Bypass: patch IsDebuggerPresent to return 0, or load the ScyllaHide plugin.
// TitanHide, the older hypervisor-based hider, is not a current option: its own
// README warns of bug check 0x109 CRITICAL_STRUCTURE_CORRUPTION on modern
// Windows and sends users to ScyllaHide instead.VM Detection
Samples that refuse to run on an analyst's machine are usually testing for hypervisor artefacts rather than for a debugger. The checks are cheap and broad, and most of them read state that a default guest installation leaves in place:
-
Registry keys written by guest additions, such as
HKLM\SOFTWARE\VMware, Inc.\VMware ToolsorHKLM\SOFTWARE\Oracle\VirtualBox Guest Additions. -
MAC address prefixes assigned to virtual adapters:
00:0C:29and00:50:56(VMware),08:00:27(VirtualBox). -
Processes and drivers belonging to the guest tools —
vmtoolsd.exe,VBoxService.exe,vmmouse.sys. - Timing and resource counts — core count, RAM size and disk serial are compared against values typical of a lab VM.
cpuid-hypervisor.c
// CPUID leaf 1: ECX bit 31 is the hypervisor-present bit
#include <intrin.h>
int cpuInfo[4];
__cpuid(cpuInfo, 1);
if (cpuInfo[2] & (1 << 31)) {
// Running under a hypervisor - a sample may refuse to continue here
}Reducing the VM Footprint
There is no single switch that hides a hypervisor. Removing the guest additions, renaming the driver
files, randomising the MAC prefix and matching a plausible core count and RAM size removes the cheap
tells; the CPUID bit is the one check that survives a well-tuned hypervisor, which is why some analysis
work still moves to bare metal.