
Windows के लिए एक स्टील्थ, पूर्णतः syscalled C/C++ यूज़रलैंड एंटी-डीबगिंग लाइब्रेरी, जिसे सॉफ़्टवेयर को रिवर्स इंजीनियरिंग से बचाने के लिए डिज़ाइन किया गया है
antidbg Windows के लिए एक x64 user-mode anti-debugging लाइब्रेरी है, जिसे सॉफ़्टवेयर को डीबगिंग से बचाने के लिए डिज़ाइन किया गया है।
लाइब्रेरी को अपनी anti-debugging सुरक्षा के आधार के रूप में मानें, न कि अपनी एकमात्र रक्षा के रूप में।
लाइब्रेरी है:
खतरा मॉडल यह मानता है कि एक डीबगर इस सुरक्षा प्रणाली द्वारा संरक्षित सॉफ़्टवेयर को किसी भी विशेषाधिकार स्तर से इंटरसेप्ट कर सकता है, और विशेषाधिकार स्तर जितना ऊँचा होगा, पहचान उतनी ही कम प्रभावी होगी।
यह सॉफ़्टवेयर निम्नलिखित द्वारा तुच्छ CPL > 0 इंटरसेप्शन को बायपास करने के लिए सख्त किया गया है:
RAX में syscall spoofing को रोकना, अवैध instrumentation callbacks का पता लगाकर और/या उन्हें अधिलेखित करके।.text अनुभागों पर किसी भी प्रकार के inline patch का पता लगाना।VEH, SEH, LPTOP_LEVEL_EXCEPTION_FILTER) और software breakpoints का विश्लेषण करना।PAGE_GUARD redirection व्यवहार का परीक्षण करना।TLS callbacks के साथ प्रक्रिया entrypoint को डीबगर attachment से सुरक्षित करना, thread start address निरीक्षण करना।DbgBreakPoint और DbgUiRemoteBreakin, ताकि प्रक्रिया क्रैश हो या वापस लौटे।यदि किसी जाँच को करने का एकमात्र तरीका non-syscallable exported function का उपयोग करना है, तो संबंधित फ़ंक्शन को मैन्युअल रूप से reverse-engineer किया जाता है और सुरक्षा थ्रेड के module address space में चलाने के लिए पुनर्निर्मित किया जाता है। सभी user-mode मेमोरी संरचनाओं को APIs का उपयोग करने के बजाय सीधे memory introspection के साथ चलाया जाता है।
सुरक्षा routines जानबूझकर कुछ execution paths को user-mode hooks के विरुद्ध असुरक्षित छोड़ देती हैं, जो memory honeypots के रूप में कार्य करते हैं। इनका उपयोग state तुलना और हमलावरों को भ्रमित करने के लिए किया जाता है।
सुरक्षा routines pseudo-randomly चलती हैं। entropy को शुद्ध hardware-based ASLR, stack व्यवहार और थोड़े से गणित के साथ तय किया जाता है; kernel को कॉल किए बिना, user-mode APIs का उपयोग किए बिना, या hypervisors द्वारा सशर्त या बिना शर्त exiting निर्देश जारी किए बिना।
जब सुरक्षा उल्लंघन का पता चलता है, तो सुरक्षा प्रणाली STATUS_SXS_EARLY_DEACTIVATION के साथ INT 29h को invoke करके वर्तमान प्रक्रिया को क्रैश कर देती है, सभी exception handlers को बायपास करते हुए। कुछ मामलों में, यह वर्तमान प्रक्रिया को समाप्त करने के लिए kernel को एक APC भी कतारबद्ध करती है।
इस लाइब्रेरी के मुख्य entrypoint (abdg.c) में पाई जाती हैं, क्रम में समझाई गई हैं।
संक्षिप्त व्याख्याएँ; एक विशिष्ट पहचान यहाँ समझाए गए से अधिक अतिरिक्त/उप-जाँचें कर सकती है।
आप अन्य पहचान अवधारणाओं का अधिक स्रोत कोड antidebug\archived फ़ोल्डर में पा सकते हैं।
1. kernel32 के export function का उपयोग करके PEB के BeingDebugged फ़ील्ड को पढ़ता है।2. यह देखने के लिए export IsRemoteDebuggerPresent को कॉल करता है कि लक्ष्य प्रक्रिया अपने स्वयं के संदर्भ के बाहर से डीबग की जा रही है या नहीं।3. INT 2D software interrupt को निष्पादित करता है, यह जाँचते हुए कि क्या ऐसे निर्देश के बाद वाला बाइट छोड़ दिया जाता है और EXCEPTION_BREAKPOINT handler के माध्यम से रूट नहीं किया जाता है।4. breakpoint interrupt INT 3D को निष्पादित करता है, फिर देखता है कि exception को इंटरसेप्ट किया जाता है या सामान्य रूप से पारित किया जाता है।5. ICE/0xF1 को invoke करता है, EXCEPTION_SINGLE_STEP उठाता है और जाँचता है कि क्या डीबगर इस exception को RFlags रजिस्टरों में single step बिट सेट के साथ निर्देश निष्पादित करके उत्पन्न सामान्य exception मानेगा।उदाहरण:
#include "adbg.h"
int main() {
StartDebugProtection();
return 0;
}
उदाहरण:
#include "adbg.h"
int main() {
if (isProgramBeingDebugged()) {
printf("Debugger detected.\n");
}
else {
printf("No debugger was detected.\n");
}
return 0;
}
test runner executable बनाने के लिए, -DBUILD_EXAMPLE=ON सक्षम करें। यह example/main.c को संकलित करता है और इसे antidebug के विरुद्ध लिंक करता है, बिना core लाइब्रेरी को entry point से प्रदूषित किए।
.sln फ़ाइल खोलें)।antidebug_runner को startup project के रूप में सेट करें और Build पर क्लिक करें (या चलाने के लिए F5 दबाएँ)।प्रोजेक्ट रूट से:
cmake -B build -S . -DBUILD_EXAMPLE=ON
cmake --build build --config Release
executable यहाँ स्थित होगा:
build/Release/antidebug_runner.exebuild/antidebug_runner.exeDebug Builds पर नोट: Debug mode (
--config Debug) में संकलनcore/debug.cके माध्यम से console/debugger diagnostic logs सक्षम करता है। Release mode logging को पूरी तरह हटा देता है।
डिफ़ॉल्ट रूप से, CMake एक static library (antidebug.lib या libantidebug.a) उत्पन्न करता है। dynamic link library (DLL) बनाने के लिए, -DBUILD_SHARED_LIBS=ON पास करें।
cl.exe)Visual Studio generator का उपयोग करके:
# Static Library (.lib)
cmake -B build -S . -A x64 -DBUILD_SHARED_LIBS=OFF
cmake --build build --config Release
# Dynamic Library (.dll + import .lib)
cmake -B build -S . -A x64 -DBUILD_SHARED_LIBS=ON
cmake --build build --config Release
clang-cl के साथ Ninja का उपयोग करके:
# Ensure clang-cl is in your PATH or run from the VS x64 Native Tools Command Prompt
cmake -B build -S . -G Ninja -DCMAKE_C_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF
cmake --build build
अपना 64-bit LLVM-MinGW shell लॉन्च करें (x86_64-w64-mingw32-clang आपके PATH में) और Ninja का उपयोग करें:
# Static Library (.a)
cmake -B build -S . -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF
cmake --build build
# Shared Library (.dll)
cmake -B build -S . -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON
cmake --build build
संकलित लाइब्रेरी और headers को एक स्थानीय prefix में इंस्टॉल करने के लिए:
cmake --install build --prefix "C:/local/antidebug"
यह उत्पन्न करता है:
C:/local/antidebug/
├── bin/
│ └── antidebug.dll (if BUILD_SHARED_LIBS=ON)
├── lib/
│ └── antidebug.lib (or libantidebug.a)
└── include/
└── antidebug/
├── adbg.h
└── ...
इस प्रोजेक्ट के किसी भी दुर्भावनापूर्ण उपयोग के माध्यम से आपके द्वारा किए गए किसी भी नुकसान के लिए मैं ज़िम्मेदार या उत्तरदायी नहीं हूँ।
BUILD दस्तावेज़ का निर्माण AI के साथ किया गया था, किसी भी समस्या की रिपोर्ट करें।
License: MIT
6. TF फ़्लैग सेट करके और जाँचकर कि क्या डीबगर इसे RFLAGS से साफ़ करता है, stack-segment रजिस्टरों की जाँच करता है, क्योंकि सामान्यतः डीबगर प्रत्येक डीबगर event वितरित होने के बाद trap flag साफ़ कर देते हैं।7. prefix-आधारित instruction-flow edge case का उपयोग करता है और जाँचता है कि क्या 0xF3 0x64, जो PREFIX REP के रूप में disassemble होता है, 0xF1 skip को बाध्य करता है।8. trap flag सेट करने और pushfd mov dword ptr [esp], 0x100 popfd nop को invoke करने के बाद जाँचता है कि EXCEPTION_SINGLE_STEP handler में जाने के बजाय nop तक पहुँचा जाता है या नहीं।9. DBG_CONTROL_C और DBG_RIPEXCEPTION event उठाता है यह देखने के लिए कि exception को इंटरसेप्ट किया जाता है और SEH के माध्यम से रूट नहीं किया जाता है।10. NtQueryInformationProcess के साथ ProcessDebugObjectHandle के लिए query करके, attached debug object handle की जाँच करता है।11. NtQuerySystemInformation के साथ SystemKernelDebuggerInformation का उपयोग करके kernel debugger की उपस्थिति के लिए query करता है, और KdDebuggerEnabled फ़ील्ड के लिए सीधे KUSER_SHARED_DATA मेमोरी पेज को पढ़ता है। इसके अतिरिक्त, जाँचता है कि kernel timer ISRs asynchronously tick कर रहे हैं या नहीं।12. FLG_HEAP_ENABLE_TAIL_CHECK (0x10), FLG_HEAP_ENABLE_FREE_CHECK (0x20) और FLG_HEAP_VALIDATE_PARAMETERS (0x40) के मास्क के लिए NT global flag को पढ़ता है।13. यह अनुमान लगाने के लिए ProcessDebugFlags का निरीक्षण करता है कि डीबगिंग सक्षम है या दबा दी गई है।14. process handles को डुप्लिकेट करता है और जाँचता है कि क्या डीबगर handles को छूता है, handles को inherit करता है, या उन्हें फिर से खोलता/डुप्लिकेट करता है; क्या मैं एक संरक्षित duplicate handle बना सकता हूँ, फिर उसे दोबारा साफ़ तरीके से डुप्लिकेट कर सकता हूँ?15. डीबगर launchers या संदिग्ध वंशावली जैसे vsjitdebugger, x64dbg, या समान का पता लगाने के लिए parent-process श्रृंखला की जाँच करता है।16. exports का उपयोग किए बिना, सीधे base (__readgsqword(0x60)) से offset *(BYTE*)((uintptr_t)peb + 2 पर पढ़कर debug PEB फ़ील्ड की जाँच करता है।17. वर्तमान प्रक्रिया के लिए ProcessDebugPort को query करता है।18. thread debug रजिस्टरों (Dr0–Dr7) का निरीक्षण करके hardware breakpoints की जाँच करता है।19. honeypots रखकर और परिवर्तनों की निगरानी करके जाँचता है कि virtual memory डीबगरों द्वारा hit की गई थी या नहीं।20. process और window handles के साथ दो invalid-handle close परीक्षण करता है, देखता है कि ERROR_INVALID_WINDOW_HANDLE और EXCEPTION_INVALID_HANDLE इंटरसेप्ट नहीं किए जाते हैं।21. जाँचता है कि debug objects डीबगर द्वारा इंटरसेप्ट किए जाते हैं और handle stripping होती है या नहीं।22. एक प्रक्रिया को इस तरह खोलने का प्रयास करता है जो बताता है कि access डीबगरों द्वारा filtered या redirected किया जा रहा है या नहीं।23. जाँचता है कि HANDLE_FLAG_PROTECT_FROM_CLOSE के रूप में चिह्नित mutex handle को सीधे बंद किया जा सकता है या नहीं।24. SysDbgGetTriageDump के साथ NtSystemDebugControl को कॉल करता है और जाँचता है कि kernel debugger कॉल को ब्लॉक करता है या कॉल को spoof करता है लेकिन हमारे memory buffer को नहीं छूता है।25. जाँचता है कि हमारे स्वयं के stack की memory reads instrumented या intercepted की जा रही हैं या नहीं।26. जाँचता है कि प्रक्रिया डीबगर द्वारा बनाए गए non whitelisted job object के अंदर है या नहीं।27. memory-breakpoint शैली का access परीक्षण उपयोग करता है, सामान्यतः watchpoints सक्रिय होने पर page-guard या fault व्यवहार की अपेक्षा करता है।28. page-exception breakpoint परिदृश्य को ट्रिगर करता है और जाँचता है कि exception श्रृंखला सही ढंग से STATUS_GUARD_PAGE_VIOLATION वितरित करती है या नहीं।29. single-stepping, breakpoints, या dynamic binary instrumentation/JIT recompilation द्वारा पेश किए गए overhead का पता लगाने के लिए execution timing मापता है।30. डीबगर टूल्स से जुड़े windows/classes/titles की गणना करके डीबगर विंडो या UI artifacts की खोज करता है।31. जाँचता है कि डीबगर अपनी स्वयं की single-stepping करने के लिए DR7 में पहले से सेट LBR/BTF बिट्स को साफ़ करता है, जिसके परिणामस्वरूप एक खाली ExceptionInformation array बनती है, या यदि डीबगर LBR को सक्षम छोड़ने का निर्णय लेता है लेकिन फिर भी icebp द्वारा invoke किए गए EXCEPTION_SINGLE_STEP को इंटरसेप्ट करता है तो kernel-mode branch addresses का पता लगाया जाता है या नहीं।32. सीधे heap को चलाता है और 0xABABABAB और 0xFEEEFEEE magic मानों की जाँच करता है। प्रभावी रूप से 12 के समान लेकिन hookable Heap APIs का उपयोग करके।33. जाँचकर कि पहले साझा किया गया पेज डीबगर द्वारा छुआ गया था या नहीं, virtual memory में Copy-On-Write हुआ है या नहीं, यह जाँचता है।34. एक console event (CTRL_C_EVENT) भेजता है और जाँचता है कि डीबगर इसे इंटरसेप्ट करता है और इसकी delivery को हमारे control handler में बदलता है, या DBG_CONTROL_C उठाता है।35. जाँचता है कि प्रक्रिया injection प्रयासों के लिए बाहरी रूप से suspended है या नहीं; हमारी प्रक्रिया की ओर इशारा करने वाले NtResumeProcess के किसी भी बाहरी कॉल का पता लगाता है।36. विभिन्न SE_DEBUG_PRIVILEGE विशेषाधिकार स्तरों के साथ NtSetDebugFilterState को कॉल करता है और जाँचता है कि kernel debugger access को गलत तरीके से संभालता है या नहीं।37. device objects का विश्लेषण करता है, यह भी जाँचता है कि kernel debugger file read को इंटरसेप्ट करता है या नहीं।38. थ्रेड्स को kernel debugger और kernel दोनों के विरुद्ध ContextFlags संरचना को पढ़ने के लिए दौड़ाता है; जाँचता है कि DEBUG_REGISTERS stripped है/क्या Dr0 सेट नहीं था।39. एक virtual section का अत्यंत बड़ा view बनाकर और map करके कुछ डीबगरों को फ्रीज़ करता है; पता लगाता है कि NtMapViewOfSection के कॉल के साथ छेड़छाड़ की गई है या नहीं।40. अवास्तविक syscalls (emulators में सामान्य) की जाँच करता है।41. चार क्रमागत NOPs पर DR0 से DR3 तक चार hardware execution breakpoints सेट करता है और VEH के माध्यम से परिणामी EXCEPTION_SINGLE_STEP deliveries की गणना करता है।42. legacy Windows XP/2000 पर OutputDebugString side effects के माध्यम से और DBG_PRINTEXCEPTION_{C,WIDE_C} exceptions के माध्यम से जिन्हें डीबगर इंटरसेप्ट कर सकता है, डीबगर involvement का परीक्षण करता है।43. जाँचता है कि हमारी स्वयं की on-disk image का पहला बाइट 0xCC है या नहीं और Windows loader file-handle व्यवहार का फायदा उठाता है जहाँ LoadLibrary डीबगर के अधीन फ़ाइल को non-exclusively accessible छोड़ सकता है।