Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
Log in
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

फ़ीडसंपर्कगोपनीयता© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
hwbp4mw — विंडोज़ के लिए हार्डवेयर ब्रेकपॉइंट हुकिंग इंजन जो फ़ंक्शंस को हुक करने, ETW/AMSI को बायपास करने, और यूज़र-लैंड EDR मॉनिटरिंग से बचने के लिए डिबग रजिस्टर का उपयोग करता है। | Kitploit
उपकरण/GitHubGitHub/rad9800/hwbp4mw
आईडीएस/आईपीएस से बचनाडीबगर्सपोस्ट-शोषणरेड टीमिंगप्रतिकूल हमला
GitHubrad9800/hwbp4mw

hwbp4mw

विंडोज़ के लिए हार्डवेयर ब्रेकपॉइंट हुकिंग इंजन जो फ़ंक्शंस को हुक करने, ETW/AMSI को बायपास करने, और यूज़र-लैंड EDR मॉनिटरिंग से बचने के लिए डिबग रजिस्टर का उपयोग करता है।

रिपॉजिटरी देखें
27354193 साल पहलेKitploit द्वारा समीक्षित

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

यह लेख मूल रूप से VX-Underground Black Mass Halloween Edition 2022 के लिए था।

हुकिंग इंजन:

  • मल्टी-थ्रेड सुरक्षित x86/x64 hwbp हुकिंग इंजन c
  • PAGE_GUARD/hwbp ब्रेकपॉइंट लाइब्रेरी c++20
  • hwbp लाइब्रेरी (DLL उदाहरण) c++20

डीबग रजिस्टर का उपयोग करते हुए सामान्य x64 यूज़र-लैंड एवेज़न तकनीक:

  • TamperingSyscalls2 c
  • TamperingSyscalls2 c++20

ETW/AMSI हुक के उदाहरण उपलब्ध

  • rad9800/misc

मैलवेयर के लिए हार्डवेयर ब्रेकपॉइंट्स v 1.0

हमारा कार्य फ़ंक्शनों को आसानी से हुक करना और आवश्यकतानुसार कोड प्रवाह को मोड़ना है, और अंत में जब हुक की आवश्यकता न रह जाए तो उसे हटा देना है।

हम IAT हुक लगाने पर विचार नहीं कर सकते क्योंकि उन्हें हमेशा कॉल नहीं किया जाता और इसलिए वे अविश्वसनीय हैं। इनलाइन हुकिंग एक शक्तिशाली तकनीक है; हालाँकि, इसके लिए हमें उस मेमोरी को पैच करना आवश्यक है जहाँ कोड स्थित होता है। यह एक शक्तिशाली तकनीक है, लेकिन PE-Sieve और Moneta जैसे उपकरण मॉड्यूल की मेमोरी-स्थित प्रति और डिस्क-स्थित प्रति के बीच अंतर को पहचान सकते हैं और फ़्लैग कर सकते हैं। यह हमें इस कार्य के लिए सही उपकरण देता है: डीबग रजिस्टर, हालाँकि वे मैलवेयर लेखकों द्वारा काफी कम सराहे गए हैं!

