CtrlK
BlogDocsLog inGet started
Tessl Logo

anti-debug-bypass

Detect and neutralize anti-debug / anti-VM checks — IsDebuggerPresent, ptrace, NtGlobalFlag, timing, hardware-breakpoint detection.

66

Quality

81%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Critical

Do not install without reviewing

SKILL.md
Quality
Evals
Security

Anti-Debug Bypass Playbook

Malware and protected commercial software check for debuggers and sandboxes before running real logic. Bypassing these checks is required to dynamically analyze them. Each check has a known counter.

1. Enumerate anti-debug techniques in the binary

Static signature scan

# Windows API calls
strings /tmp/sample | grep -iE 'IsDebuggerPresent|NtQuery|CheckRemoteDebugger|OutputDebugString'

# Linux ptrace check
strings /tmp/sample | grep -iE 'ptrace|/proc/self/status|TracerPid'

# CPUID hypervisor check
strings /tmp/sample | grep -iE 'vmware|VirtualBox|qemu|xen'

# Detect via YARA rules
yara -r /opt/yara-rules/anti_debug.yar /tmp/sample

Decepticon helper:

bin_anti_debug_scan("/tmp/sample")

2. Common checks + bypasses

Windows checks

CheckWhat it doesBypass
IsDebuggerPresent()reads PEB.BeingDebugged byteSet PEB.BeingDebugged = 0 in debugger; ScyllaHide handles
CheckRemoteDebuggerPresent()calls NtQueryInformationProcess(ProcessDebugPort)Patch return to FALSE; ScyllaHide hooks the syscall
NtQueryInformationProcess(ProcessDebugPort)returns nonzero if debugger attachedHook + return 0
NtQueryInformationProcess(ProcessDebugFlags)returns 0 if debugger, 1 if notForce return 1
NtQueryInformationProcess(ProcessDebugObjectHandle)nonzero handle if attachedForce NULL
PEB.NtGlobalFlag0x70 if heap debuggingSet to 0
PEB.HeapFlags & PEB.ForceFlagsnon-default if debuggerReset to defaults
NtSetInformationThread(ThreadHideFromDebugger)unhook debugger from threadHook NtSetInformationThread
INT 2D / INT 3 exception handlingnormal flow if no debuggerSet exception handler in debugger
Hardware breakpoint detection (GetThreadContext check)reads DR0-3, fails if BPs setUse software BPs, or zero DRs before check

ScyllaHide (x64dbg/x32dbg/IDA plugin) handles essentially all of these automatically.

Linux checks

CheckWhat it doesBypass
ptrace(PTRACE_TRACEME)fails if already tracedRun w/o ptrace, or use LD_PRELOAD to hook
Read /proc/self/status TracerPid:nonzero if debuggerLD_PRELOAD hook reading; or modify /proc on a fork
prctl(PR_SET_DUMPABLE, 0)prevents gdb attachPatch out the prctl
getppid() parent process nameif it's gdb/stracerename gdb binary, or LD_PRELOAD getppid
Timing checks via rdtscmeasures execution timeUse gdb's set $rax = ... to fake; or patch rdtsc out

LD_PRELOAD bypass example

// bypass.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <string.h>

long ptrace(int request, int pid, void *addr, void *data) {
    return 0;  // pretend it always succeeds
}

FILE *fopen(const char *path, const char *mode) {
    static FILE *(*orig)(const char *, const char *) = NULL;
    if (!orig) orig = dlsym(RTLD_NEXT, "fopen");
    if (strstr(path, "/proc/self/status") || strstr(path, "/proc/self/stat")) {
        // Return a doctored file
        FILE *tmp = tmpfile();
        fprintf(tmp, "TracerPid:\t0\n");
        rewind(tmp);
        return tmp;
    }
    return orig(path, mode);
}
gcc -shared -fPIC bypass.c -o bypass.so -ldl
LD_PRELOAD=./bypass.so gdb /tmp/sample

3. Anti-VM / sandbox detection

CheckBypass
CPUID leaf 0x40000000 (hypervisor bit)Mask CPUID via KVM -cpu host,-hypervisor or VMM config
VMware backdoor 0x564D5868 magic via IN/OUTPatch the magic number check
MAC address vendor (00:0C:29 = VMware)Spoof MAC in VM config
Disk size < 50GBAllocate larger disk for the analysis VM
RAM < 2GBProvision more RAM
Username sandbox, vagrant, virtualChange username in analysis env
Recent file count lowPre-populate Documents folder before run
Mouse cursor never movesUse xdotool to inject mouse jitter
Process count, uptime, kernel objectsBoot the VM a while before analysis

4. Dynamic bypass via debugger

x64dbg / x32dbg (Windows)

  1. Install ScyllaHide plugin
  2. In the plugin, enable all checks (PEB patches, NtSetInformation hooks, etc)
  3. Open the binary, set BP at entry → continue
  4. ScyllaHide neutralizes most checks transparently

IDA Pro

  • Built-in remote debugger + IDAStealth plugin
  • For step-tracing through anti-debug: Debugger options → Suspend on library load/unload = no

radare2 / r2dbg

r2 -d /tmp/sample
> e dbg.aslr = false
> dc                  # continue, see where it dies
> dbt                 # backtrace at SIGSEGV / exit

gdb / pwndbg

For Linux:

gdb /tmp/sample
> set follow-fork-mode parent
> set detach-on-fork off
> catch syscall ptrace
> run
# When hit, override
> return 0
> continue

5. Patching for static-replay analysis

If you only need to analyze the unpacked / decrypted state, sometimes easier to patch the anti-debug checks to no-ops:

# Find the check
r2 -A /tmp/sample
> afl ~ debug
> s sym.imp.IsDebuggerPresent
> /c call sym.imp.IsDebuggerPresent
> # for each hit, patch w/ "xor eax,eax; ret"
> wx 31c0c3 @ <addr>

Caution: patching may break self-checksums. Run static-validation YARA post-patch to ensure binary still loads.

6. Promote

kg_add_node(kind="observation", label="anti-debug: <check-name>",
            props={"sample":"<sha256>","check":"<name>","bypassed":<bool>})
kg_add_edge(src=<sample>, dst=<observation>, kind="exhibits")

OPSEC (for malware analysis)

  • Run in isolated VM w/ NO connectivity to your network — many anti-VM checks involve DNS / HTTP probes
  • Snapshot before run, revert after
  • Don't analyze on host w/ persistent creds in browsers
  • For commercial protected SW (legitimate analysis), document authorization to bypass DRM-adjacent protections

Tool cheat sheet

ToolUse for
ScyllaHidex64dbg/IDA plugin, neutralizes Windows checks
HideDebuggerOlder but still useful x32dbg plugin
Phant0mOllyDbg-era plugin
gdb-peda / pwndbg / gefgdb plugins w/ anti-debug awareness
ltrace / straceobserve library / syscall use
fridaruntime hooking, can no-op checks dynamically
MalwareAnalysisSandbox / Cuckoofull automated detonation w/ anti-anti-VM
unpac.mecommunity unpack service (engagement-permitting)

Known exemplars

  • Stuxnet: multiple anti-VM checks (Siemens PLC env detection)
  • Conti / Ryuk: PEB checks, sleep timer skipping, mouse-cursor check
  • Most banking trojans (Trickbot, Emotet): full Anti-Debug + anti-sandbox + anti-emul
  • Cobalt Strike beacons: lighter anti-debug, more anti-AV focus
  • iOS / Android packers: ptrace + frida-detect (objection bypasses most)
Repository
PurpleAILAB/Decepticon
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.