
Anti Debugging Techniques
- 2.3k installs
- 1.5k repo stars
- Updated June 16, 2026
- yaklang/hack-skills
anti-debugging-techniques is an agent skill that Anti-debugging detection and bypass playbook. Use when reversing protected binaries that detect debuggers via ptrace, PEB flags, timing checks, or signal/exception handle.
About
The anti-debugging-techniques skill. 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. 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. LINUX ANTI-DEBUG TECHNIQUES ### 1.1 ptrace(PTRACE_TRACEME) The classic self-attach: a process calls . If a debugger is already attached, the call fails (returns -1). **Bypass**: Set hardware breakpoint after second , modify to pass the comparison. Or use Frida to replace the timing function. The workflow follows the source SKILL.md contract with progressive reference loading, clear trigger phrases, and practical steps developers can apply directly in agent sessions.
- [code-obfuscation-deobfuscation](../code-obfuscation-deobfuscation/SKILL.md) when the binary also uses control flow flat
- [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 en
- Complete cross-reference matrix of technique × OS × detection method × bypass method
- Per-technique reliability ratings and false-positive notes
Anti Debugging Techniques by the numbers
- 2,282 all-time installs (skills.sh)
- +141 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #231 of 2,203 Security skills by installs in the Skillselion catalog
- Security screen: CRITICAL risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
anti-debugging-techniques capabilities & compatibility
- Capabilities
- [code obfuscation deobfuscation](../code obfusca · [vm and bytecode reverse](../vm and bytecode rev · [symbolic execution tools](../symbolic execution · complete cross reference matrix of technique × o · per technique reliability ratings and false posi
- Use cases
- security audit · testing · debugging
What anti-debugging-techniques says it does
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.
npx skills add https://github.com/yaklang/hack-skills --skill anti-debugging-techniquesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.3k |
|---|---|
| repo stars | ★ 1.5k |
| Security audit | 1 / 3 scanners passed |
| Last updated | June 16, 2026 |
| Repository | yaklang/hack-skills ↗ |
How do I apply anti-debugging-techniques correctly using the SKILL.md workflows and reference files?
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.
Who is it for?
Developers and software engineers working with anti-debugging-techniques patterns from the skill documentation.
Skip if: Skip when cached docs are empty, boilerplate-only, or outside the skill documented scope.
When should I use this skill?
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.
What you get
Grounded anti-debugging-techniques guidance with highlights, triggers, and evidence quotes from SKILL.md.
- technique selection matrix
- bypass tool recommendations
- reliability assessments
By the numbers
- Organizes techniques in a multi-column matrix across OS, detection, bypass, and reliability
- Linux section includes numbered technique rows starting at L1 for ptrace(PTRACE_TRACEME)
Files
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 when the binary also uses control flow flattening, VM protection, or string encryption
- vm-and-bytecode-reverse when the anti-debug sits inside a custom VM dispatcher
- symbolic-execution-tools when you want to symbolically skip anti-debug checks entirely
Advanced Reference
Also load 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 attachedBypass: 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_detectedBypass: 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 signalWhen 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_detectedBypass: 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 kernel debug service interrupt. Without a debugger, it raises STATUS_BREAKPOINT; with a debugger, behavior differs (byte skipping).
xor eax, eax
int 2dh
nop ; debugger may skip this byte
; ... divergent execution path ...Bypass: Handle in VEH or patch the interrupt instruction.
2.6 TLS Callbacks
TLS callbacks execute before main() / WinMain(). Anti-debug checks placed here run before the debugger's initial break.
Bypass: In x64dbg, set "Break on TLS Callbacks" option. In WinDbg, use sxe ld to break on module load.
2.7 NtSetInformationThread(ThreadHideFromDebugger)
NtSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0);After this call, the thread becomes invisible to the debugger — breakpoints and single-stepping stop working silently.
Bypass: Hook NtSetInformationThread to NOP when ThreadInfoClass == 0x11.
2.8 VEH-Based Detection
Registers a Vectored Exception Handler that checks EXCEPTION_RECORD for debugger-specific behavior (single-step flag, guard page violations with debugger semantics).
Bypass: Understand the VEH logic and ensure the exception chain behaves identically to non-debugged execution.
---
3. ADVANCED MULTI-LAYER TECHNIQUES
3.1 Self-Debugging (fork + ptrace)
The process forks a child that attaches to the parent via ptrace. If an external debugger is already attached, the child's ptrace fails.
pid_t child = fork();
if (child == 0) {
if (ptrace(PTRACE_ATTACH, getppid(), 0, 0) == -1)
kill(getppid(), SIGKILL);
else
ptrace(PTRACE_DETACH, getppid(), 0, 0);
_exit(0);
}
wait(NULL);Bypass: Patch the fork() return or kill/detach the watchdog child.
3.2 Multi-Process Debugging Detection
Parent and child cooperatively check each other's debug state, creating a mutual-watch pattern.
Bypass: Attach to both processes (GDB follow-fork-mode, or two debugger instances).
3.3 Timing-Based with Multiple Checkpoints
Distributes timing checks across multiple functions, comparing cumulative drift. Single patches fail because the total still exceeds threshold.
Bypass: Frida Interceptor.replace all timing sources (rdtsc, clock_gettime, QueryPerformanceCounter) to return controlled values.
3.4 Nanomite / INT3 Patching
Original conditional jumps are replaced with INT3 (0xCC). A parent debugger process handles each INT3, evaluates the condition, and sets the child's EIP accordingly.
Bypass: Reconstruct the original jump table by tracing all INT3 handlers, then patch the binary.
---
4. COUNTERMEASURE TOOLS
| Tool | Platform | Capability |
|---|---|---|
| ScyllaHide | Windows (x64dbg/IDA/OllyDbg) | Auto-patches PEB, hooks NtQuery*, hides threads, fixes timing |
| TitanHide | Windows (kernel driver) | Kernel-level hiding for all user-mode checks |
| Frida | Cross-platform | Script-based hooking of any function, timing spoofing |
| LD_PRELOAD shims | Linux | Replace ptrace, getenv, fopen at load time |
| GDB scripts | Linux | catch syscall, conditional BP, register fixup |
| Qiling | Cross-platform | Full-system emulation, bypass all hardware checks |
---
5. SYSTEMATIC BYPASS METHODOLOGY
Step 1: Static analysis — identify anti-debug calls
└─ Search for: ptrace, IsDebuggerPresent, NtQuery, rdtsc,
GetTickCount, SIGTRAP, INT 2D, TLS directory entries
Step 2: Classify each check
├─ API-based → hook or patch the call
├─ Flag-based → patch PEB/proc fields
├─ Timing-based → spoof time source
├─ Exception-based → forward/handle exception correctly
└─ Multi-process → handle both processes
Step 3: Apply bypass (order matters)
1. Load ScyllaHide / set LD_PRELOAD (covers 80% of checks)
2. Handle TLS callbacks (break before main)
3. Patch remaining custom checks (Frida or binary patch)
4. Verify: run with breakpoints, confirm no premature exit
Step 4: Validate bypass completeness
└─ Set BP on ExitProcess/exit/_exit — if hit unexpectedly,
a check was missed → trace back from exit call---
6. DECISION TREE
Binary exits/crashes under debugger?
│
├─ Crashes immediately before main?
│ └─ TLS callback anti-debug
│ └─ Enable TLS callback breaking in debugger
│
├─ Crashes at startup?
│ ├─ Linux: check for ptrace(TRACEME)
│ │ └─ LD_PRELOAD hook or NOP patch
│ └─ Windows: check IsDebuggerPresent / PEB
│ └─ ScyllaHide or manual PEB patch
│
├─ Crashes after some execution?
│ ├─ Consistent crash point → API-based check
│ │ ├─ NtQueryInformationProcess → hook return values
│ │ ├─ /proc/self/status → filter TracerPid
│ │ └─ Hardware BP detection → hook GetThreadContext
│ │
│ ├─ Variable crash point → timing-based check
│ │ └─ Hook rdtsc / QueryPerformanceCounter
│ │
│ └─ Crash on breakpoint hit → exception-based check
│ ├─ INT 2D / INT 3 trick → handle in VEH
│ └─ SIGTRAP handler → GDB: handle SIGTRAP pass
│
├─ Debugger loses control silently?
│ └─ ThreadHideFromDebugger
│ └─ Hook NtSetInformationThread
│
├─ Child process detects and kills parent?
│ └─ Self-debugging (fork+ptrace)
│ └─ Patch fork() or handle both processes
│
└─ All basic bypasses applied but still detected?
└─ Multi-layer / custom checks
├─ Use Frida for comprehensive API hooking
├─ Full emulation with Qiling
└─ Trace all calls to exit/abort to find remaining checks---
7. CTF & REAL-WORLD PATTERNS
Common CTF Anti-Debug Patterns
| Pattern | Frequency | Quick Bypass |
|---|---|---|
Single ptrace(TRACEME) | Very common | LD_PRELOAD one-liner |
IsDebuggerPresent + NtGlobalFlag | Common | ScyllaHide |
| rdtsc timing in loop | Moderate | Patch comparison threshold |
| signal(SIGTRAP) + raise | Moderate | GDB signal forwarding |
| fork + ptrace watchdog | Rare but tricky | Kill child or patch fork |
| Nanomite INT3 replacement | Rare (advanced) | Reconstruct jump table |
Real-World Protections
| Protector | Primary Anti-Debug | Recommended Tool |
|---|---|---|
| VMProtect | PEB + timing + driver-level | TitanHide + ScyllaHide |
| Themida | Multi-layer PEB + SEH + timing | ScyllaHide + manual patches |
| Enigma Protector | IsDebuggerPresent + CRC checks | x64dbg + ScyllaHide |
| UPX (custom) | Usually none (just packing) | Standard unpack |
| Custom (malware) | Varies widely | Frida + Qiling for analysis |
---
8. QUICK REFERENCE — BYPASS CHEAT SHEET
Linux One-Liners
# LD_PRELOAD anti-ptrace
echo 'long ptrace(int r, ...) { return 0; }' > /tmp/ap.c
gcc -shared -o /tmp/ap.so /tmp/ap.c
LD_PRELOAD=/tmp/ap.so ./target
# GDB: catch and bypass ptrace
(gdb) catch syscall ptrace
(gdb) commands
> set $rax = 0
> continue
> endFrida Anti-Debug Bypass (Cross-Platform)
// Hook IsDebuggerPresent (Windows)
Interceptor.replace(
Module.getExportByName('kernel32.dll', 'IsDebuggerPresent'),
new NativeCallback(() => 0, 'int', [])
);
// Hook ptrace (Linux)
Interceptor.replace(
Module.getExportByName(null, 'ptrace'),
new NativeCallback(() => 0, 'long', ['int', 'int', 'pointer', 'pointer'])
);
// Timing spoof
Interceptor.attach(Module.getExportByName(null, 'clock_gettime'), {
onLeave(retval) {
// manipulate timespec to hide debugger delay
}
});x64dbg ScyllaHide Quick Setup
1. Plugins → ScyllaHide → Options 2. Check: PEB BeingDebugged, NtGlobalFlag, HeapFlags 3. Check: NtQueryInformationProcess (all classes) 4. Check: NtSetInformationThread (HideFromDebugger) 5. Check: GetTickCount, QueryPerformanceCounter 6. Apply → restart debugging session
Anti-Debug Technique × OS × Detection × Bypass — Comprehensive Matrix
AI LOAD INSTRUCTION: Load this when you need the full cross-reference of anti-debugging techniques, their OS applicability, detection methods, bypass tools, reliability ratings, and false-positive notes. Assumes the main SKILL.md is already loaded for conceptual understanding.
---
1. LINUX ANTI-DEBUG MATRIX
| # | Technique | Detection Method | Reliability | Bypass Method | Bypass Tool | False Positives |
|---|---|---|---|---|---|---|
| L1 | ptrace(PTRACE_TRACEME) | Self-attach; fails if already traced | High | LD_PRELOAD shim, NOP patch, GDB catch syscall | GDB, gcc | None — definitive |
| L2 | /proc/self/status TracerPid | Read TracerPid field; non-zero = traced | High | Hook fopen/fread, FUSE mount, patch string | Frida, LD_PRELOAD | Container environments may show artifacts |
| L3 | /proc/self/maps scanning | Search for debugger/instrumentation libraries | Medium | Filter maps output via hook, rename agent libs | Frida (rename gadget.so) | Security tools may trigger |
| L4 | rdtsc timing | Measure cycle count delta between two points | Medium | Fix registers at BP, hook timing source | GDB scripts, Frida | High CPU load can cause false positives |
| L5 | clock_gettime timing | Similar to rdtsc but via syscall | Medium | Hook clock_gettime, return controlled values | Frida, LD_PRELOAD | System load variation |
| L6 | SIGTRAP handler | Install handler, raise SIGTRAP; debugger swallows it | High | GDB: handle SIGTRAP nostop pass | GDB | None |
| L7 | SIGSTOP/SIGCONT self-send | Send SIGSTOP to self, measure if debugger intervenes | Low | Forward signals properly | GDB signal handling | Rare |
| L8 | Fork + ptrace watchdog | Child attaches to parent; fails if debugger present | High | Kill child, patch fork, dual-attach | GDB (follow-fork-mode) | None |
| L9 | LD_PRELOAD env check | getenv("LD_PRELOAD") | Low | Unset env var, hook getenv | Shell, Frida | Legitimate LD_PRELOAD usage |
| L10 | Parent PID check | getppid() — expect init/shell, not debugger | Low | Run from shell normally, hook getppid | Frida | Terminal multiplexers |
| L11 | /proc/self/exe readlink | Check if binary path matches expected | Low | Symlink or hook readlink | Shell | Custom install paths |
| L12 | Breakpoint scanning (0xCC) | Scan .text for INT3 bytes | Medium | Use hardware breakpoints only | x86 HW BP (DR0-DR3) | Legitimate 0xCC in data |
| L13 | prctl(PR_SET_DUMPABLE, 0) | Prevent ptrace attach after start | Medium | Hook prctl, keep dumpable | LD_PRELOAD, Frida | None |
| L14 | personality(ADDR_NO_RANDOMIZE) | Detect if ASLR disabled (common debugger setting) | Low | Keep ASLR enabled while debugging | GDB (don't disable ASLR) | Manual ASLR disable |
---
2. WINDOWS ANTI-DEBUG MATRIX
| # | Technique | Detection Method | Reliability | Bypass Method | Bypass Tool | False Positives |
|---|---|---|---|---|---|---|
| W1 | IsDebuggerPresent | Reads PEB.BeingDebugged | High | Patch PEB byte, hook API | ScyllaHide, x64dbg | None |
| W2 | CheckRemoteDebuggerPresent | Calls NtQueryInformationProcess(DebugPort) | High | Hook underlying NtQIP | ScyllaHide | None |
| W3 | PEB.BeingDebugged | Direct PEB read (no API call) | High | Zero the byte at PEB+0x02 | ScyllaHide, manual patch | None |
| W4 | PEB.NtGlobalFlag (0x70) | Check for FLG_HEAP_ENABLE_* flags | High | Zero PEB+0xBC | ScyllaHide | None |
| W5 | Heap flags | ProcessHeap.Flags / ForceFlags | High | Patch heap header | ScyllaHide | None |
| W6 | NtQueryInformationProcess DebugPort | InfoClass 0x07 → non-zero if debugged | High | Hook NtQIP, return 0 | ScyllaHide, Frida | None |
| W7 | NtQueryInformationProcess DebugObjectHandle | InfoClass 0x1E → valid handle if debugged | High | Hook NtQIP, return error | ScyllaHide | None |
| W8 | NtQueryInformationProcess DebugFlags | InfoClass 0x1F → 0 if debugged (inverted!) | High | Hook NtQIP, return 1 | ScyllaHide | None |
| W9 | OutputDebugString timing | Measure time for ODS call (faster with debugger) | Medium | Hook ODS or fix timing | Frida | System load |
| W10 | INT 2D | Kernel debug interrupt; byte-skip behavior differs | High | Handle in VEH, NOP patch | ScyllaHide, manual | None |
| W11 | INT 3 (0xCC) | Breakpoint instruction behavior | Medium | Single-step past, VEH | Debugger built-in | None |
| W12 | UD2 (#UD exception) | Invalid opcode exception handling differs | Medium | Handle in VEH | Manual | None |
| W13 | TLS callbacks | Code runs before entry point | High | Break on TLS callback | x64dbg option, WinDbg | None |
| W14 | NtSetInformationThread HideFromDebugger | Thread becomes invisible to debugger | High | Hook NtSIT, NOP the call | ScyllaHide | None |
| W15 | DR register check | GetThreadContext reads DR0-DR3 | High | Hook GTC, zero DRx | ScyllaHide | None |
| W16 | NtQuerySystemInformation SystemKernelDebuggerInformation | Detects kernel debugger | High (kernel) | TitanHide (kernel driver) | TitanHide | None |
| W17 | VEH chain inspection | Walk VEH list for debugger-installed handlers | Low | Don't install VEH from debugger | Manual | Security software VEHs |
| W18 | CloseHandle(invalid) | With debugger: raises exception; without: returns error | Medium | Handle exception in VEH | ScyllaHide | None |
| W19 | NtClose(invalid) | Same as CloseHandle trick at NT level | Medium | Hook NtClose | ScyllaHide | None |
| W20 | SEH-based detection | Install SEH, trigger exception, check handler invocation | Medium | Ensure correct SEH dispatch | Debugger settings | None |
| W21 | QueryPerformanceCounter timing | Measure ticks between two points | Medium | Hook QPC, spoof delta | ScyllaHide, Frida | System load |
| W22 | GetTickCount / GetTickCount64 timing | Millisecond-level timing check | Medium | Hook and spoof | ScyllaHide | System load |
| W23 | RDTSC instruction | Direct CPU timestamp counter | Medium | Patch comparison or hook via VEH on #UD | Frida (replace block) | CPU frequency changes |
| W24 | Parent process check | NtQueryInformationProcess → check parent is explorer.exe | Low | Spoof parent PID or hook | Frida | Non-standard launchers |
| W25 | Window class enumeration | FindWindow("OLLYDBG"), FindWindow("x64dbg") | Low | Rename debugger window class | Debugger plugin | None |
| W26 | Process enumeration | Enumerate processes for known debugger names | Low | Rename debugger executable | Shell | None |
| W27 | CRC / integrity check | Hash .text section, compare against stored value | Medium | Patch stored hash or hook CRC function | Manual, Frida | Legitimate code updates |
| W28 | BlockInput(TRUE) | Lock keyboard/mouse during sensitive operations | Low | Hook BlockInput | ScyllaHide | None |
---
3. TOOL COMPATIBILITY MATRIX
| Technique | GDB | x64dbg + ScyllaHide | WinDbg | IDA Remote | Frida | Qiling |
|---|---|---|---|---|---|---|
| ptrace self-attach | catch syscall | N/A | N/A | N/A | Hook | Emulate |
| /proc/self/status | Manual hook | N/A | N/A | N/A | Hook fopen | Emulate |
| PEB.BeingDebugged | N/A | Auto-patch | Manual | Plugin | Hook | Emulate |
| NtGlobalFlag | N/A | Auto-patch | Manual | Plugin | Hook | Emulate |
| NtQueryInformationProcess | N/A | Auto-hook | Manual | Plugin | Hook | Emulate |
| IsDebuggerPresent | N/A | Auto-hook | eb kernel32!IsDebuggerPresent | Plugin | Hook | Emulate |
| rdtsc timing | Register fixup | Spoof QPC | Manual | N/A | Replace block | Emulate |
| INT 2D / INT 3 | Handle signal | VEH/auto | Handle exception | N/A | Replace insn | Emulate |
| TLS callback | starti | Break on TLS | sxe ld | Break on entry | Early inject | Emulate |
| ThreadHideFromDebugger | N/A | Auto-NOP | Manual | Plugin | Hook NtSIT | Emulate |
| DR register check | N/A | Auto-zero DRx | Manual | N/A | Hook GTC | Emulate |
| fork+ptrace watchdog | follow-fork-mode | N/A | N/A | N/A | Hook fork | Emulate both |
| SIGTRAP handler | handle pass | N/A | N/A | N/A | Hook signal | Emulate |
| Breakpoint scan (0xCC) | Use HW BP | Use HW BP | Use HW BP | N/A | No BP needed | Emulate |
---
4. BYPASS PRIORITY CHECKLIST
Apply bypasses in this order for maximum coverage with minimum effort:
Phase 1 — Automated tools (covers ~80%)
├─ Windows: Load ScyllaHide with all options checked
├─ Linux: Set LD_PRELOAD with ptrace + timing shims
└─ Verify: program runs past initial checks
Phase 2 — TLS / early execution (covers +10%)
├─ Break on TLS callbacks or _init functions
└─ Patch any pre-main checks found
Phase 3 — Custom checks (covers +8%)
├─ Trace exit/abort calls → backtrack to find check
├─ Frida hook remaining detection functions
└─ Patch binary for persistent bypass
Phase 4 — Multi-process / kernel (covers +2%)
├─ Handle fork+ptrace with dual-process debugging
├─ TitanHide for kernel-level debugger detection
└─ Qiling full emulation for heavily protected targets---
5. DETECTION RELIABILITY RATING GUIDE
| Rating | Meaning | Example |
|---|---|---|
| High | Definitive detection, no false positives | PEB.BeingDebugged, ptrace self-attach |
| Medium | Reliable but environment-sensitive | Timing checks (CPU load affects), breakpoint scanning |
| Low | Easily spoofed or many false positives | Process name enumeration, window class search, env var check |
Related skills
How it compares
Pick anti-debugging-techniques when you need a structured technique-by-OS bypass matrix, not a general vulnerability scanner or web pentest playbook.
FAQ
Who is anti-debugging-techniques for?
Developers and software engineers working with anti-debugging-techniques patterns from the skill documentation.
When should I use 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.
Is anti-debugging-techniques safe to install?
Review the Security Audits panel on this page before installing in production.