
مكتبة C++17 مكوّنة من ملفات رأس فقط (Header-only) لتطوير برمجيات ويندوز مراوِغة: تجزئة واجهات API في وقت الترجمة، فكّ خطافات DLL، مسح نقاط التوقف العتادية، إزالة VEH، وقمع استدعاءات الإعلام الخاصة بـ DLL للتهرب من خطافات EDR.
هذا استمرار لمشروعي الأصلي WTSRM وإلى المحاضرة المرتبطة به.
أُعيدت كتابة هذا المشروع من أجل استخدام C++17 لإنشاء قالب (template) يتيح لنا تغيير الوظائف المطلوبة بسهولة في وقت الترجمة! تم تنفيذه كملف ترويسة فقط بحيث يمكنك إضافته بسهولة إلى مشاريعك الخاصة.
بعض الميزات المطبقة حاليًا تشمل:
.text باستخدام \KnownDlls\ أو \System32\يمكننا تكوين هذا السلوك كما يلي
#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، فإننا لا ندفع ثمن الميزات التي لا نستخدمها لأنها كود ميت (dead code) ويتم استبعادها من البرنامج.
لاستيراد مكتبات 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"}
};
لاستيراد الدوال، يجب أولاً إنشاء تجزئة اسم الدالة و typedef باستخدام ماكرو HASH_FUNC
HASH_FUNC(NtUnmapViewOfSection, NTSTATUS, HANDLE, PVOID)
المعامل الأول هو اسم الدالة، يليه نوع الإرجاع، ثم وسائط الدالة. بعد ذلك، يتعين علينا إضافته إلى 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