Skip to content
Security
Skill

/anti-debugging-techniques

Anti-debugging detection and bypass playbook. Use when reversing protected binaries that detect debuggers via ptrace, PEB flags, timing checks, or signal/exception handlers on Linux and Windows.

From plugin
hack-skills
2.6k103 skills

Claude Code

$ npx -y skills add yaklang/hack-skills --skill anti-debugging-techniques --agent claude-code

SKILL.md

anti-debugging-techniques.SKILL.md
name: anti-debugging-techniques
description: >-
  Anti-debugging detection and bypass playbook. Use when reversing protected
  binaries that detect debuggers via ptrace, PEB flags, timing checks, or
  signal/exception handlers on Linux and Windows.

SKILL: Anti-Debugging Techniques — Detection & Bypass Playbook

> **AI LOAD INSTRUCTION**: Expert anti-debug techniques across Linux and Windows. Covers ptrace, PEB flags, NtQueryInformationProcess, timing attacks, signal-based detection, TLS callbacks, VEH tricks, and all corresponding bypass methods. Base models often miss the distinction between user-mode and kernel-mode detection and the correct patching strategy for each.

0. RELATED ROUTING

  • [code-obfuscation-deobfuscation](../code-obfuscation-deobfuscation/SKILL.md) when the binary also uses control flow flattening, VM protection, or string encryption
  • [vm-and-bytecode-reverse](../vm-and-bytecode-reverse/SKILL.md) when the anti-debug sits inside a custom VM dispatcher
  • [symbolic-execution-tools](../symbolic-execution-tools/SKILL.md) when you want to symbolically skip anti-debug checks entirely

Advanced Reference

Also load [ANTI_DEBUG_MATRIX.md](./ANTI_DEBUG_MATRIX.md) when you need:

  • Complete cross-reference matrix of technique × OS × detection method × bypass method
  • Per-technique reliability ratings and false-positive notes
  • Tool compatibility chart (GDB, x64dbg, WinDbg, Frida, ScyllaHide)

Quick bypass picks

| Detection Class | First Bypass | Backup | |---|---|---| | ptrace-based (Linux) | `LD_PRELOAD` hook `ptrace()` → return 0 | Kernel module to hide tracer | | PEB.BeingDebugged (Windows) | Patch PEB byte at `fs:[0x30]+0x2` | ScyllaHide auto-patch | | Timing check (rdtsc) | Conditional BP after rdtsc, fix registers | Frida hook `rdtsc` return | | IsDebuggerPresent | NOP the call / hook return 0 | x64dbg built-in hide | | INT 2D / UD2 exception | Set VEH to handle gracefully | TitanHide driver |

---

1. LINUX ANTI-DEBUG TECHNIQUES

1.1 ptrace(PTRACE_TRACEME)

The classic self-attach: a process calls `ptrace(PTRACE_TRACEME, 0, 0, 0)`. If a debugger is already attached, the call fails (returns -1).

if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) {
    exit(1); // debugger detected
}

**Bypass methods**:

| Method | How | |---|---| | `LD_PRELOAD` shim | Compile shared lib: `long ptrace(int r, ...) { return 0; }` and set `LD_PRELOAD` | | Binary patch | NOP the `ptrace` call or patch return value check | | GDB catch | `catch syscall ptrace` → modify `$rax` to 0 on return | | Kernel module | Hook `sys_ptrace` to allow multiple tracers |

1.2 /proc/self/status — TracerPid

FILE *f = fopen("/proc/self/status", "r");
// parse TracerPid: if non-zero → debugger attached

**Bypass**: Mount a FUSE filesystem over `/proc/self`, or `LD_PRELOAD` hook `fopen`/`fread` to filter `TracerPid` to 0.

1.3 Timing Checks (rdtsc / clock_gettime)

Measures elapsed time between two points; debugger single-stepping causes noticeable delay.

rdtsc
mov ebx, eax       ; save low 32 bits
; ... protected code ...
rdtsc
sub eax, ebx
cmp eax, 0x1000    ; threshold
ja  debugger_detected

**Bypass**: Set hardware breakpoint after second `rdtsc`, modify `eax` to pass the comparison. Or use Frida to replace the timing function.

1.4 Signal-Based Detection (SIGTRAP)

