A small, cross-platform anti-debugging library for software protection.
Detect and react to debuggers in your process — with one line of code.
Replace
OWNERin the CI badge above with your GitHub org/user once you push.
antidbg runs a layered set of independent checks — documented APIs, direct
PEB reads, NtQueryInformationProcess, hardware-breakpoint registers, and
timing anomalies — and combines them into a single result. It also ships a
background guard that re-checks on an interval, so a debugger that attaches
after startup still trips it.
No dependencies. No build system lock-in. Drop it in and go.
- One-line detection —
if (adbg_detected()) { ... } - Continuous guard — a background thread that fires your callback the moment a debugger appears
- Spots RE tools on the host — IDA, Ghidra, Binary Ninja, x64dbg, Cutter, dnSpy, Process Hacker & more, even before they attach (how)
- 10+ techniques across Windows, Linux, and macOS (details)
- Zero dependencies — just the C standard library + OS APIs
- Tiny & portable — C99, static or shared, ~600 lines
- Python binding included via
ctypes
#include <antidbg/antidbg.h>
int main(void) {
if (adbg_detected()) {
// A debugger is attached — react however you like.
return 1;
}
// ... your protected code ...
}Continuous protection with a background guard:
#include <antidbg/antidbg.h>
static void on_debugger(adbg_flags flags, void *user) {
// Called from the guard thread. Wipe secrets, then bail.
_Exit(1);
}
int main(void) {
adbg_guard_config cfg = adbg_guard_default();
cfg.on_detected = on_debugger;
adbg_guard_start(&cfg); // now protected for the life of the process
// ... your protected code ...
}./build.sh # Linux / macOSbuild.bat REM Windows (needs CMake + a C toolchain)cmake -B build
cmake --build build
ctest --test-dir build --output-on-failureadd_subdirectory(antidbg)
target_link_libraries(your_app PRIVATE antidbg::antidbg)cc -Iantidbg/include your_app.c \
antidbg/src/antidbg.c antidbg/src/antidbg_*.c -o your_appcmake -B build -DANTIDBG_SHARED=ON && cmake --build build
python bindings/python/antidbg.py # prints "clean" or "detected"import antidbg
if antidbg.detected():
print("running under a debugger:", antidbg.flags_to_string(antidbg.scan()))| Function | Description |
|---|---|
adbg_flags adbg_scan(void) |
Run every check once; returns a bit mask of what fired. |
int adbg_detected(void) |
1 if anything was detected, else 0. |
adbg_flags_to_string(flags, buf, size) |
Human-readable names for set flags. |
adbg_guard_default() |
A ready-to-tweak guard config. |
adbg_guard_start(&cfg) |
Start the background guard thread. |
adbg_guard_stop() |
Stop the guard (blocks until it exits). |
adbg_guard_running() |
1 if the guard is active. |
Full header: include/antidbg/antidbg.h.
Choosing techniques for the guard. By default the guard runs everything.
The host-wide tool scan (ADBG_ANALYSIS_TOOL) can fire on a developer's own
machine, so to run every check except that one:
adbg_guard_config cfg = adbg_guard_default();
cfg.on_detected = on_debugger;
cfg.techniques = ~ADBG_ANALYSIS_TOOL; // all bits except the tool scan
adbg_guard_start(&cfg);See docs/TECHNIQUES.md for the full table of techniques per platform and how each can be bypassed.
Anti-debugging is deterrence, not DRM. It raises the cost of reversing or
tampering with your software; it does not make either impossible. A determined
analyst with a kernel debugger or a patched loader can defeat any user-mode
check. Use antidbg as one layer in a defense-in-depth strategy — alongside
integrity checks, obfuscation, and server-side validation — not as the only lock
on the door.
Intended for protecting software you own or are authorized to protect.
antidbg/
├── include/antidbg/antidbg.h # public API (start here)
├── src/ # core + per-platform backends
├── examples/ # basic.c, protect.c
├── tests/ # dependency-free self-tests
├── bindings/python/ # ctypes wrapper
└── docs/TECHNIQUES.md # technique reference
MIT — see LICENSE.