How to check if a file is signed in C#? [closed]
Asked Answered
S

1

23

I'm writing a program that need to load a few other files. is there a way to check if those files are signed or not, without right clicking them and check? I use 300-400 files that change every few days I need to check DLL/EXE/CAB/OCX/MSI (and maybe also vbs/js)

is there a way to check it?

Sevenfold answered 6/7, 2011 at 12:26 Comment(13)
Unless you're having a specific problem with this, help has a chance to be scarce other than some referencing links that you could potentially have found personally - please let us know what you have attempted so far.Zaslow
@Tigran: Code signing. msdn.microsoft.com/en-us/library/ms537361(v=vs.85).aspxBurhans
possible duplicate of how to check if a file has a digital signatureBurhans
Ok, digital signature stuff, thank you...Carminacarminative
I don't agree that this question is not a real question or not constructive. Closers should read what he is asking for.. it is code signing. Right-clicking and checking the properties of the file is the manual way to see if a file is signed. I do agree that it is a duplicate and I posted the link.Burhans
Check this post, I think this is what you're searching for: #667517Carminacarminative
@Mr. Disappointment: He is asking for code signing/digital certificates and how to check if a file is signed.Burhans
@0A0D My point still stands (only now emphasised, given the provided answer.)Zaslow
@Mr. Disappointment: He obviously does not know how to do it or he wouldn't have asked.Burhans
Hmm, if this is not about digital signature, what is this question about so?Carminacarminative
it is about digital signature. does 'Assembly.LoadFile("").IsFullyTrusted()' mean it is signed?Sevenfold
This question was closed for no good reason, but I posted a relevant solution here: https://mcmap.net/q/329329/-how-to-check-if-a-file-has-a-digital-signatureDarn
See this crookm.com/journal/2019/verify-signed-executables-in-dotnet/…Giuditta
C
75

Assuming you want to check if a file is Authenticode signed and that the certificate is trusted you can pinvoke to WinVerifyTrust in Wintrust.dll.

Below is a wrapper (more or less reproduced from here) that can be called as follows:

AuthenticodeTools.IsTrusted(@"path\to\some\signed\file.exe")

Where AuthenticodeTools is defined as follows:

internal static class AuthenticodeTools
{
    [DllImport("Wintrust.dll", PreserveSig = true, SetLastError = false)]
    private static extern uint WinVerifyTrust(IntPtr hWnd, IntPtr pgActionID, IntPtr pWinTrustData);
    private static uint WinVerifyTrust(string fileName)
    {

        Guid wintrust_action_generic_verify_v2 = new Guid("{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}");
        uint result=0;
        using (WINTRUST_FILE_INFO fileInfo = new WINTRUST_FILE_INFO(fileName,
                                                                    Guid.Empty))
        using (UnmanagedPointer guidPtr = new UnmanagedPointer(Marshal.AllocHGlobal(Marshal.SizeOf(typeof (Guid))),
                                                               AllocMethod.HGlobal))
        using (UnmanagedPointer wvtDataPtr = new UnmanagedPointer(Marshal.AllocHGlobal(Marshal.SizeOf(typeof (WINTRUST_DATA))),
                                                                  AllocMethod.HGlobal))
        {
            WINTRUST_DATA data = new WINTRUST_DATA(fileInfo);
            IntPtr pGuid = guidPtr;
            IntPtr pData = wvtDataPtr;
            Marshal.StructureToPtr(wintrust_action_generic_verify_v2,
                                   pGuid,
                                   true);
            Marshal.StructureToPtr(data,
                                   pData,
                                   true);
            result = WinVerifyTrust(IntPtr.Zero,
                                    pGuid,
                                    pData);
            
        }
        return result;

    }
    public static bool IsTrusted(string fileName)
    {
        return WinVerifyTrust(fileName) == 0;
    }


}

internal struct WINTRUST_FILE_INFO : IDisposable
{

    public WINTRUST_FILE_INFO(string fileName, Guid subject)
    {

        cbStruct = (uint)Marshal.SizeOf(typeof(WINTRUST_FILE_INFO));

        pcwszFilePath = fileName;



        if (subject != Guid.Empty)
        {

            pgKnownSubject = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));

            Marshal.StructureToPtr(subject, pgKnownSubject, true);

        }

        else
        {

            pgKnownSubject = IntPtr.Zero;

        }

        hFile = IntPtr.Zero;

    }

    public uint cbStruct;

    [MarshalAs(UnmanagedType.LPTStr)]

    public string pcwszFilePath;

    public IntPtr hFile;

    public IntPtr pgKnownSubject;



    #region IDisposable Members



    public void Dispose()
    {

        Dispose(true);

    }



    private void Dispose(bool disposing)
    {

        if (pgKnownSubject != IntPtr.Zero)
        {

            Marshal.DestroyStructure(this.pgKnownSubject, typeof(Guid));

            Marshal.FreeHGlobal(this.pgKnownSubject);

        }

    }



    #endregion

}

