📄 Безопасная работа с DLL: Защита от инъекций и цифровые подписи в C++

Безопасная работа с DLL: Защита от инъекций и цифровые подписи в C++

Введение: Почему это критически важно?

DLL (Dynamic Link Libraries) — мощный инструмент модульности в Windows, но их уязвимость к инъекциям и подмене превращает их в «ахиллесову пяту» безопасности. Результат: утечки данных, RCE-атаки, кражи сессий. Ваша миссия — превратить DLL из слабости в крепость!


1. Безопасная загрузка DLL: Контроль над процессом

✅ Практики:

  • Полные пути вместо LoadLibrary("dll.dll")
wchar_t fullPath[MAX_PATH];
GetFullPathNameW(L"my_secure.dll", MAX_PATH, fullPath, nullptr);
HMODULE hLib = LoadLibraryW(fullPath);  // Загрузка по абсолютному пути
  • Ограничение поиска DLL:
SetDllDirectory(L"");  // Отключает поиск в текущей директории
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32); // Разрешает только System32

⚠️ Опасность:

Атаки через DLL Search Order Hijacking — злоумышленник кладет вредоносную your_dll.dll в C:\temp, и ваше приложение грузит ее вместо системной!

?️ 2. Защита от DLL-инъекторов: Страж процесса

Методы детектирования:

// Проверка нелегальных модулей
void CheckForSuspiciousModules() {
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
    MODULEENTRY32 me = { sizeof(me) };
    for (BOOL ok = Module32First(hSnapshot, &me); ok; ok = Module32Next(hSnapshot, &me)) {
        if (IsIllegalModule(me.szModule)) {  // Ваша функция проверки
            TerminateProcess(GetCurrentProcess(), 0xDEAD); // Экстренное завершение
        }
    }
    CloseHandle(hSnapshot);
}

?️ Техники защиты:

  1. Callbacks-фильтры:
LPVOID pCallback = AddVectoredExceptionHandler(1, VectoredHandler);
  1. Хуки на LoadLibrary:
DetourTransactionBegin();
DetourAttach(&(PVOID&)Real_LoadLibrary, My_LoadLibrary);
DetourTransactionCommit();

3. Цифровые подписи: Гарантия подлинности

Верификация подписи DLL (пример):

#include <Softpub.h>
#include <Wintrust.h>

bool VerifySignature(const wchar_t* dllPath) {
    WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo) };
    fileInfo.pcwszFilePath = dllPath;

    WINTRUST_DATA trustData = { sizeof(trustData) };
    trustData.dwUIChoice = WTD_UI_NONE;
    trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
    trustData.dwUnionChoice = WTD_CHOICE_FILE;
    trustData.pFile = &fileInfo;

    GUID policy = WINTRUST_ACTION_GENERIC_VERIFY_V2;
    LONG status = WinVerifyTrust(NULL, &policy, &trustData);
    return (status == ERROR_SUCCESS); // Подпись действительна
}

Ключевые шаги:

  1. Получить сертификат EV Code-Signing (не SHA1!).
  2. Подписывать каждую сборку:
signtool sign /fd SHA256 /f "cert.pfx" /p password "my_dll.dll"
  1. Проверять подпись при загрузке DLL.

4. Продвинутые практики:

  • ASLR + DEP:
    /DYNAMICBASE и /NXCOMPAT в компиляторе.
  • Песочница: Запуск подложных процессов с ограниченными правами.
  • Анти-отладка:
if (IsDebuggerPresent()) std::exit(11);

Заключение: Ваш чек-лист безопасности

  1. Всегда указывайте абсолютные пути для DLL.
  2. Верифицируйте цифровые подписи перед загрузкой.
  3. Мониторьте модули процесса на нелегальные вставки.
  4. Используйте строгие разрешения для файлов DLL (только для TrustedInstaller).
  5. Обновляйте зависимости — устаревшие библиотеки = смертельный риск.

Безопасность — не фича, а фундамент. 10 минут, потраченные на интеграцию этих практик, спасут годы репутации.

? Дополнительные ресурсы:

  • Microsoft Docs: «Secure Loading of Libraries»
  • OWASP: DLL Injection Prevention Cheat Sheet
  • Курс «Windows Security Internals» на Pluralsight

// КОММЕНТАРИИ (0)

// ОСТАВИТЬ КОММЕНТАРИЙ

// Ваш email не будет опубликован. Обязательные поля помечены *