Threat Level: green Handler on Duty: Didier Stevens

SANS ISC: Digging into Authenticode Certificates - SANS Internet Storm Center SANS ISC InfoSec Forums

Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!
Digging into Authenticode Certificates

I was speaking with a client about securing desktop operating systems, and his immediate comment to me was "of course, we could limit execution to only signed code" as one of his first planned steps to restrict malware execution.  By "signed" he of course refers to authenticode signing, where a software author can "sign" their code with a trusted certificate, just like we use certificates to websites.  You commonly see certificates on .exe, .cab, .dll, .ocx, .xpi, and .ps1 files - really anything that can be executed can be signed.

I hear the "restrict to signed code" position a lot, and it does sound like a great plan to start restricting access to trusted code!  But how would that work in today's Windows 10?  So I decided to do some preliminary poking around ....

First, let's collect all exe, dll and ps1 files in c:\windows.  You'd think that this would look something like (while running as administrator):
$allfilez = Get-ChildItem C:\Windows -Recurse -ErrorAction SilentlyContinue

However, when you look at the resulting file count just for .exe's , this looks a tad low.  I turns out that this combination of switches on GCI just plain skips entire trees in c:\windows, "because permissions"
$f = $allfilez | Where-Object { ($_.extension.tolower() -eq '.exe') }

So, after some time trying to figure this out (and not getting to a better place on this), I fell back to the "dir" command (which I KNOW will work without any back-chat).  We'll collect just the exe, dll and ps1 files:

$filez = iex "cmd /c dir c:\windows\*.exe,c:\windows\*.dll,c:\windows\*.ps1 /s/b/a-d"
Note that this just collects the filenames (with paths), where "get-childitem" would collect way more information about each file.

Now, let's grab the authenticode certificates for each of these:
$certz = $filez | get-authenticodeSignature

Looking at what fields are in a certificate:
$certz | gm

   TypeName: System.Management.Automation.Signature

Name                   MemberType Definition                                                                                  
----                   ---------- ----------                                                                                  
Equals                 Method     bool Equals(System.Object obj)                                                              
GetHashCode            Method     int GetHashCode()                                                                           
GetType                Method     type GetType()                                                                              
ToString               Method     string ToString()                                                                           
IsOSBinary             Property   bool IsOSBinary {get;}                                                                      
Path                   Property   string Path {get;}                                                                          
SignatureType          Property   System.Management.Automation.SignatureType SignatureType {get;}                             
SignerCertificate      Property   System.Security.Cryptography.X509Certificates.X509Certificate2 SignerCertificate {get;}     
Status                 Property   System.Management.Automation.SignatureStatus Status {get;}                                  
StatusMessage          Property   string StatusMessage {get;}                                                                 
TimeStamperCertificate Property   System.Security.Cryptography.X509Certificates.X509Certificate2 TimeStamperCertificate {get;}

Or at the expanded certificate metadata for one file:
$certz[12] | fl

SignerCertificate      : [Subject]
                           CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
                           CN=Microsoft Windows Production PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
                         [Serial Number]
                         [Not Before]
                           8/11/2017 4:23:35 PM
                         [Not After]
                           8/11/2018 4:23:35 PM
TimeStamperCertificate : [Subject]
                           CN=Microsoft Time-Stamp Service, OU=nCipher DSE ESN:2137-37A0-4AAA, OU=AOC, O=Microsoft Corporation,
                         L=Redmond, S=Washington, C=US
                           CN=Microsoft Time-Stamp PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
                         [Serial Number]
                         [Not Before]
                           9/7/2016 1:56:56 PM
                         [Not After]
                           9/7/2018 1:56:56 PM
Status                 : Valid
StatusMessage          : Signature verified.
Path                   : C:\windows\write.exe
SignatureType          : Catalog
IsOSBinary             : True

Let's expand '$filez' to include our target files across all of c:, collect some 'information of interest' for each file, then poke at it some more with excel (because nothing spells patterns faster than a sorted list, a pivot table or few graphics) and sed (because my fingers still know sed faster than the equivalent powershell):