enum AllocMethod
{
    HGlobal,
    CoTaskMem
};
enum UnionChoice
{
    File = 1,
    Catalog,
    Blob,
    Signer,
    Cert
};
enum UiChoice
{
    All = 1,
    NoUI,
    NoBad,
    NoGood
};
enum RevocationCheckFlags
{
    None = 0,
    WholeChain
};
enum StateAction
{
    Ignore = 0,
    Verify,
    Close,
    AutoCache,
    AutoCacheFlush
};
enum TrustProviderFlags
{
    UseIE4Trust = 1,
    NoIE4Chain = 2,
    NoPolicyUsage = 4,
    RevocationCheckNone = 16,
    RevocationCheckEndCert = 32,
    RevocationCheckChain = 64,
    RecovationCheckChainExcludeRoot = 128,
    Safer = 256,
    HashOnly = 512,
    UseDefaultOSVerCheck = 1024,
    LifetimeSigning = 2048
};
enum UIContext
{
    Execute = 0,
    Install
};

[StructLayout(LayoutKind.Sequential)]

internal struct WINTRUST_DATA : IDisposable
{

    public WINTRUST_DATA(WINTRUST_FILE_INFO fileInfo)
    {

        this.cbStruct = (uint)Marshal.SizeOf(typeof(WINTRUST_DATA));

        pInfoStruct = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINTRUST_FILE_INFO)));

        Marshal.StructureToPtr(fileInfo, pInfoStruct, false);

        this.dwUnionChoice = UnionChoice.File;



        pPolicyCallbackData = IntPtr.Zero;

        pSIPCallbackData = IntPtr.Zero;



        dwUIChoice = UiChoice.NoUI;

        fdwRevocationChecks = RevocationCheckFlags.None;

        dwStateAction = StateAction.Ignore;

        hWVTStateData = IntPtr.Zero;

        pwszURLReference = IntPtr.Zero;

        dwProvFlags = TrustProviderFlags.Safer;



        dwUIContext = UIContext.Execute;

    }



    public uint cbStruct;

    public IntPtr pPolicyCallbackData;

    public IntPtr pSIPCallbackData;

    public UiChoice dwUIChoice;

    public RevocationCheckFlags fdwRevocationChecks;

    public UnionChoice dwUnionChoice;

    public IntPtr pInfoStruct;

    public StateAction dwStateAction;

    public IntPtr hWVTStateData;

    private IntPtr pwszURLReference;

    public TrustProviderFlags dwProvFlags;

    public UIContext dwUIContext;



    #region IDisposable Members



    public void Dispose()
    {

        Dispose(true);

    }



    private void Dispose(bool disposing)
    {

        if (dwUnionChoice == UnionChoice.File)
        {

            WINTRUST_FILE_INFO info = new WINTRUST_FILE_INFO();

            Marshal.PtrToStructure(pInfoStruct, info);

            info.Dispose();

            Marshal.DestroyStructure(pInfoStruct, typeof(WINTRUST_FILE_INFO));

        }



        Marshal.FreeHGlobal(pInfoStruct);

    }



    #endregion

}

internal sealed class UnmanagedPointer : IDisposable
{

    private IntPtr m_ptr;

    private AllocMethod m_meth;

    internal UnmanagedPointer(IntPtr ptr, AllocMethod method)
    {

        m_meth = method;

        m_ptr = ptr;

    }



    ~UnmanagedPointer()
    {

        Dispose(false);

    }



    #region IDisposable Members

    private void Dispose(bool disposing)
    {

        if (m_ptr != IntPtr.Zero)
        {

            if (m_meth == AllocMethod.HGlobal)
            {

                Marshal.FreeHGlobal(m_ptr);

            }

            else if (m_meth == AllocMethod.CoTaskMem)
            {

                Marshal.FreeCoTaskMem(m_ptr);

            }

            m_ptr = IntPtr.Zero;

        }



        if (disposing)
        {

            GC.SuppressFinalize(this);

        }

    }



    public void Dispose()
    {

        Dispose(true);

    }



    #endregion



    public static implicit operator IntPtr(UnmanagedPointer ptr)
    {

        return ptr.m_ptr;

    }

}
Clarke answered 6/7, 2011 at 13:16 Comment(4)
Also see pinvoke.net/default.aspx/wintrust.winverifytrust for other interop notes about the WinVerifyTrust function.Freedom
FWIW there is an excellent purely .NET library for this now github.com/vcsjones/AuthenticodeExaminerSoul
@VivekRathod Nice find, but I take exception to the term "purely .NET library". "The library is a wrapper around native Windows APIs that provide this functionality."Clarke
@Clarke agreed - I used the term rather incorrectly as you pointed out.Soul

© 2022 - 2024 — McMap. All rights reserved.