
Заголовочная библиотека C++17 для скрытной разработки под Windows: хэширование API на этапе компиляции, снятие хуков DLL, очистка аппаратных точек останова, удаление VEH и подавление callback-уведомлений DLL для обхода хуков EDR.
Это продолжение моего исходного проекта 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, мы не платим за неиспользуемые функции, так как они являются мёртвым кодом и оптимизируются из программы.
Чтобы импортировать 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