विंडोज़ पर, उच्च-स्तरीय अवलोकन के रूप में, एक प्रक्रिया अनिवार्य रूप से थ्रेड्स का संपुटन है, और इनमें से प्रत्येक थ्रेड एक कॉन्टेक्स्ट बनाए रखता है जो थ्रेड की स्थिति है: रजिस्टर, स्टैक आदि। डीबग रजिस्टर एक विशेषाधिकार प्राप्त संसाधन हैं, और उन्हें सेट करना भी विशेषाधिकार प्राप्त है; हालाँकि, विंडोज़ विभिन्न syscalls उजागर करता है, जो हमें अनुरोध करने की अनुमति देते हैं कि कर्नेल हमारी ओर से एक विशेषाधिकार प्राप्त कार्रवाई करे; इसमें डीबग रजिस्टर सेट करना शामिल है जो हमारे लिए एकदम सही हैं। NtSetThreadContext और NtGetThreadContext कार्यक्षमता उजागर करते हैं किसी भी थ्रेड कॉन्टेक्स्ट को संशोधित करने के लिए जिसके लिए हम आवश्यक विशेषाधिकार के साथ हैंडल खोल सकते हैं। हम देख सकते हैं कि Win32 API के साथ डीबग रजिस्टर कैसे सेट करें।```c CONTEXT context = { .ContextFlags = CONTEXT_DEBUG_REGISTERS }; GetThreadContext(thd, &context);

// set our debug information in the Dr registers

SetThreadContext(thd, &context);
There are 8 Debug registers, from Dr0 through to Dr7. The ones of interest to us are only
Dr0-3 which we store addresses we would like to break on, and Dr6 is just the debug
status. Most importantly is Dr7, which describes the breakpoints conditions in which the
processor will throw an exception. There are various limitations when using debug
registers, such as a limited number (4) and not being applied to all threads/newly
spawned threads. We will look to address some of these limitations!

यहाँ Dr0 से Dr7 तक 8 डिबग रजिस्टर होते हैं। हमारे लिए केवल Dr0-3 ही महत्वपूर्ण हैं, जिनमें हम वे पते संग्रहीत करते हैं जिन पर हम ब्रेक करना चाहते हैं, और Dr6 केवल डिबग स्थिति है। सबसे महत्वपूर्ण Dr7 है, जो ब्रेकपॉइंट की उन शर्तों को दर्शाता है जिनके अंतर्गत प्रोसेसर एक अपवाद उत्पन्न करेगा। डिबग रजिस्टरों का उपयोग करते समय कई सीमाएँ होती हैं, जैसे सीमित संख्या (4) और सभी थ्रेड्स/नव निर्मित थ्रेड्स पर लागू न होना। हम इनमें से कुछ सीमाओं को दूर करने का प्रयास करेंगे!

जब अपवाद उत्पन्न होता है, तो यह एक अपवाद हैंडलर की तलाश करेगा, जिसे हम अपने प्रोग्राम में परिभाषित और पंजीकृत कर सकते हैं [1]। अपने परिभाषित अपवाद हैंडलर में, हम चाहते हैं कि संबंधित ब्रेकपॉइंट ट्रिगर होने पर हमारा संबद्ध कोड (विभिन्न कोड प्रवाह) चले।```c
LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
	if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)
	{
		// Look for our associated code flow relative to our RIP 
		if (HWBP_ADDRESS_MAP.contains(ExceptionInfo->ContextRecord->Rip)) {
			HWBP_ADDRESS_MAP.at(ExceptionInfo->ContextRecord->Rip).func(ExceptionInfo);
			return EXCEPTION_CONTINUE_EXECUTION;
		}
	}
	return EXCEPTION_CONTINUE_SEARCH;
}

यह एक कंस्ट्रक्टर फ़ंक्शन द्वारा प्राप्त किया जाता है जो एक "callback" लैम्ब्डा फ़ंक्शन और एक एड्रेस के बीच मैपिंग सेट करता है। using EXCEPTION_FUNC = std::function <void(PEXCEPTION_POINTERS)>;```c typedef struct { UINT pos; EXCEPTION_FUNC func; } HWBP_CALLBACK;

// Global std::unordered_map<uintptr_t, HWBP_CALLBACK> HWBP_ADDRESS_MAP{ 0 };

// Create our mapping HWBP_ADDRESS_MAP[address].func = function; HWBP_ADDRESS_MAP[address].pos = pos;

हमें अपने सभी प्रोसेस थ्रेड्स के माध्यम से पुनरावृत्ति करनी होगी और उनके लिए संदर्भ में संबंधित समायोजन
सेट करने होंगे। यह ToolHelp32 सहायक फ़ंक्शनों का उपयोग करके प्राप्त किया जा सकता है:
CreateToolhelp32Snapshot, और Thread32Next। यह कुछ खास नहीं है, लेकिन यह हमारी एक सीमा को संबोधित करता है
जो सभी थ्रेड्स से न जुड़ने की है।```c
VOID SetHWBPS(const uintptr_t address, const UINT pos, const bool init = true)
{
	DWORD pid{ GetCurrentProcessId() };
	HANDLE h{ CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0) };
	if (h != INVALID_HANDLE_VALUE) {
		THREADENTRY32 te{ .dwSize = sizeof(THREADENTRY32) };
		if (Thread32First(h, &te)) {
			do {
				if ((te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
					sizeof(te.th32OwnerProcessID)) && te.th32OwnerProcessID == pid) {

					HANDLE thd = OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
					if (thd != INVALID_HANDLE_VALUE) {
						SetHWBP(thd, address, pos, init);
						CloseHandle(thd);
					}
				}
				te.dwSize = sizeof(te);
			} while (Thread32Next(h, &te));
		}
		CloseHandle(h);
	}
}