volatile int caught = 0;
void handler(int sig) { caught = 1; }
signal(SIGTRAP, handler);
raise(SIGTRAP);
if (!caught) exit(1); // debugger swallowed the signal

When a debugger is attached, `SIGTRAP` is consumed by the debugger rather than delivered to the handler. **Bypass**: In GDB, use `handle SIGTRAP nostop pass` to forward the signal.

1.5 /proc/self/maps & LD_PRELOAD Detection

Checks for injected libraries or memory regions characteristic of debuggers/instrumentation.

FILE *f = fopen("/proc/self/maps", "r");
while (fgets(buf, sizeof(buf), f)) {
    if (strstr(buf, "frida") || strstr(buf, "LD_PRELOAD"))
        exit(1);
}

**Bypass**: Hook `fopen("/proc/self/maps")` to return a filtered version, or rename Frida's agent library.

1.6 Environment Variable Checks

Some protections check for `LD_PRELOAD`, `LINES`, `COLUMNS` (set by GDB's terminal), or debugger-specific env vars.

**Bypass**: Unset suspicious env vars before launch, or hook `getenv()`.

---

2. WINDOWS ANTI-DEBUG TECHNIQUES

2.1 IsDebuggerPresent / CheckRemoteDebuggerPresent

if (IsDebuggerPresent()) ExitProcess(1);

BOOL debugged = FALSE;
CheckRemoteDebuggerPresent(GetCurrentProcess(), &debugged);
if (debugged) ExitProcess(1);

**Bypass**: Hook `kernel32!IsDebuggerPresent` to return 0, or patch PEB directly.

2.2 PEB Flags

| Field | Offset (x64) | Debugged Value | Normal Value | |---|---|---|---| | `BeingDebugged` | `PEB+0x02` | 1 | 0 | | `NtGlobalFlag` | `PEB+0xBC` | `0x70` (FLG_HEAP_*) | 0 | | `ProcessHeap.Flags` | Heap+0x40 | `0x40000062` | `0x00000002` | | `ProcessHeap.ForceFlags` | Heap+0x44 | `0x40000060` | 0 |

mov rax, gs:[0x60]    ; PEB
movzx eax, byte [rax+0x02]  ; BeingDebugged
test eax, eax
jnz debugger_detected

**Bypass**: Zero all four fields. ScyllaHide does this automatically.

2.3 NtQueryInformationProcess

| InfoClass | Value | Debugged Return | |---|---|---| | `ProcessDebugPort` | 0x07 | Non-zero port | | `ProcessDebugObjectHandle` | 0x1E | Valid handle | | `ProcessDebugFlags` | 0x1F | 0 (inverted!) |

**Bypass**: Hook `ntdll!NtQueryInformationProcess` to return clean values per info class.

2.4 Hardware Breakpoint Detection

CONTEXT ctx;
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(GetCurrentThread(), &ctx);
if (ctx.Dr0 || ctx.Dr1 || ctx.Dr2 || ctx.Dr3)
    ExitProcess(1);

**Bypass**: Hook `GetThreadContext` to zero DR0–DR3, or use `NtSetInformationThread(ThreadHideFromDebugger)` preemptively (ironically, the anti-debug technique itself).

2.5 INT 2D / INT 3 / UD2 Exception Tricks

`INT 2D` is the ke

Read more
@yaklang
Ships withhack-skills

Master Entry → Category Entries → Deep Topic Skills One master entry, six category entries, and 102 deep topic skills across 14 security domains.

2.6k103 skills
Get the whole plugin

Stars on GitHub

Momentum

stars in total
2.6k
Star history of yaklang/hack-skills on GitHub, a chart by star-history.com

Other skills on hack-skills.

ai-ml-security

ai-ml-security

AI/ML security playbook. Use when assessing model supply chain attacks (pickle RCE, poisoned weights), adversarial examples,…

@yaklang@yaklangInstall Skill

More skills from other plugins.

api-security

api-security

Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…

@zhaoxuya520@zhaoxuya520Install Skill
nemoclaw-user-guide

nemoclaw-user-guide

Find official NemoClaw documentation for installation, configuration, operation, or troubleshooting. Also handles requested docs…

nemoclaw11d23k
@nvidia@nvidiaInstall Skill

Questions about anti-debugging-techniques.

Which coding agents can use anti-debugging-techniques?
anti-debugging-techniques installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.