Developers are usually signing their code in order to provide assurance to users that their software is trusted and it has not been modified in a malicious way. This is done with the use of digital signatures. Therefore signing code is a method to verify the authenticity and integrity of a file.
Threat hunters and blue teams usually check the digital signature of a binary in order to perform an initial check and determine whether or not it should be considered as suspicious. Microsoft defensive technologies such as AppLocker and Device Guard support the use of rules that allow only executables and PowerShell scripts that are coming from trusted publishers and are digitally signed to be executed on the system. This verification is performed through the use of certificates.
Validation of the digital signature can be performed by invoking the Get-AuthenticodeSignature via PowerShell and by using SigCheck utility from Sysinternals.

Matt Graeber in his keynote talk for DerbyCon 2017 described the process of how to execute unsigned code on a system that is lockdown by a device guard policy by performing a signature verification attack.
Digital Certificates
In modern windows operating systems code signing technology is used to assist users to recognize trusted binaries from untrusted. Native binaries are signed through the use of digital certificates which contain information about the publisher, the private key which is embedded and the public key.
The authenticode signature can be used to segregate signed PowerShell scripts and binaries from unsigned.

The certificate of PowerShell scripts can be hijacked easily by copying the signature block of a digitally signed Microsoft PowerShell script and applying it into a PowerShell script that has not been signed. The following script is part of the Windows ecosystem and has already a Microsoft signature.
C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ISE\ise.psm1

The CryptSIPDllGetSignedDataMsg contains a registry key which handles the default PowerShell SIP (pwrshsip.dll) and the digital signatures for native Microsoft PowerShell scripts.
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{603BCC1F-4B59-4E08-B724-D2C6297EF351}
The DLL and the FuncName values of this key needs to be replaced with a custom SIP and with the GetLegitMSSignature function. Matt Graeber created a custom SIP (Subject Interface Package) which can be compiled and used in order unsigned PowerShell scripts to get a legitimate Microsoft signature. A compiled version of this DLL can be found on GitHub.
DLL - C:\Users\User\MySIP.dll FuncName - GetLegitMSSignature

The legitimate digital signature will be applied to the script and this can be verified by invoking again the Get-AuthenticodeSignature module from a PowerShell console.

However validation of the digital signature will fail as the authenticode hash will be different.
Various tools can be used in order to hijack a certificate from a trusted binary and use it to a non-legitimate binary.
python sigthief.py -i consent.exe -t mimikatz.exe -o signed-mimikatz.exe

SigPirate.exe -s consent.exe -d mimikatz.exe -o katz.exe -a

The consent file is an executable which is part of Windows operating system and therefore it is digitally signed by Microsoft. The binary will appear to have a digital signature of Microsoft.

As previously the digital signature will fail to validate.
Bypassing Signature Validation
The Authenticode is a Microsoft code signing technology that can be used by blue teams to identify the identity of a publisher through the digital certificate and to verify that the binary has not been tampered since it performs a validation of the digital signature hash.
Even if a trusted certificate has been stolen and applied to a malicious binary the digital signature will still be invalid as the authenticode hash will not match. An invalid authenticode hash is a strong indication that the binary is not legitimate. Executing the Get-AuthenticodeSignature from a PowerShell console against a binary that has a trusted certificate will produce a HashMismatch error.

The executable code is signed by a private key of the digital certificate. The public key is embedded in the certificate itself. Since the private key is not known it will always fail the hash validation process as the hash will be different.
Therefore the digital signature validation mechanism needs to be weakened through registry modifications. Matt Graeber discovered in which location in the registry the validation of the hash is performed and how. The CryptSIPDllVerifyIndirectData component handles the digital signature validation for PowerShell scripts and for portable executables.
Implementation of the hash validation of the digital signatures is performed via the following registry keys:
- {603BCC1F-4B59-4E08-B724-D2C6297EF351} // Hash Validation for PowerShell Scripts
- {C689AAB8-8E78-11D0-8C47-00C04FC295EE} // Hash Validation for Portable Executables
These keys exists in the following registry locations:
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{603BCC1F-4B59-4E08-B724-D2C6297EF351} HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}
A legitimate Microsoft DLL file needs to be used because it should be already signed with the same private key. The function name DbgUiContinue is used because it accepts two parameters like the original function that is replacing and returns TRUE if the function CryptSIPDllVerifyIndirectData succeeds.
DLL - C:\Windows\System32\ntdll.dll FuncName - DbgUiContinue

