Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get .dll or .exe files digital signer certificate info even if the certificate expired

Tags:

c#

.net

I'm using C# to check some .exe and .dll file digital certificates.

Assembly asm = Assembly.LoadFrom(assembly);
                
Module module = asm.GetModules().First();
System.Security.Cryptography.X509Certificates.X509Certificate certificate = module.GetSignerCertificate();
// it will null if the certificate time expired
if (certificate != null && certificate.Subject.Contains("Company Name"))
{
   Console.Write("success");
}
else
{
   Console.Write("failed");
}

If the certificate time is expired or local time is modified to after certificate time, module.GetSignerCertificate() returns null.

I just want to check that the assembly has a digital certificate and company name, I don't care about expiration. Is there another way, or can I modify my current code to not return null?

like image 267
qakmak Avatar asked Nov 15 '25 09:11

qakmak


2 Answers

This code does work well in my case, including expired certificate case.

using System.Security.Cryptography.X509Certificates;
...
// "assembly" is a string of full path for .exe or .dll.
var cert = X509Certificate.CreateFromSignedFile(assembly);
like image 159
jsakamoto Avatar answered Nov 17 '25 23:11

jsakamoto


The module is incorrectly signed. A properly signed module includes the timestamp when the module was signed. The validation rule dictates that the certificate should had been valid at the moment of signing (this, at the timestamp). Read this answer here https://stackoverflow.com/a/3428386/105929 for more details.

If this is your own module, then the best action is to modify your release sign-off to include a timestamp in the signature. Read Time Stamping Authenticode Signatures to understand how to do it (time stamping involves a URL service provided by your certificate CA). Also read Everything you need to know about Authenticode Code Signing.

As to your question: if you look at module.cs reference code, you'll see that the implementation is native and not much you can do about it to modify it:

    [System.Security.SecurityCritical]  // auto-generated
    [ResourceExposure(ResourceScope.None)]
    [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
    [SuppressUnmanagedCodeSecurity]
    static private extern void GetSignerCertificate(RuntimeModule module, ObjectHandleOnStack retData);

You could instead use the signtool.exe verify command, afaik it has options to display all certificates, including expired ones on modules lacking a proper timestamp.

The module is correct. Because before it expired, it can use very well. not get null. after it expired, or I change my system time. it will get null

This can easily be proven to be incorrect. Find an old correctly signed assembly on your machine, one distributed by a serious vendor that knows what is doing. Eg. I found this on my machine: c:\Program Files (x86)\Microsoft SQL Server\100\Setup Bootstrap\Release\x64\Microsoft.AnalysisServices.DLL. Look at the Digital Signature properties:

enter image description here

Do note the signature timestamp (20110922) and the certificate expiration (20120521).

Write a small app to get the cert using CLR API:

    static void Main(string[] args)
    {
        Assembly asm = Assembly.LoadFile(@"c:\Program Files (x86)\Microsoft SQL Server\100\Setup Bootstrap\Release\x64\Microsoft.AnalysisServices.DLL");
        Module m = asm.GetModules()[0];

        var cert = m.GetSignerCertificate();

        Console.WriteLine("{0}", cert);
    }

Is the certificate found? Yes. Is the certificate expired? Yes. Is the module properly signed, using a timestmap? Yes.

QED

like image 27
Remus Rusanu Avatar answered Nov 18 '25 01:11

Remus Rusanu