
चोरी-छिपे Windows विकास के लिए हेडर-ओनली C++17 लाइब्रेरी: कंपाइल-टाइम API हैशिंग, DLL अनहुकिंग, हार्डवेयर ब्रेकपॉइंट क्लियरिंग, VEH निष्कासन, और EDR हुक्स से बचने के लिए DLL नोटिफिकेशन-कॉलबैक दमन।
यह मेरे मूल प्रोजेक्ट WTSRM और संबंधित टॉक की निरंतरता है।
इस प्रोजेक्ट को C++17 का उपयोग करने के लिए फिर से लिखा गया था, ताकि एक टेम्पलेट तैयार किया जा सके जो हमें कंपाइल-टाइम पर आवश्यक कार्यक्षमता को आसानी से बदलने की अनुमति देता है! इसे केवल हेडर फ़ाइल के रूप में लागू किया गया है, जिससे आप इसे अपने प्रोजेक्ट्स में आसानी से जोड़ सकते हैं।
वर्तमान में लागू की गई कुछ विशेषताओं में शामिल हैं:
हम इस व्यवहार को निम्नानुसार कॉन्फ़िगर कर सकते हैं
#define HASHING_ALGORITHM hash_string_fnv1a // constexpr algorithm
namespace config
{
...
//
// configure behaviour
//
inline constexpr unsigned unhooking = system32 | write_process_memory;
inline constexpr auto work_item_load_library = true; // use a work item for LL
//
// configure evasive features
//
inline constexpr auto clear_and_restore_veh = true; // clear and restore veh
inline constexpr auto unregister_dll_notifs = true; // LdrRegisterDllNotification
inline constexpr auto clear_thread_hwbps = true; // clear the hwbps
}
चूंकि हम constexpr का उपयोग करते हैं, इसलिए हम उन सुविधाओं के लिए भुगतान नहीं करते जिनका हम उपयोग नहीं करते, क्योंकि वे डेड कोड हैं और प्रोग्राम से अनुकूलित (optimized) हो जाते हैं।
DLL आयात करने के लिए पहले हमें DLL_HASH मैक्रो का उपयोग करके हैश बनाना होगा
DLL_HASH(DBGHELP, L"DBGHELP.DLL")
फिर हमें इसे module_address_table में जोड़ना होगा, जो हमारे आंतरिक IAT के रूप में कार्य करता है। hash_ स्थिरांक DLL_HASH मैक्रो द्वारा बनाया गया है। गैर-सामान्य DLL के लिए जो हमेशा लोड नहीं होते, हमें उनका नाम निर्दिष्ट करना होगा ताकि हम उन्हें लोड कर सकें।
inline addr_struct<decltype(HASHING_ALGORITHM(TOKENIZEA(T))), wchar_t> module_address_table[] =
{
{hash_NTDLL, nullptr,},
{hash_KERNEL32, nullptr,},
{hash_DBGHELP, nullptr, L"DBGHELP.DLL"}
};
फ़ंक्शन आयात करने के लिए, पहले हमें HASH_FUNC मैक्रो का उपयोग करके फ़ंक्शन नाम हैश और typedef बनाना होगा
HASH_FUNC(NtUnmapViewOfSection, NTSTATUS, HANDLE, PVOID)
पहला पैरामीटर फ़ंक्शन का नाम है, अगला रिटर्न प्रकार है, और फिर फ़ंक्शन के तर्क (arguments) हैं। फिर हमें इसे अपने api_address_table में जोड़ना आवश्यक है, जो वर्तमान फ़ंक्शन पतों से भरा जाएगा
inline addr_struct<decltype(HASHING_ALGORITHM(TOKENIZEA(T))), void> api_address_table[] =
{
{hash_GetProcAddress, nullptr},
{hash_NtUnmapViewOfSection, nullptr},
यदि आप इस फ़ंक्शन को इस तालिका में जोड़ने में विफल रहते हैं, तो प्रोग्राम क्रैश नहीं होगा, बल्कि स्थिरता बढ़ाने के प्रयास में -1 लौटाएगा।
API का उपयोग करने के लिए API()() मैक्रो का उपयोग करें जैसा कि प्रदर्शित किया गया है
API(NtWaitForSingleObject)(NtCurrentProcess(), FALSE, &timeout);
अपना स्वयं का API हैशिंग फ़ंक्शन जोड़ने के लिए आपको आवश्यक प्रकारों के साथ काम करने हेतु इस टेम्पलेट का उपयोग करना होगा।
template <typename T>
constexpr auto hash_string_(const T* buffer)
{
TRIVIAL_TYPE_CHECK()
}
इन व्यक्तियों को उनके विचारों और योगदान के लिए धन्यवाद (किसी विशेष क्रम में नहीं) @peterwintrsmith @modexpblog @jonaslyk @JustasMasiulis