{"id":29538788,"url":"https://github.com/haxo-games/antidebug","last_synced_at":"2025-07-17T05:16:13.531Z","repository":{"id":303972093,"uuid":"1017329580","full_name":"haxo-games/AntiDebug","owner":"haxo-games","description":"Windows x86_64 anti-debugging sandbox (Work in progress)","archived":false,"fork":false,"pushed_at":"2025-07-10T13:37:30.000Z","size":6361,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-10T19:43:25.791Z","etag":null,"topics":["anti-debugging","cpp","malware-analysis","reverse-engineering","security","terminal","windows","x86-64"],"latest_commit_sha":null,"homepage":"https://haxo.games","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/haxo-games.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-10T11:18:26.000Z","updated_at":"2025-07-10T18:59:13.000Z","dependencies_parsed_at":"2025-07-10T19:53:30.046Z","dependency_job_id":null,"html_url":"https://github.com/haxo-games/AntiDebug","commit_stats":null,"previous_names":["haxo-games/antidebug"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/haxo-games/AntiDebug","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxo-games%2FAntiDebug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxo-games%2FAntiDebug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxo-games%2FAntiDebug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxo-games%2FAntiDebug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/haxo-games","download_url":"https://codeload.github.com/haxo-games/AntiDebug/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haxo-games%2FAntiDebug/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265567476,"owners_count":23789489,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anti-debugging","cpp","malware-analysis","reverse-engineering","security","terminal","windows","x86-64"],"created_at":"2025-07-17T05:15:41.352Z","updated_at":"2025-07-17T05:16:13.523Z","avatar_url":"https://github.com/haxo-games.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AntiDebug\n\n## What is this?\n\nA simple terminal interface tool to test Windows x86_64 anti-debugging techniques. Like many of our public projects this was made because we needed it to better explain\nsome of [our courses](https://haxo.games/courses).\n\n## Build\n\nAll this requires is Visual Studio 2022 (minimum) and the \"Desktop Development with C++\" package installed. The only dependencies this project uses are the Windows API \nand [FTXUI](https://github.com/ArthurSonzogni/FTXUI). FTXUI is directly included within the `dependencies/` folder. I'm aware this is bad practice, but I want to keep\nthe build environment as simplistic and similar to what is used throughout the course as possible for beginners.\n\n## Usage\n\nSimply run the executable and attach your debugger to the process. The console is conveniently titled \"AntiDebug\" on launch for you to easily find it. You can toggle\ndetections by navigating to them using your up and down arrow keys and pressing `ENTER` or `SPACE`. You can terminate the program with `Q`. Dections checks run continuously\nwhen enabled so just experiment and see what detects you, good luck!\n\n![Screenshot of AntiDebug running.](repo/preview.png)\n\n### Adding detections\n\nIf you'd like to add detections you first need to create the callback for said detection. To do so head into `antidebug.h`, make its definition with the following format:\n`void callbackMyDetectionName(AntiDebugOption\u0026 option);`, then head into `antidebug.cpp` and create its declaration like so:\n```c++\nvoid AntiDebug::callbackMyDetectionName(AntiDebugOption\u0026 option)\n{\n\t// Example detection\n\toption.detected = IsDebuggerPresent();\n}\n```\nSetting `option.detected` to true or false will instantly update the UI once the detection is fully integrated. You don't need to handle anything else than setting this\nvalue as you wish here. Disable logic and UI events are already handled in the `main` function.\n\u003cbr /\u003e\nNow to integrate the detection, locate `options` inside of the `antidebug.h` and add a new member in its initializer list like so:\n```c++\nAntiDebug::AntiDebugOptions anti_debug_options\n{\n\tADD_ANTI_DEBUG_OPTION(\"IsDebuggerPresent\", true, callbackIsDebuggerPresent),\n\tADD_ANTI_DEBUG_OPTION(\"MyDetectionName\", true, callbackMyDetectionName), // \u003c- Example integration\n};\n```\nThe first argument is the title to be displayed in the UI, the second sets if the detection should be enabled or not by default and the third is your callback.\n\u003cbr /\u003e\nThe last step will be to update the length of the `std::array` type alias for options in `antidebug.h`.\n\n## Documentation\n\nIn this section I will do my best to document the different anti-debugging techniques used, and maybe add extra details like how they can be avoided etc. For any further\ninformation please join [our Discord server](https://discord.gg/f6AbaCATMg).\n\n### `IsDebuggerPresent`\n\n`IsDebuggerPresent` is a Windows API function that simply accesses the `BeingDebugged` boolean from the thread environment block (TEB) of the current process. This value\nis true when the process is being debugged. This can be bypassed by simply setting `BeingDebugged` to 0. Patching `IsDebuggerPresent` may seem idiotic since anyone with a\nminimum of common sense would not invoke it directly, and yet most programs out there do.\n\n### `BeingDebugged`\n\nThis technique directly reads the `BeingDebugged` member of the process environment block (PEB) for the current process. If true, it is being debugged. Can be bypassed by\nsimply setting the value to 0.\n\n### `CheckRemoteDebuggerPresent`\n\n`CheckRemoteDebuggerPresent` is a Windows API function which which calls `NtQueryInformationProcess` for the `ProcessDebugPort` value under the hood. If this value is 0\nno debugger is attached, otherwise it sets the pointer to the boolean it was passed to true. This can be bypassed by hooking `NtQueryInformationProcess` or the function\nitself. `ProcessDebugPort` being in the `EPROCESS` structure it is immune to usermode shenanigans.\n\n### `NtQueryInformationProcess`\n\n`NtQueryInformationProcess` can be used to get `ProcessDebugPort` which can indicate if a debugger is present. It can also query a few values in an undocumented way such\nas the heap flags (`ProcessDebugFlags`) and the debug object handle (`ProcessDebugHandle`).\n\n### `FindWindowByTitle`\n\nSearches for debugging tools by enumerating windows and checking their titles. It searches for substrings in window titles such as \"Cheat Engine\" or \"Process Hacker\". \nThe substring matching provides flexibility to detect multiple versions of tools even when version numbers are appended to titles. This can be bypassed by hiding debugger \nwindows, changing window titles and hooking `FindWindowExA` functions.\n\n### `FindWindowByClass`\n\nSearches for debugging tools by enumerating windows and checking their classes. It uses `FindWindowA` from Windows API to detect specific window classes like \"OLLYDBG\" and \"WinDbgFrameClass\", \nThis can be bypassed by hiding debugger windows, changing window classes and hooking `FindWindowA`/`FindWindowExA` functions.\n\n### `GetThreadContext`\n\n`GetThreadContext` is a Windows API function that retrieves the current thread context, including hardware debug registers (Dr0, Dr1, Dr2, Dr3). When hardware breakpoints are set by debuggers, the corresponding debug register contains the breakpoint address. This technique checks if any of these registers contain non-zero values, indicating active hardware breakpoints. Hardware breakpoints are preferred by advanced debuggers since they don't modify process memory. This can be bypassed by clearing debug registers before detection, hooking `GetThreadContext` to return clean registers.\n\n### `NtQuerySystemInformation`\n\n`NtQuerySystemInformation` can be used to get `DebuggerInformation`. It's an undocumented structured made up of three booleans:\n```c++\ntypedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX \n{\n\tBOOLEAN DebuggerAllowed;\n\tBOOLEAN DebuggerEnabled;\n\tBOOLEAN DebuggerPresent;\n} SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX, * PSYSTEM_KERNEL_DEBUGGER_INFORMATION_EX;\n```\n`DebuggerAllowed` is true when a kernel debugger is allowed on the system. This will usually become true when the system gets a debugger attached to it. `KernelDebuggerEnabled` will\nbe true if the kernel was initialized with debugging enabled. `DebuggerPresent` is true when there currently is a debugger attached to the system.\n\n### `CloseHandle`\n\nWhen closing an invalid handle an `EXCEPTION_INVALID_HANDLE (0xC0000008)` will be raised if a debugger is attached. This can then be cought by an `__except` block once the debugger passes\ncontrol back to the procediss. If no debugger is present no exception is thrown. This detection is disabled by default because it causes an exception.\n\n### `DbgPrint`\n\nThis method will raise the exception `DBG_PRINTEXCEPTION_C (0x40010006)`. If it is handled by the program itself then no debugger is attached. Otherwise one obviously is. It is usually is raised\nby functions like `DbgPrint`.\n\n### `NtGlobalFlag`\n\n`NtGlobalFlag` is a member of the PEB which, when a debugger is attached, has three bit flags set to 1 notably: `0x10: EAP_ENABLE_TAIL_CHECK`, `0x20: HEAP_ENABLE_FREE_CHECK` and `0x40: HEAP_VALIDATE_PARAMETERS`. \nBypassing is as simple setting it to any value that does not match any of those flags (0 will work great). Also it seems these flags are only set when a program is launched with a debugger. When it is attached \nafter startup they aren't.\n\n## Contributing\n\nThis project is free and open source and will remain so forever. You are welcome to contribute. Simply make a pull request for whatever it is you would like to add, but\nthere are a few things you need to keep in mind:\n1. C++17 only for now.\n2. snake_case for variable names, PascalCase for namespaces and structures and camelCase for methods and function names (there might be more specefics so please just\nbase your style on the already existing code).\n3. Make an issue first, and specify your intent to address said issue.\n4. When making a branch give it a meaningful name like `feature/name_of_feature` for example.\n\n## Special thanks\n\nThank you to all who contributed to the project already and thank you to [vergiliusproject.com](https://www.vergiliusproject.com/) for documenting undocumented windows structures\nand [anti-debug.checkpoint.com](https://anti-debug.checkpoint.com/) for documenting many anti-debugging tricks.\n\n## License\n\nThis project is licensed under the MIT License with some specifications - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaxo-games%2Fantidebug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhaxo-games%2Fantidebug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaxo-games%2Fantidebug/lists"}