This program allows you to embed a payload containing custom user data into an executable generated by NSIS (Nullsoft Scripted Installer System) and signed with Microsoft SignTool.exe (or similar). This is tested and working with the NSIS ReadCustomerData Function. Windows recognizes the original digital signature since we are just adding arbitrary data and did not modify the code.
⚡ WARNING: The technique used to add payload to a signed exe takes advantage of CVE-2013-3900. If the "EnableCertPaddingCheck" registry key is configured as described in Microsoft Security Advisory 2915720, the signature verification will fail after adding your payload to the signed exe. Microsoft currently disables the "EnableCertPaddingCheck" setting by default, but this may change in the future. Thank you to @MustrumRidcully0 for identifying this issue. |
---|
Original Source: Changing a Signed Executable Without Altering Windows Digital Signature by Aymeric Barthe 02/22/2019
The way Microsoft authenticode works is the following. During the signature process, it computes the hash on the executable file. The hash is then used to make a digital certificate which is authenticated by some authority. This certificate is attached to the end of the PE exectuable, in a dedicated section called the Certificate Table. When the executable is loaded, Windows computes the hash value, and compares it to the one attached to the Certificate table. It is “normally” impossible to change anything in the file without breaking the digital authentication.
However three areas of a PE executable are excluded from the hash computation:
- the Checksum in the optional Windows specific header. 4 bytes.
- the Certificate Table entry in the optional Windows specific header. 8 bytes.
- the Digital Certificate section at the end of the file. Variable length.
You should be able to change those area without breaking the signature. I have discovered by accident that it is possible to append an arbitrary ammount of data at the end of the Digital Certificate. These data are ignored by both the signature parsing and hash computation algorithms. It works on all version of Windows I tested (2000, XP, Vista) as long as the length of the Certificate Table is correctly increased. The length is stored in two different location: the PE header and the beginning of the certificate table.
How to add a payload
- Locate beginning of PE header (PE)
- Skip COFF header (+=28 bytes)
- Go to Certification Table Entry in the Windows specific optional PE header (+=120 bytes after COFF; total +=148 bytes)
- Change size of Certificate Table as defined in IMAGE_DATA_DIRECTORY.Size to add the size of the payload.
- Go to location defined IMAGE_DATA_DIRECTORY.VirtualAddress. This is the absolute location of the Certificate Table within the file.
- Change again the size of the header, inside the PKCS1_MODULE_SIGN.dwLength
- This should normally be the last section in the executable; so go to the end and add payload
- Possibly calculate the new checksum of the file
- Caution: the previous constants are true for the 32bit x86 versions of Windows. Payload needs to be 64bits aligned. All the 32 bits constants are of course little endians woo woo!
This repository includes the original code written for Windows by Aymeric Barthe as well as modified code tested on Linux and macOS.
You will need to download to Linux or macOS, install the g++ compiler, compile the program, and run. Details below.
Install g++ on Debian Linux 9 by running the following command:
apt-get install g++
I tested with the following g++ compiler on Debian 9:
$ g++ --version
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Install g++ on macOS by installing XCode.
I tested with the following g++ compiler on macOS 10.13:
$ g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Compile the program using the following command on Linux or macOS:
g++ AppendPayLoad.cpp
mv a.out AppendPayLoad
End with an example of getting some data out of the system or using it for a little demo
The following commands will READ SetupMaster.exe (your signed NSIS installer), append payload from SetupUser123.dat, and write a custom NSIS installer file SetupUser123.exe with embedded username and password. The original digital signature will still be intact.
echo "CUSTDATA:username123;password123" > SetupUser123.dat
./AppendPayLoad SetupMaster.exe SetupUser123.dat SetupUser123.exe
Use the NSIS ReadCustomerData function to read the appended data. Learn more in my NSIS ReadCustomerData without invalidating SignTool Digital Signature blog post.
- Changing a Signed Executable Without Altering Windows Digital Signature - Original release by Aymeric Barthe on 02/22/2009
- Hackers Library - The PE Format - Documentation by Gaurav Mogre 12/08/2008 (archived in this repo)
- Microsoft KB 904424 - IMAGE_DATA_DIRECTORY - This structure represents the data directory.
- Microsoft KB 448396 - Signature Creation - Signature format details
- Aymeric Barthe - Initial work - @aymericb
- Jason Klein - Adapt/test on Linux/macOS - @jason-klein