You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何确保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),说明静态链接参数未生效,需检查编译命令。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 01:54:55