如何确保MinGW编译的wintrust代理DLL在32/64位Windows兼容并验证功能
为wintrust.dll创建代理DLL:兼容性保障与功能验证方案
需求与当前实现
我正在使用MinGW32/64工具链的gcc,为wintrust.dll编译32位和64位的代理DLL,核心目标是让WinVerifyTrust函数始终返回成功,其余函数转发至系统原始wintrust.dll。当前实现的文件如下:
wintrust_proxy.def
EXPORTS WinVerifyTrust @1 ComputeFirstPageHash=wintrust.ComputeFirstPageHash @2 CryptCATVerifyMember=wintrust.CryptCATVerifyMember @3 CryptSIPGetInfo=wintrust.CryptSIPGetInfo @4 CryptSIPGetRegWorkingFlags=wintrust.CryptSIPGetRegWorkingFlags @5 ; rest of the wintrust.dll functions…
wintrust_proxy.c
#include <windows.h> // Define Success as 0 #define WINVERIFYTRUST_SUCCESS 0 // Define the function signature based on the original WinVerifyTrust WINAPI LONG WinVerifyTrust( HWND hwnd, GUID *pgActionID, LPVOID pWVTData ) { // Return Success enum value return WINVERIFYTRUST_SUCCESS; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
compile.bat
@echo off setlocal REM Switch to mingw32 bin folder (32-bit environment) set "PATH=C:\msys64\mingw32\bin\" gcc "wintrust_proxy.c" "wintrust_proxy.def" -o "wontrust.dll" -shared -static-libgcc -Wl,--enable-stdcall-fixup REM Switch to mingw64 bin folder (64-bit environment) set "PATH=C:\msys64\mingw64\bin\" gcc "wintrust_proxy.c" "wintrust_proxy.def" -o "womtrust.dll" -shared -static-libgcc pause endlocal
当前输出为32位的wontrust.dll和64位的womtrust.dll,但需要解决两个问题:确保DLL在新旧Windows系统无额外依赖运行,以及验证版本功能符合预期。
一、确保DLL跨Windows版本兼容且无额外依赖
1. 优化编译参数
- 静态链接所有非系统库:除了
-static-libgcc,添加-static-libstdc++(即使当前用C编写,避免潜在的C++ runtime依赖),同时添加-Wl,--no-undefined参数,编译时检查未定义符号,提前发现转发函数的错误。 - 指定兼容的最低Windows版本:添加
-D_WIN32_WINNT=0x0501(对应Windows XP)或0x0600(对应Vista),让编译器生成兼容旧系统的代码,避免依赖高版本系统才有的API。修改后的编译命令示例:# 32位编译 gcc "wintrust_proxy.c" "wintrust_proxy.def" -o "wontrust.dll" -shared -static-libgcc -static-libstdc++ -D_WIN32_WINNT=0x0501 -Wl,--enable-stdcall-fixup,--no-undefined # 64位编译 gcc "wintrust_proxy.c" "wintrust_proxy.def" -o "womtrust.dll" -shared -static-libgcc -static-libstdc++ -D_WIN32_WINNT=0x0501 -Wl,--no-undefined - 避免使用非标准API:确保代码仅调用Windows核心API(如kernel32、user32中的函数),这些API在所有Windows版本中均存在。
2. 强化依赖检查
- 使用Dependencies(新版工具,替代Dependency Walker)或VS的
dumpbin /dependents命令,检查DLL的依赖项:- 32位DLL应仅依赖
syswow64下的kernel32.dll、user32.dll等系统核心库; - 64位DLL应仅依赖
system32下的对应系统库; - 若发现依赖MinGW的runtime库(如
libgcc_s_dw2-1.dll),说明静态链接参数未生效,需检查编译命令。
- 32位DLL应仅依赖
3. 保持编译环境一致性
使用MSYS2的最新版本,定期更新MinGW工具链(通过pacman -Syu命令),避免旧工具链的兼容性bug。
二、验证32/64位DLL功能符合预期
1. 直接验证WinVerifyTrust返回值
编写简单的测试程序,分别调用对应版本的DLL,检查返回值是否为0:
32位测试程序(test32.c)
#include <windows.h> #include <stdio.h> typedef LONG (WINAPI *WinVerifyTrustFunc)(HWND, GUID*, LPVOID); int main() { HMODULE hDll = LoadLibraryA("wontrust.dll"); if (!hDll) { printf("加载32位DLL失败: %d\n", GetLastError()); return 1; } WinVerifyTrustFunc func = (WinVerifyTrustFunc)GetProcAddress(hDll, "WinVerifyTrust"); if (!func) { printf("获取函数地址失败: %d\n", GetLastError()); FreeLibrary(hDll); return 1; } LONG result = func(NULL, NULL, NULL); printf("32位WinVerifyTrust返回值: %ld\n", result); if (result == 0) { printf("验证成功: 返回预期的成功值\n"); } else { printf("验证失败: 返回非预期值\n"); } FreeLibrary(hDll); return 0; }
编译命令(MinGW32环境):
gcc test32.c -o test32.exe
运行test32.exe,确认输出返回值为0。
64位测试程序(test64.c)
将上述代码中的wontrust.dll改为womtrust.dll,用MinGW64环境编译:
gcc test64.c -o test64.exe
运行后确认返回值为0。
2. 验证转发函数有效性
对于def文件中转发至系统wintrust.dll的函数(如ComputeFirstPageHash),可以编写测试代码调用这些函数,确保能正常执行:
#include <windows.h> #include <stdio.h> typedef BOOL (WINAPI *ComputeFirstPageHashFunc)(HANDLE, DWORD*, DWORD); int main() { HMODULE hDll = LoadLibraryA("wontrust.dll"); // 64位用womtrust.dll if (!hDll) { printf("加载DLL失败: %d\n", GetLastError()); return 1; } ComputeFirstPageHashFunc func = (ComputeFirstPageHashFunc)GetProcAddress(hDll, "ComputeFirstPageHash"); if (!func) { printf("获取转发函数地址失败: %d\n", GetLastError()); FreeLibrary(hDll); return 1; } // 传入无效参数测试(仅验证函数能被调用,不会崩溃) BOOL result = func(NULL, NULL, 0); printf("转发函数调用结果: %d\n", result); FreeLibrary(hDll); return 0; }
编译运行后,若程序未崩溃且能获取函数地址,说明转发配置正确。
3. 实际场景测试
找一个依赖wintrust.dll进行签名验证的程序:
- 对于32位程序,将其目录下的
wintrust.dll替换为你的wontrust.dll; - 对于64位程序,替换为
womtrust.dll; - 运行程序,若原本因签名无效无法运行的程序现在能正常启动,说明代理DLL生效。
4. 跨系统兼容性测试
在不同Windows版本(如Windows 7、10、11,以及32位Windows系统)上重复上述测试,确保DLL能正常加载并工作。
内容的提问来源于stack exchange,提问作者Lawrence Cohen
相关产品推荐
相关产品推荐

