概述:如何安全加载dll文件,防止 dll 替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
__inline HMODULE WINAPI LoadLibraryEx_api(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{
return ::LoadLibraryEx(lpFileName, hFile, dwFlags);
}
//安全版LoadLibrary_api,可以降低dll劫持的可能性
HMODULE WINAPI LoadLibrary_api_s(LPCTSTR lpFileName)
{
#ifdef __360PubDLLSafeInitHelper
/*
当使用 S360时,我们优先使用 S360 提供是 DLL 安全加载。
这是因为 S360 提供的LoadLibraryFormSystem32能为Windows XP以及其他所有没有安装 KB2533623 的系统提供 LOAD_LIBRARY_SEARCH_SYSTEM32 特性。
提升不支持 LOAD_LIBRARY_SEARCH_SYSTEM32 特性系统中的安全性。
*/
return S360::Helper::LoadLibraryFormSystem32(lpFileName);
#elif defined _M_IX86 || defined _M_AMD64 || defined _M_IA64
/*
https://docs.microsoft.com/zh-cn/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibraryexa
Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008:
The LOAD_LIBRARY_SEARCH_ flags are available on systems that have KB2533623 installed.
To determine whether the flags are available, use GetProcAddress to get the address of
the AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories function.
If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_ flags can be used with LoadLibraryEx.
*/
//不再使用ERROR_INVALID_PARAMETER判断,规避联想一键影音导致的Hook Bug。
static int bSafeLoadAvailable = 0;

if (bSafeLoadAvailable == 0)
{
//此处不考虑线程安全,因为多执行一次 GetProcAddress 操作没什么大不了的。
bSafeLoadAvailable = GetProcAddress(GetModuleHandleW(L"Kernel32.dll"), "AddDllDirectory") != NULL ? 1 : -1;
}

//尝试使用DLL安全初始化
return LoadLibraryEx_api(lpFileName, NULL, bSafeLoadAvailable == 1 ? /*LOAD_LIBRARY_SEARCH_SYSTEM32*/0x00000800 : 0);
#else // ARM || ARM64
//始终使用DLL安全初始化
return LoadLibraryEx_api(lpFileName, NULL, /*LOAD_LIBRARY_SEARCH_SYSTEM32*/0x00000800);
#endif
}