Why Isn’t PowerShell.exe Authenticode Signed?

This question came up on our internal forum last week, and Jeffrey, knowing of my sharp wit and keen hand for prose, asked me to blog about the answer. So here goes:

It is Authenticode signed. Just in a special way.

The Windows PowerShell update packages each contain a catalog (.cat) file, which has a list of files in the package and a hash of each file. Since the .cat file is Authenticode signed, the chain of trust can be verified by checking the signature on the .cat file, then comparing the hash the catalog lists for PowerShell.exe to a newly computed hash of PowerShell.exe. If the signature is valid and the hashes match, your trust of the signature on the catalog file can be extended to PowerShell.exe.

If you have a copy of PowerShell.exe (or any of the files distributed in the update) and you want to verify the signing manually, you can use ‘signtool.exe’, which is part of the .Net 2.0 SDK. Once you have signtool.exe, locate the catalog file for the update, which is named KB926139.cat for Server 2003 and XP, or KB928439.cat for Vista and is installed under the Windows directory. When you’ve got all three files, run the tool like this:

signtool verify /c KB926139.CAT powershell.exe

For valid files, you should see results like this:

If the file has been modified by hackers, viruses, code coverage instrumentation, xmodem rounding, or by someone appending the word “garbage” to it for demonstration purposes, the newly computed hash won’t match the one in the catalog, and you’ll see output like this:

If you want to verify the signature programmatically from a script, signtool.exe behaves well and will set $LastExitCode (or %ERRORLEVEL%) to 0 on success or 1 on failure.

Catalog signing doesn’t help with Software Restriction Policies, though. I have a number of large clients who use SRP to determine what software is permitted to run on various machines; while they take take a hash of PowerShell.exe, they prefer to have signed executables since SRP can simply allow them to "permit all apps signed with a Microsoft-owned certificate," meaning they can universally allow MS stuff (Office, etc) without having to individually "allow" each application. Please consider individually signing PowerShell.exe in the future!