Cheat sheet — Anti-Analysis Techniques¶
Companion to Module 10 — Anti-Analysis Techniques · CC BY 4.0 — print it, pin it, share it.
Last reviewed: 2026-07
Only run live malware in an isolated, disposable analysis VM with no bridged network. Every bypass here still detonates the sample — reset to clean afterward.
The three families — what to recognise¶
| Family | Example check | Bypass |
|---|---|---|
| Environment | /proc/cpuinfo hypervisor flag, sandbox user |
modify the environment, not binary |
| Timing | delta between two timestamps; stall loops | freeze the clock (LD_PRELOAD) |
| Code-flow | exception handlers, self-modifying, TLS callbacks | manual patch / dynamic dump |
Detect the check with strace¶
strace -f ./sample 2>&1 | grep -E 'ptrace|cpuid|clock_gettime|gettimeofday|nanosleep'
strace -e trace=ptrace ./sample # see the PTRACE_TRACEME probe fire
ptrace(PTRACE_TRACEME)is the canonical Linux debugger check: only one tracer at a time, so if it returns -1 the process is already being debugged and the malware bails. (Windows:IsDebuggerPresent(),NtQueryInformationProcessclass 7.)
LD_PRELOAD hook — defeat ptrace and freeze the clock¶
// hooks.c — return success for ptrace, zero the timing delta
#define _GNU_SOURCE
#include <sys/ptrace.h>
#include <time.h>
long ptrace(int req, ...) { return 0; } // pretend "not traced"
int clock_gettime(clockid_t c, struct timespec *t) { // freeze the clock
t->tv_sec = 0; t->tv_nsec = 0; return 0; // elapsed delta → 0
}
gcc -shared -fPIC -o hooks.so hooks.c
LD_PRELOAD=./hooks.so ./sample # libc wrappers hit our stubs first
LD_PRELOADintercepts the libc wrapper before the syscall — clean and no debugger needed. Timing checks compare two timestamps; freeze either side and the comparison breaks in your favour.
Environment bypass — hypervisor flags¶
grep -E 'hypervisor|vmware|kvm' /proc/cpuinfo # what the sample scans for
# CPUID/proc reflect REAL hardware — you change the environment, not the binary:
# - present a modified /proc/cpuinfo (bind-mount / overlay)
# - VMware: set hypervisor.cpuid.v0 = FALSE
# - or run the sample on bare metal
Bypass hierarchy — work up it¶
1. strace — intercepts syscalls without a full debugger; some ptrace checks won't fire
2. LD_PRELOAD .so — return success from ptrace(); hook clock_gettime for timing
3. manual patch — NOP the check / flip the jump when the above fail (static-linked binaries)
Author the detection — flag the evasion itself¶
rule linux_anti_analysis {
meta: attck = "T1497"
strings:
$p = "PTRACE_TRACEME"
$c = "/proc/cpuinfo"
$h = "hypervisor"
condition:
2 of them // fire on the demo binary, quiet on benign
}
Gotchas worth remembering¶
- "The sample did nothing" is the most dangerous result to report uncritically. "Did nothing" and "detected me and went quiet" look identical and mean opposite things — the first clears it, the second is a missed live threat.
LD_PRELOADonly works on dynamically linked binaries. Go and Rust malware often statically links libc — the hook does nothing and you need kernel-level interception or a manual patch.- The sample can detect
straceitself. Choosing the wrong bypass wastes the run — aptracecheck may see the tracer and bail. - Hypervisor flags are real hardware data, not something the binary invents — you bypass by changing the environment (
/proc/cpuinfo,hypervisor.cpuid.v0=FALSE, bare metal), never by patching the binary. - A suggested bypass is not a working one. Confirm each by running the demo binary with and without it — reading the AI's suggestion is not confirmation.
Comments
Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).