Friday 30 March 2012

Digitally signing Delphi executables

 Background

From Windows XP Service Pack 2 onwards, any application downloaded with a mainstream web browser (Internet Explorer, Firefox, Opera) will display a Security Warning dialog when executed.




Zone Identifier

The warning dialog is shown when an Authenticode-compliant* download tool writes an Alternative Data Stream (so the the NTFS file system must be in use) for a binary file using the IAttachmentExecute interface
(http://msdn.microsoft.com/en-us/library/windows/desktop/bb776297%28v=vs.85%29.aspx).

The Save method of this interface is used to create a stream called “Zone.Identifier” and writes to it the values:

[ZoneTransfer]
ZoneID=3

– “3” indicating an Internet download source.

References:

http://bit.ly/GUqsok
http://bit.ly/HaCR0Y
http://bit.ly/GROWtT

A digitally signed application will be identified by its “Publisher” – usually a company name – and this will be listed towards the top of the dialog.
*Microsoft's “Introduction to Code Signing”
http://msdn.microsoft.com/en-us/library/ms537361%28VS.85%29.aspx

In the case of an unsigned application, Windows will automatically apply the disconcerting label “The publisher could not be verified. Are you sure you want to run this software?”, and “Unknown Publisher” in place of a company name.

 Executing an unsigned application


Running a signed application


From Windows Vista onwards (when User Account Control is enabled), an additional dialog is shown when Windows detects execution of an “Installer” under the following conditions:

Installer Detection only applies to:

  • 32 bit executables
  • Applications without a requestedExecutionLevel
  • Interactive processes running as a Standard User with UAC enabled

Before a 32 bit process is created, the following attributes are checked to determine whether it is an installer:

  • Filename includes keywords such as "install," "setup," and "update."
  • Keywords in the following Versioning Resource fields: Vendor, Company Name, Product Name, File Description, Original Filename, Internal Name, and Export Name.
  • Keywords in the side-by-side application manifest embedded in the executable.
  • Keywords in specific StringTable entries linked in the executable.
  • Key attributes in the resource file data linked in the executable.
  • Targeted sequences of bytes within the executable.

Note: The keywords and sequences of bytes were derived from common characteristics observed from various installer technologies

Reference: http://msdn.microsoft.com/en-us/library/aa905330.aspx

Again, a signed “Installer” will be identified by a company name as the “Verified publisher” of the application, and the dialog colored with prosaic hues. An unsigned “Installer” will list the Publisher as “Unknown” and be decorated with amber “hazard” colouring.

Running an unsigned "installer"


Running a signed "installer" 

This is all part of Microsoft's system for securing users from potentially malicious software where origin and integrity cannot be tested and confirmed (with a substantial recurring financial cost to software authors for participating in the system).

Newer versions of Visual Studio bundle all of the Microsoft tools necessary for digitally signing a binary file with that programming environment.
Delphi developers are required to source them elsewhere.


Getting the tools

For the purposes of this article, we're going to be generating our own private key and digital certificate for signing executables. Links at the end of the article expound upon these same ideas, detailing the steps involved in acquiring a certificate from a recognised Certificate Authority (CA).

There are limitations to a self-created certificate; as an individual you are not a part of the “chain of trust” that exists between the various issuing organisations, and as a result, any binary file signed with the certificate will not be validated by Windows (the “Unknown Publisher” message will still be shown).
However, it can be a useful for internal testing, or for preparing your build processes in anticipation of adding a CA-sourced certificate at some future date.

To generate our private key and signing certificate, four tools are needed:

makecert.exe
Cert2Spc.exe
pvkimprt.exe
signtool.exe

...and an additional DLL file, “capicom.dll”.

There are various ways of obtaining them (they used to be included in the .NET SDK, but this has since evolved into the “Windows SDK”), one option is to download the “Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)” - a 570MB package.
Another is the “Windows SDK for Windows Server 2008 and .NET Framework 3.5” - a whopping 1.3 GB download.

Windows SDK for Windows 7 and .NET Framework 4 (GRMSDK_EN_DVD.iso):