The final data collection script looks like this:
$filez = iex "cmd /c dir c:\*.exe,c:\*.dll,c:\*.ps1 /s/b/a-d"
$certz = $filez | get-authenticodeSignature
$certz | foreach {
 $cc = new-object -typename psobject -prop (@{'Path'=$_.Path; 'IsOSBinary'=$_.IsOSBinary; 'Status'=$_.Status;'SignatureType'=$_.SignatureType;'SignerIssuer'=$_.SignerCertificate.Issuer;'SignerThumbprint'=$_.SignerCertificate.Thumbprint;"TimeStampSig'=$_.TimeStamperCertificate.Issuer})
$certinfolist += $cc
$certinfolist | Export-Csv \temp\certz-all-of-c.csv

I'll focus on files in the c:\windows directory, plus the files that are part of MS Office (I'm running Office 2013 Pro on this laptop)

There are 6794 Unsigned files, just in c:\windows.  Just with a bit of poking, 127 of those files are easily associated with MS Office (the uniq filename contains the strings office, word, excel, powerpoint or visio)

Certs with the word "Microsoft" in the CN (with the file counts) include:
     62 CN=Microsoft Code Signing PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
   3766 CN=Microsoft Code Signing PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
     34 CN=Microsoft Code Signing PCA, OU=Copyright (c) 2000 Microsoft Corp., O=Microsoft Corporation, L=Redmond, S=Washington, C=US
      2 CN=Microsoft Development PCA 2014, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
      1 CN=Microsoft Digital Media Subordinate CA 2017 1
      1 CN=Microsoft Update Signing CA 2.1, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
    464 CN=Microsoft Windows Hardware Compatibility PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
     24 CN=Microsoft Windows Phone Production PCA 2012, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
  20895 CN=Microsoft Windows Production PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
    331 CN=Microsoft Windows Third Party Component CA 2012, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
     10 CN=Microsoft Windows Third Party Component CA 2014, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
      7 CN=Microsoft Windows Verification Intermediate PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
     46 CN=Microsoft Windows Verification PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
     42 CN=MSIT Test CodeSign CA 6, DC=redmond, DC=corp, DC=microsoft, DC=com

Those all look pretty good, though the "Windows Phone" CA does stand out a bit.  hmmm - except for that last one - - did Microsoft really mean to include executables signed based on a test CA?  Looking at one of these files, we see that it's an internal-use-only CA, untrusted by production Windows:

Taking a closer look at this, we see that they're all part of "Microsoft Office Hub" - most of us would see this as an explicit app mainly on the phone platforms (which maybe also explains that Windows Phone CA), but it's part of the Windows version of Office also.

Let's pull files using that certificate by the signer thumbprint:
$certinfolist | Where-Object { $_.SignerThumbprint -eq "E657C209642F2585756FA612997DA548C82EBFEB" } |  select Path

C:\Program Files\WindowsApps\Microsoft.MicrosoftOfficeHub_17.9328.1700.0_x64__8wekyb3d8bbwe\mso20imm.dll
C:\Program Files\WindowsApps\Microsoft.MicrosoftOfficeHub_17.9328.1700.0_x64__8wekyb3d8bbwe\mso30imm.dll
C:\Program Files\WindowsApps\Microsoft.MicrosoftOfficeHub_17.9328.1700.0_x64__8wekyb3d8bbwe\mso40uiimm.dll
C:\Program Files\WindowsApps\Microsoft.MicrosoftOfficeHub_17.9328.1700.0_x64__8wekyb3d8bbwe\mso50imm.dll

Using the same method, we find that all of the files signed from the "Windows Phone" CA are located in: C:\Program Files\WindowsApps\Microsoft.VCLibs.140.00_14.0.24605.0_x86__8wekyb3d8bbwe\

There are a large number of files (6087) that have an authenticode status "UnknownError".  Of these 66 are actually signed with a CA listed.  Of the 66, 42 of those are in that OfficeHub directory.  So there's more than one problem with that component of Office.

When I looked a bit closer at unsigned files, I found file and directory names that included strings like:
(of course there are lots more)

Most of the strings in this list seem to cover authentication and authorization functions, these would seem important enough to sign, at least from my perspective?

Of the 132 files that have the string "hyperv" in the name or path, most (113) are unsigned.  This struck me as ironic as it gets, since that subsystem is integral to the Device Guard feature.  You know, Device Guard, the feature you use to restrict execution to only signed executable files?  More than a bit of irony there....

Want some more irony?  The Host Guardian service is used (in Microsoft's words) to "provide Attestation and Key Protection services that enable Hyper-V to run Shielded virtual machines."  In other words, HGS uses a virtual TPM module to support BitLocker encryption of VMs.  Neat, eh?  And, you guessed it, 15 "hostguard" executable files are unsigned.

Anyway, long story short - - yes, restricting execution to only signed executables is a terrific goal.  Can you do this right out of the box on Windows 10? - short answer is "expect some bumps in the road" - even Windows and MS Office are not consistently signed.

I'll take this a bit further in a future post, I'll try applying that restriction to my laptop and see how things go.  
If you've already gone down this path, by all means post any war stories to our comment section.
Or if you've gotten around that get-childitem issue in c:\windows, I think an answer or a better work-around there would be of interest to lots of people as well !

Rob VandenBrink

Rob VandenBrink

469 Posts
ISC Handler
Hi Rob,

Indeed, allowing execution of only signed files is a real challenge, especially for the myriad of .Net-based applications that perform just-in-time compilation of DLL's using csc.exe and mscorsvw.exe. The former are typically just 'read', whereas the latter (typically "") are loaded for execution by apps like MS Exchange, etc. These cannot be signed readily because they are compiled at application installation or startup time on the machine itself. Blocking these WILL break key functionality of these applications. However, with attackers also leveraging csc.exe and mscorsvw.exe to build tools on a compromised box, it's very difficult to identify which application actually called csc/mscorsvw and thus know if the DLL can be trusted or not.
I actually have been diving into the preventative side of infosec as of late. It seems this game I play while being a multiplayer online game is full of deadcode that needs a clean up. The developer did recompile with the new MS guard ready libraries or what have you after the latest win x arrived. This was mainly due to a publicized RCE that people were exploiting, and that said rce based on rop gadgets and stack pivoting got me trying all kinds of new things like... all the app guards, system guards, hvci system protection, Norton, malware bytes, Kaspersky, what have you. I even tried tinkering around with the successor to ms emet, and looking at moving my system to a whitelist firewall.

I digress, after all that research, I have come to a conclusion, windows, is just like all the other major software out there that is sold for ad revenue, profit, or market positioning of other proprietary software. It is super sloppily put together, and an on going melee of God knows how many coders or dev teams, not to mention the accountants making sure they push applications you have to PowerShell to get removed like the xbox live bs

You mentioned the windows phone, and look at how well that shit is doing amiright?

If you are going to white list anything in Windows either your firewall or authorized executables it is going to be a pain in the ass.

Justtrying alone to get windows to update on a whitelist firewall is a giant nightmare, although I have to say I'm quite fond of some of the MS progs like the adv firewall...

Making me have to spend money on pro so my state of the art dell laptop can install the hypervisor and have access to the group policy editor... not so fond of.

50 Posts Posts

Sign Up for Free or Log In to start participating in the conversation!