|
| 1 | +--- |
| 2 | +description: Notes about the use of Authenticode signing of executable files |
| 3 | +ms.assetid: df71ff3b-2bed-4089-bbf7-2d2509182f92 |
| 4 | +title: Best Practices for the Security APIs |
| 5 | +ms.topic: best-practice |
| 6 | +ms.date: 07/24/2025 |
| 7 | +--- |
| 8 | +# Understanding Executable File Signing |
| 9 | +In Windows, a file’s digital signature may be stored in either a catalog signature, an embedded signature, or both. Catalog Signatures are |
| 10 | +files that contain signatures for one or more other files, while embedded signatures are stored in file-format-specific structures that allow |
| 11 | +embedding a signature within the bytes of the file itself. For example, the Windows [Portable Executable (PE) File Format](/windows/win32/debug/pe-format) |
| 12 | +allows embedding a Certificate Table in the Data directory section; the signature data contains signed hashes of the code components of the file. |
| 13 | + |
| 14 | +## Signature Calculations |
| 15 | +The specific bytes protected by a file’s signature vary based upon the Subject Interface Package (SIP) used to generate and later verify a |
| 16 | +signature for a given file type. Windows’ signing infrastructure is extensible, allowing third-parties to [register additional SIPs](/windows/win32/api/mssip/) to support |
| 17 | +signing of additional file types beyond the signable formats included by Windows. |
| 18 | + |
| 19 | +In the case of file types for which no SIP is installed, the entire content of the file may be hashed (as in the case of a text file) and |
| 20 | +stored in a Catalog file. |
| 21 | + |
| 22 | +For filetypes that are supported by a SIP, like Windows Portable Executable (PE) files, the SIP may exclude some sections of the file from |
| 23 | +the hash calculation, and may store the resulting signature within the file itself or within a separate Catalog file. In a Windows PE file, |
| 24 | +digital signatures can be "embedded" in a location specified by the Certificate Table entry in Optional Header Data Directories. When |
| 25 | +Authenticode is used to sign a Windows PE file, the algorithm that calculates the file's hash value excludes certain PE fields. When embedding |
| 26 | +the signature in the file, the signing process can modify these fields without affecting the file's hash value. |
| 27 | + |
| 28 | +After the to-be-signed content’s hash is generated, it is signed using a signing certificate, allowing future validation that the hash is |
| 29 | +unmodified and that the hashed portion of the file's content remains unchanged since signing. |
| 30 | + |
| 31 | +## Security Implications |
| 32 | +The Software Publisher Trust Provider SIP for PE files hashes the executable content of the file, but necessarily omits the file’s checksum |
| 33 | +(which changes when a signature is embedded) and the Certificate Table directory (which is populated by the file’s signatures during signing). |
| 34 | + |
| 35 | +The fact that the Software Publisher Trust Provider SIP does not hash all of the bytes of the file (i.e. it’s not a “flat file hash”) when |
| 36 | +calculating the signature means that it is possible to embed additional content into a signed PE file without breaking its signature. For |
| 37 | +example, some services will [embed metadata into already-signed](/archive/blogs/ieinternals/caveats-for-authenticode-code-signing) software installers, |
| 38 | +either by storing the metadata in an PKCS#7 padding area in the WIN_CERTIFICATE structure, by adding unvalidated attributes to a signature, |
| 39 | +or by adding an extra signature signed with a self-signed certificate. Each of these techniques introduces risk. While the injected content |
| 40 | +is not directly executable, a vulnerable application might incorrectly expect it to be trustworthy (because the rest of the file is correctly |
| 41 | +signed) and act upon it. |
| 42 | + |
| 43 | +This unsigned-embedding capability was exploited in attacks dating back to 2013, leading to the introduction of the [`EnableCertPaddingCheck`](/security-updates/SecurityAdvisories/2014/2915720) |
| 44 | +registry override introduced for CVE-2013-3900. When the EnableCertPaddingCheck DWORD is present and set to 1, |
| 45 | +[WinVerifyTrust](/windows/win32/api/wintrust/nf-wintrust-winverifytrust) will validate that all PKCS#7 padding bytes in the WIN_CERTIFICATE |
| 46 | +structure are set to 0. If other values are found, the SIP will deem the signature invalid. |
| 47 | + |
| 48 | +## Notes on Catalog Signatures |
| 49 | +Catalog signature verification does not support every SIP. When verifying a Catalog-signed file, the SIP is loaded only for signing |
| 50 | +and validating the PE and CAB file types. Other file types are signed and validated using a flat file hash. |
| 51 | + |
| 52 | +Enabling the EnableCertPaddingCheck registry key does not impact WinVerifyTrust’s evaluation of a Catalog-signed PE file. If an executable |
| 53 | +file is Catalog-signed, the embedded signature is not checked and thus the certificate padding is not evaluated for unexpected content |
| 54 | +even when the EnableCertPaddingCheck registry key is set. |
0 commit comments