Starting a new PowerShell process will complete the bypass of the hash validation. The malicious binary will appear signed and with a valid Microsoft signature.


Matt Graeber did the initially discovery of this bypass and it is explained in detail in his paper about Subverting Trust in Windows. He released also a PowerShell script which can be used to automate the signature verification attack.
The script will target the two registry keys where the hash validation of the digital signatures for PowerShell scripts and portable executables is performed.

The following registry values will be modified automatically with the required values in order to bypass the hash validation.

Running the PowerShell script will perform the bypass.
powershell.exe -noexit -file C:\Python34\SignatureVerificationAttack.ps1

Executing the Get-AuthenticodeSignature PowerShell module will result of a valid digital signature hash.

Metadata
Some antivirus companies are relying on the digital signatures and metadata in order to identify malicious files. Therefore antivirus detection rate against a non-legitimate binary that is using a valid certificate and metadata from a trusted entity will be decreased.
MetaTwin is a PowerShell based script that can copy metadata details from a file to another binary automatically.
PS C:\metatwin> Import-Module .\metatwin.ps1 PS C:\metatwin> Invoke-MetaTwin -Source C:\Windows\System32\netcfgx.dll -Target .\mimikatz.exe -Sign

On top of that it can steal the digital signature from a Microsoft file since it is using SigThief to perform this task.

The final executable will have metadata details and a digital signature from Microsoft.

This can be verified by checking the details tab from the file properties.

If the system has been already modified via the registry in order to bypass the hash validation of the digital signature the malicious binary will look like it is signed from a trusted entity like Microsoft.

Conclusion
Hijacking a legitimate digital signature and bypassing the hash validation mechanism of Windows can be used by red teams to blend malicious binaries and PowerShell scripts with the native operating system files in order to evade detection and bypass device guard.In a summary:
- Administrator Access is required to conduct this attack
- Digitally signed executables will not appear in Autoruns default view
- Antivirus detection rate is lower for digitally signed code
Blue teams can perform the following two steps as a quick way to determine if digital signature hijack attack has been occurred on the system.
- Verify the validity of the digital signature hash with Get-AuthenticodeSignature
- Review the following registry keys and values
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{603BCC1F-4B59-4E08-B724-D2C6297EF351} DLL - C:\Windows\System32\WindowsPowerShell\v1.0\pwrshsip.dll FuncName - PsGetSignature HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{C689AAB8-8E78-11D0-8C47-00C04FC295EE} DLL - C:\Windows\System32\ntdll.dll FuncName - CryptSIPGetSignedDataMsg HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{603BCC1F-4B59-4E08-B724-D2C6297EF351} DLL - C:\Windows\System32\WindowsPowerShell\v1.0\pwrshsip.dll FuncName - PsVerifyHash HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE} DLL - C:\Windows\System32\WINTRUST.DLL FuncName - CryptSIPVerifyIndirectData
References
- https://github.com/secretsquirrel/SigThief
- https://github.com/xorrior/Random-CSharpTools/tree/master/SigPirate
- https://specterops.io/assets/resources/SpecterOps_Subverting_Trust_in_Windows.pdf
- https://github.com/minisllc/metatwin
- https://github.com/mattifestation/PoCSubjectInterfacePackage
- https://github.com/netbiosX/Digital-Signature-Hijack
- https://github.com/mstefanowich/FileSignatureHijack
- http://www.exploit-monday.com/2017/08/application-of-authenticode-signatures.html
- https://gist.github.com/mattifestation/439720e2379f4bc93f0ed3ce88814b5b
- https://docs.microsoft.com/en-us/sysinternals/downloads/sigcheck
thankyou so much for writing such amazing an article. this has helped a lot. it has provided a good piece of information on digital signatures and digital certificates. keep writing. hope to read many such articles in future as well. keep sharing.
Valuable and helpful advice. Thanks!