हार्डवेयर ब्रेकपॉइंट सेट होना संदिग्ध माना जा सकता है क्योंकि वे दुर्भावनापूर्ण गतिविधि का संकेत दे सकते हैं (हालाँकि मेरी जानकारी के अनुसार कोई EDR सक्रिय रूप से इन्हें स्कैन नहीं करते)। इन्हें उपयोग किया जा सकता है हमारे विरुद्ध संभावित IoC के रूप में, इसलिए हमें इनका उपयोग समाप्त करने के बाद इनके निशान हटाने होंगे।

हम इसे अपने deconstructor फ़ंक्शन में लागू कर सकते हैं!! यह सभी थ्रेड्स को इटरेट करेगा और जाँच करेगा कि क्या रजिस्टर (&context.Dr0)[pos] उस पते की ओर इशारा करता है जिस पर हमने शुरू में हार्डवेयर ब्रेकपॉइंट सेट किया था (pos केवल एक index % 4 है जो हमें पहुँच प्रदान करता है context.Dr0-Dr3 तक)। हम Dr7 रजिस्टर में आवश्यक शर्तों को भी हटा सकते हैं। हमें अपनी मैपिंग प्रविष्टि को हटाना भी याद रखना चाहिए। इसलिए, हमारा हार्डवेयर ब्रेकपॉइंट केवल आवश्यक अवधि के लिए उपस्थित रहेगा!```c SetHWBPS(address, pos, false); HWBP_ADDRESS_MAP.erase(address);

हार्डवेयर ब्रेकपॉइंट का एक उदाहरण Sleep होगा, जहाँ हम स्लीप अवधि को
0 से बदल देते हैं।```c
HWBP HWBPSleep{ (uintptr_t)&Sleep, 0,	// Set Dr 0 
	([&](PEXCEPTION_POINTERS ExceptionInfo) {
		ExceptionInfo->ContextRecord->Rcx = 0;
		ExceptionInfo->ContextRecord->EFlags |= (1 << 16);	// continue execution
}) };

हमें पता है कि x64 Windows चार-रजिस्टर fast-call कॉलिंग कन्वेंशन[1] के कारण RCX सेट करना होता है। कंस्ट्रक्टर का पहला आर्गुमेंट वह पता है जिस पर ब्रेक करना है, दूसरा यह है कि किस Dr0- 3 रजिस्टर में स्टोर करना है (ध्यान दें, हम एक समय में केवल 4 पतों पर ब्रेक कर सकते हैं), और तीसरा एक lambda फ़ंक्शन है जो संदर्भ द्वारा PEXCEPTION_POINTERS को कैप्चर करेगा, जो वह जानकारी है जो exception handler को प्राप्त होगी। यह अंततः हमें किसी प्रोग्राम के प्रवाह को अलग-अलग तरीके से नियंत्रित करने देगा, जो इस बात पर निर्भर करता है कि कौन सा ब्रेकपॉइंट ट्रिगर हुआ।

जब कोई नया thread बनाया जाता है, तो वह संबद्ध Debug Registers सेट इनहेरिट नहीं करता, जब तक कि हम किसी तरह नए thread के निर्माण को इंटरसेप्ट न कर लें! एक आसान तरकीब जो हम उपयोग कर सकते हैं वह है वास्तविक start address को कैप्चर करना और नए thread को हमारे अपने thread बनाने के लिए मोड़ देना। अधिकांश नए thread NtCreateThreadEx को कॉल करके समाप्त होते हैं।```c // Global Variable PVOID START_THREAD{ 0 };

टूल डाउनलोड करें