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

为何X509Chain.Build()在DLL签名无效时仍返回True?

问题原因及解决方案

你的代码只完成了证书链有效性验证,但没有验证DLL的Authenticode签名与文件内容的一致性——这是两个完全独立的操作:

  • new X509Certificate2("path/To/The/Dll")仅提取DLL中嵌入的签名证书,无论DLL内容是否被篡改,这个证书都能被正常读取。
  • X509Chain.Build()仅验证该证书能否通过你指定的根/中间证书构成信任链,完全不检查证书对应的签名是否与当前DLL的字节内容匹配。

所以即便你修改了DLL字节,只要嵌入的证书本身信任链有效,Build()就会返回true。


正确的验证方式:验证DLL的Authenticode签名完整性

要检测DLL篡改后的签名失效,需要使用专门处理Authenticode签名的API。以下是两种适配离线环境的实现方式:

方式1:使用.NET原生SignedCms类

using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.IO;

// 读取DLL字节
byte[] dllBytes = File.ReadAllBytes("path/To/The/Dll");
ContentInfo contentInfo = new ContentInfo(dllBytes);
SignedCms signedCms = new SignedCms(contentInfo, detached: false);

try
{
    // 从DLL中解码签名信息
    signedCms.Decode(dllBytes);
    
    // 配置离线验证策略:添加信任的根/中间证书,关闭吊销检查
    X509Certificate2Collection extraStore = new X509Certificate2Collection();
    extraStore.Add(intermediateCertificate);
    extraStore.Add(rootCertificate);
    
    X509ChainPolicy chainPolicy = new X509ChainPolicy();
    chainPolicy.ExtraStore = extraStore;
    chainPolicy.RevocationMode = X509RevocationMode.NoCheck;
    chainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
    
    // 执行签名+证书链双重验证
    signedCms.CheckSignature(extraStore, verifySignatureOnly: false);
    Console.WriteLine("DLL签名有效且证书链可信");
}
catch (CryptographicException ex)
{
    Console.WriteLine($"签名验证失败:{ex.Message}");
}

方式2:使用Windows原生WinVerifyTrust API

该方式与系统级签名验证逻辑完全一致,适合需要严格匹配Windows验证规则的场景:

using System;
using System.Runtime.InteropServices;

public static class AuthenticodeChecker
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct WINTRUST_FILE_INFO
    {
        public uint cbStruct;
        public string pcwszFilePath;
        public IntPtr hFile;
        public IntPtr pgKnownSubject;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct WINTRUST_DATA
    {
        public uint cbStruct;
        public IntPtr pPolicyCallbackData;
        public IntPtr pSIPClientData;
        public uint dwUIChoice;
        public uint fdwRevocationChecks;
        public uint dwUnionChoice;
        public IntPtr pFile;
        public uint dwStateAction;
        public IntPtr hWVTStateData;
        public string pwszURLReference;
        public uint dwProvFlags;
        public uint dwUIContext;
        public IntPtr pSignatureSettings;
    }

    [DllImport("wintrust.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern uint WinVerifyTrust(IntPtr hwnd, IntPtr pgActionID, ref WINTRUST_DATA pWinTrustData);

    private static readonly IntPtr WINTRUST_ACTION_GENERIC_VERIFY_V2 = new IntPtr(unchecked((int)0xa0000003));

    public static bool ValidateDllSignature(string dllPath)
    {
        WINTRUST_FILE_INFO fileInfo = new WINTRUST_FILE_INFO
        {
            cbStruct = (uint)Marshal.SizeOf(typeof(WINTRUST_FILE_INFO)),
            pcwszFilePath = dllPath
        };

        WINTRUST_DATA trustData = new WINTRUST_DATA
        {
            cbStruct = (uint)Marshal.SizeOf(typeof(WINTRUST_DATA)),
            dwUIChoice = 2, // 不显示验证UI
            fdwRevocationChecks = 0, // 关闭吊销检查(适配离线)
            dwUnionChoice = 1, // 指定验证文件类型
            pFile = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINTRUST_FILE_INFO))),
            dwStateAction = 0, // 忽略状态缓存
            dwProvFlags = 0x10000 | 0x20000, // 适配离线环境的验证标志
            dwUIContext = 0
        };

        Marshal.StructureToPtr(fileInfo, trustData.pFile, false);
        uint verifyResult = WinVerifyTrust(IntPtr.Zero, WINTRUST_ACTION_GENERIC_VERIFY_V2, ref trustData);
        Marshal.FreeHGlobal(trustData.pFile);

        // 返回0表示签名验证通过
        return verifyResult == 0;
    }
}

// 使用示例
bool isDllValid = AuthenticodeChecker.ValidateDllSignature("path/To/The/Dll");

内容的提问来源于stack exchange,提问作者Rena821

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:04:51