修改Visual Studio默认搜索顺序,防范DLL预加载攻击
解决Windows系统DLL预加载攻击问题(以Version.dll为例)
针对你遇到的系统DLL被预加载攻击的问题,以下是几种直接有效的解决方案:
一、显式加载系统目录下的DLL(最安全)
放弃隐式链接,改用LoadLibraryEx直接加载系统目录中的目标DLL,完全绕过默认搜索顺序。步骤如下:
- 调用
GetSystemDirectory获取系统目录路径(32位应用在64位系统上会返回SysWOW64路径) - 拼接目标DLL的完整路径
- 使用
LoadLibraryEx加载DLL,并通过GetProcAddress获取所需函数指针
示例代码:
#include <windows.h> #include <shlwapi.h> #pragma comment(lib, "shlwapi.lib") // 定义Version.dll中需要的函数指针类型 typedef DWORD (WINAPI *GetFileVersionInfoSizeWPtr)(LPCWSTR, LPDWORD); typedef BOOL (WINAPI *GetFileVersionInfoWPtr)(LPCWSTR, DWORD, DWORD, LPVOID); typedef BOOL (WINAPI *VerQueryValueWPtr)(LPCVOID, LPCWSTR, LPVOID, PUINT); int main() { WCHAR systemDir[MAX_PATH]; // 获取系统目录 if (!GetSystemDirectoryW(systemDir, MAX_PATH)) { return GetLastError(); } // 拼接Version.dll的完整路径 PathAppendW(systemDir, L"Version.dll"); // 加载系统目录下的Version.dll,指定仅搜索系统目录 HMODULE hVersionDll = LoadLibraryExW(systemDir, NULL, LOAD_LIBRARY_SEARCH_SYSTEM_DIRS); if (!hVersionDll) { return GetLastError(); } // 获取函数地址 GetFileVersionInfoSizeWPtr pGetFileVersionInfoSize = reinterpret_cast<GetFileVersionInfoSizeWPtr>(GetProcAddress(hVersionDll, "GetFileVersionInfoSizeW")); GetFileVersionInfoWPtr pGetFileVersionInfo = reinterpret_cast<GetFileVersionInfoWPtr>(GetProcAddress(hVersionDll, "GetFileVersionInfoW")); VerQueryValueWPtr pVerQueryValue = reinterpret_cast<VerQueryValueWPtr>(GetProcAddress(hVersionDll, "VerQueryValueW")); // 调用函数获取版本信息(示例逻辑) if (pGetFileVersionInfoSize && pGetFileVersionInfo && pVerQueryValue) { DWORD dummy; DWORD size = pGetFileVersionInfoSize(L"your_app.exe", &dummy); if (size > 0) { LPVOID buffer = LocalAlloc(LPTR, size); if (buffer) { pGetFileVersionInfo(L"your_app.exe", 0, size, buffer); // 后续处理版本信息... LocalFree(buffer); } } } FreeLibrary(hVersionDll); return 0; }
二、修改进程的DLL搜索顺序
通过系统API调整进程的DLL搜索规则,移除当前工作目录的优先级:
1. 移除当前工作目录搜索路径
在进程启动时调用SetDllDirectoryW(L""),此操作会将当前工作目录从默认搜索顺序中剔除,后续所有隐式加载的DLL都不会优先搜索当前目录。
示例(放在main开头):
#include <windows.h> int main() { // 清空当前目录搜索路径 SetDllDirectoryW(L""); // 后续正常执行代码,隐式链接的Version.dll会跳过当前目录搜索 return 0; }
2. 限制仅搜索系统目录(Windows 7及以上)
使用SetDefaultDllDirectories指定仅搜索系统目录和安全路径,进一步缩小搜索范围:
#include <windows.h> int main() { // 设置默认搜索目录为系统目录+默认安全路径 SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM_DIRS | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); // 后续隐式加载的DLL只会从指定目录搜索 return 0; }
三、通过清单文件指定DLL路径
在应用的清单文件中添加<file>元素,明确指定Version.dll的系统路径,让Windows加载器直接从该路径加载:
示例清单内容:
<?xml version="1.0" encoding="UTF-8"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <!-- 指定Version.dll的系统路径 --> <file name="Version.dll" path="%SystemRoot%\system32\"/> <!-- 若为32位应用,路径改为%SystemRoot%\SysWOW64\ --> <!-- <file name="Version.dll" path="%SystemRoot%\SysWOW64\"/> --> </assembly>
将此清单文件嵌入应用(在Visual Studio中设置为“嵌入的资源”),加载器会优先使用清单中指定的路径加载DLL。
内容的提问来源于stack exchange,提问作者Preethi Ravi
相关产品推荐
相关产品推荐

