July 24th, 2019

Reporting on Digitally Signed Files with PowerShell

Doctor Scripto
Scripter

Summary: Using the Get-AuthenticodeSignature cmdlet to show if a file is Digitally Signed

Q: Hey, Doctor Scripto!

I was curious, since many new files are Digitally signed with a certificate if there was an easy way to see the status of the Digital Signatures of many files easily?

—SH

A: Hello SH your good friend Doctor Scripto is here today to help you along.

One of the things which changed with PowerShell in version 3.0 was a beautiful little Cmdlet called Get-AuthenticodeSignature

This Cmdlets task was very simple, examine a file and show the properties of the Digital Certificate on a file. Here’s an example of it in action

A quick glance shows us the file has a Valid digital signature. If you would like to see more details you can pipe the results into Format-List

Visually this is a nice way of trying to determine if the content you downloaded is at least signed with a current certificate from a vendor.

I can even take a list of files, pipe them in to see their status!

However the Cmdlet does have a Snag. If I wish to take this information and try to Export it as a list to a CSV to report on a list of files, it produces some unexpected results.

Instead of seeing a nicely formatting CSV file in columns and perhaps the odd Object reference, it looks more like a regular text file

This had the good Doctor doing some head scratching. How could this be fixed? Something in the way the part of the object had parsed did not show up the way we wanted. I was expecting individual columns on data.

I could just hear myself shouting out, “This is a job for … Select-Object!”

First let’s see what was exposed using Get-Member to decide where the problem might be.

I could see a total of seven properties to view. The bool and string properties were probably straight forward and not causing an issue. System.Management.Automation as it was accessing a single property within itself was probably ok.   I could be wrong, but sometimes a good honest guest works.

But those X509Certificate2 objects? I foresaw them containing a lot of information such as Expiry, Issue, signatures. They could have been the problem.

A simple test I did was to Run the Get-AuthenticodeSignature and only take the ones I guessed were ok and output them to a CSV file.

Get-ChildItem c:\windows\notepad*.exe | Get-AuthenticodeSignature | ` Select-Object -Property Path,ISOSBinary,SignatureType,Status,StatusMessage | ` Export-CSV C:\report\Signature.csv -NoTypeInformation

This time the results were much nicer. So the challenge was to pull out the objects from WITHIN the object in X509Certificate2. Again a task designed for Select-Object and Get-Member.

The first we needed to do was to see the properties *IN* that X509Certificate2 object.

Now we can see a myriad of additional properties that were in that object. To obtain a property such as the SerialNumber, we need to leverage a feature of Select-Object called a “Calculated Property”. This feature has been around PowerShell for a VERY long time and is quite useful in these situations.

Get-ChildItem C:\Windows\notepad.exe | Get-AuthenticodeSignature | ` Select-Object -Property @{Name=’SignerSerialNumber’;Expression={($_.SignerCertificate.SerialNumber)}}

Using this in PowerShell produced the following result

SignerSerialNumber —————— 33000001C422B2F79B793DACB20000000001C4

A much more desirable output. At this point it was a matter of producing a Calculated Property for each of the individual items from the X509Certificate2 object.

Get-ChildItem C:\Windows\notepad.exe | Get-AuthenticodeSignature | ` Select-object -Property Path, Status,StatusMessage,SignatureType, ` @{Name=’SubjectName’;Expression={($_.SignerCertificate.Subject)}}, ` @{Name=’SubjectIssuer’;Expression={($_.SignerCertificate.Issuer)}}, ` @{Name=’SubjectSerialNumber’;Expression={($_.SignerCertificate.SerialNumber)}}, ` @{Name=’SubjectNotBefore’;Expression={($_.SignerCertificate.NotBefore)}}, ` @{Name=’SubjectNotAfter’;Expression={($_.SignerCertificate.NotAfter)}}, ` @{Name=’SubjectThumbprint’;Expression={($_.SignerCertificate.ThumbPrint)}}, ` @{Name=’TimeStamperName’;Expression={($_.SignerCertificate.Subject)}}, ` @{Name=’TimeStamperIssuer’;Expression={($_.SignerCertificate.Issuer)}}, ` @{Name=’TimeStamperSerialNumber’;Expression={($_.SignerCertificate.SerialNumber)}}, ` @{Name=’TimeStamperNotBefore’;Expression={($_.SignerCertificate.NotBefore)}}, ` @{Name=’TimeStamperNotAfter’;Expression={($_.SignerCertificate.NotAfter)}}, ` @{Name=’TimeStamperThumbprint’;Expression={($_.SignerCertificate.ThumbPrint)}}

With this we now had an object that would export directly to a CSV.

As a simple way to consume it, we could even write it up as a function.

Function Expand-AuthenticodeSignature($AuthenticodeSignature) { $AuthenticodeSignature | Select-object -Property Path, ` Status,StatusMessage,SignatureType, ` @{Name=’SubjectName’;Expression={($_.SignerCertificate.Subject)}}, ` @{Name=’SubjectIssuer’;Expression={($_.SignerCertificate.Issuer)}}, ` @{Name=’SubjectSerialNumber’;Expression={($_.SignerCertificate.SerialNumber)}}, ` @{Name=’SubjectNotBefore’;Expression={($_.SignerCertificate.NotBefore)}}, ` @{Name=’SubjectNotAfter’;Expression={($_.SignerCertificate.NotAfter)}}, ` @{Name=’SubjectThumbprint’;Expression={($_.SignerCertificate.ThumbPrint)}}, ` @{Name=’TimeStamperName’;Expression={($_.SignerCertificate.Subject)}}, ` @{Name=’TimeStamperIssuer’;Expression={($_.SignerCertificate.Issuer)}}, ` @{Name=’TimeStamperSerialNumber’;Expression={($_.SignerCertificate.SerialNumber)}}, ` @{Name=’TimeStamperNotBefore’;Expression={($_.SignerCertificate.NotBefore)}}, ` @{Name=’TimeStamperNotAfter’;Expression={($_.SignerCertificate.NotAfter)}}, ` @{Name=’TimeStamperThumbprint’;Expression={($_.SignerCertificate.ThumbPrint)}}}

Now that we have the data in a more consumable and exportable fashion. We can even grab a list of files with their Digital Certificate status

$List=Get-ChildItem C:\Windows\*.exe | Get-AuthenticodeSignature

….then produce the new output in a script with our function and Export it directly to a CSV file

Expand-AuthenticodeSignature -AuthenticodeSignature $List | Export-Csv C:\report\working.csv

As you can see, the results are much more useful.

SH that is all there is to seeing how to report on Digitally Signed files with Get-AuthenticodeSigntature

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Forum. See you tomorrow. Until then, peace.

Your good friend, Doctor Scripto

PowerShell, Doctor Scripto, Certificates, Sean Kearney

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • ethanwilliam404@gmail.com

    Great Article it its really informative and innovative keep us posted with new updates. its was really valuable. thanks a lot.