Windows SDK for Windows Server 2008 and .NET Framework 3.5 (6.0.6001.18000.367-KRMSDK_EN.iso):

In either case a tool capable of browsing ISOs – such as the indispensable freeware/open-source 7zip (http://www.7-zip.org/) - can be used to locate the files inside of them without any protracted CD-burning or other intermediate extraction.

If you opt for the former, open the ISO, then the Setup folder, then the WinSDKTools folder, and within that the cab1.cab file. Here you'll find 3 of the 4 tools above – extract these to a convenient location.

Within the cabinet the files are named:

WinSDK_makecert_exe_5D21BAF1_83A4_4E71_998E_FF39C36EA905_x86
WinSDK_Cert2Spc_Exe_910B78B5_FBE7_44CD_867D_0F90509859B0_x86
WinSDK_signtool_exe_B2E1011D_2F14_488D_A056_C5BD55106409_x86

Rename these to:

makecert.exe
Cert2Spc.Exe
signtool.exe

...respectively. Note, though, that the Windows 7/.NET 4 SDK does not include (as far as I can tell), the “capicom.dll” file, so this must be downloaded separately (via the webpage “Platform SDK Redistributable: CAPICOM”) – it's available (at slightly under 2MB) here:

If you choose the later option, open the ISO with a browsing tool (such as 7zip), open the Setup folder, locate the WinSDKTools-WinSDKTools-common.0.cab file, open this, and extract the four files:

capicom_dll.970E4F94_546F_49F3_BF1F_18BE6B938B02
Cert2Spc_exe.D7AE6AF7_EC98_4D5C_97F8_562E6B8AF64F
makecert_exe.E4279728_DED0_47AC_8B96_F1269703DEFB
signtool_exe.B68FF751_0B1A_4F33_B044_1871CB4B13CC

...then rename them to:

capicom.dll
Cert2Spc.exe
makecert.exe
signtool.exe

pvkimprt.exe is not available in either distribution so, also, must be downloaded separately. It can be found via the webpage “Office 2000 Tool: PVK Digital Certificate Files Importer” (http://www.microsoft.com/download/en/details.aspx?displaylang=EN&id=6563).
It's a self-extracting zip file, but again, a tool like 7zip can browse its content without having to execute it and step through the extraction wizard. When opened, extract the file “pvkimprt.exe” to a convenient location. This file is, in turn, a self-extracting zip. Open it with 7zip, and extract “pvkimprt.exe”.


Generating a certificate

With all of the required tools available, we can now generate our private key and code signing certificate.

Open a command prompt (type cmd in the Run or “Start Search” box, or use Start->All Programs/Programs->Accessories->Command Prompt), navigate to the directory containing the tools, and execute them in the following sequence (with all spaces and other punctuation as shown):
makecert.exe MyCertificateFile.cer -r -n "CN= MyCompanyName " -$ individual -sv MyPrivateKeyFile.pkv -pe -eku 1.3.6.1.5.5.7.3.3

This first step will produce a “self-signed” certificate. Substitute “MyCertificateFile.cer” with the name you want to give to the generated certificate (the name you choose is just a label, the value of the text is inconsequential to the outcome of later stages – in all instances it makes sense to retain the suggested extensions, though, for clarity); “MyCompanyName” with an appropriate value for your “Publisher” identity; “MyPrivateKeyFile.pkv” with a name to use for your private key store file.

For further information about the meaning of the command line switches added here, use the in-built help “makecert.exe /?”.

The string after the “eku” switch indicates that the file to create will be a “code signing” certificate.

When you run the tool, you will be prompted to enter a “Private Key Password” - you will need to provide this again in step 3, and each time you sign a file, so make a note of the password you choose to use here.
cert2spc.exe MyCertificateFile.cer MyCertificateFile.spc

Replace “MyCertificateFile.cer” with the name you chose to give your generated self-signed certificate from step 1, and choose a matching name (again, just for clarity – it doesn't have to match) to replace “MyCertificateFile.spc”. This will create a “Software Publisher Certificate” (SPC) from the “MyCertificateFile.cer” file – a certificate equivalent to one that would be issued from a Certificate Authority.
pvkimprt.exe -pfx MyCertificateFile.spc MyPrivateKeyFile.pkv

Replace “MyCertificateFile.spc”with the name you chose for your Software Publisher Certificate (.spc file) in step 2, and “MyPrivateKeyFile.pkv” with a name for the file to be created by Pvkimprt – a “Personal Information Exchange” (PFX) file – this is what will be used to for code signing.
Pkimprt is a GUI wizard. When you run it you'll first be asked to enter your “Private Key Password” - the password you selected for step 1.

None of the default wizard values need to be changed, so click through each successive form by clicking Next (x3), then on the “Password” form, enter your Private Key Password twice more, and click Next again.

On the “File to Export” form, click the Browse button, navigate to the directory containing the signing tools, and type a name for the PFX file – e.g., “MyPFXFile.pfx”, then click Next.
On the final wizard form, “Completing the Certificate Export Wizard”, click the Finish button to complete the procedure.

As a result of these steps, you should now have four new files labelled something like:

MyPrivateKeyFile.pkv
MyCertificateFile.cer
MyCertificateFile.spc
MyPFXFile.pfx


Code signing

To use our newly generated certificate, we need signtool.exe and a target file. Suppose we have a binary executable named “MyProgram.exe” - the syntax for signing this file would be:
signtool.exe sign /f MyPFXFile.pfx /p MyPrivateKeyPassword /v /t http://timestamp.verisign.com/scripts/timstamp.dll MyProgram.exe

- where “MyPrivateKeyPassword” is the password you chose in step 1 (note also that “timstamp.dll” is not a misspelling).


Automating the process

To make things easier and avoid having to re-type long commands in the case of a syntax error, it makes sense to string the tool commands together in a batch file. See the listing below for two batch files based upon the text of the steps listed above.

Generating a private key, self-signed certificate, and PFX file:

MakeCert.bat
@ECHO OFF

makecert.exe MyCertificateFile.cer -r -n "CN= MyCompanyName " -$ individual -sv MyPrivateKeyFile.pkv -pe -eku 1.3.6.1.5.5.7.3.3


cert2spc.exe MyCertificateFile.cer MyCertificateFile.spc

pvkimprt.exe -pfx myCertificateFile.spc myPrivateKeyFile.pkv


Signing a binary file:

SignBinary.bat
@ECHO OFF

signtool.exe sign /f MyPFXFile.pfx /p MyPrivateKeyPassword /v /t http://timestamp.verisign.com/scripts/timstamp.dll %1


To use the second batch file with a named binary, launch it with a parameter – the name of the target binary file, e.g., “SignBinary.bat MyProgram.exe”.


References





Code Signing for Developers – a Delphi-orientated article covering the same sort of territory, but addressing (in addition) sourcing and using a Certificate Authority issued certificate:
http://www.wiscocomputing.com/articles/code-signing.htm

A Microsoft article explaining different methods for sourcing a code signing certificate: http://technet.microsoft.com/en-us/library/cc732597%28v=ws.10%29.aspx#BKMK_Anchor3


How to create your own certificate for signing ClickOnce manifests and Strong Naming assemblies (highly recommended!):
http://www.uphillriver.com/CreateYourOwnCertificate.aspx

All About Authenticode (highly recommended!):
http://www.tech-pro.net/authenticode.html

Code Signing for Developers - An Authenticode How-To (highly recommended!):
http://www.tech-pro.net/code-signing-for-developers.html

3 comments:

  1. This means... we can sign our executable for free?
    Thanks for the info. Useful post.

    ReplyDelete
  2. This is very help full for me. thank you very much. i want to know one thing is there any way i can run this in another computer with verify publisher. it only work in my computer

    ReplyDelete
  3. o que tecnicamente se aproveita deste artigo é este comando

    SignTool.exe / f ArquivoCertificadoAdquiridoDeCertificadora.pfx / p SenhaDoCertificado / v / t http://timestamp.verisign.com/scripts/timstamp.dll SeuAPP.exe

    Pois a geracao do certificado modelo nao assina o aplicativo

    ReplyDelete