Search code examples
winapidigital-signaturecode-signingsigntoolauthenticode

Codesign an executable and allow the modification of some bytes


I use signtool.exe to codesign a Windows executable.

Which options of this tool can be used to define that a few bytes should be omitted from the hash calculation, and thus allowing that a digitally signed executable can have 8 or 16 bytes modified later?

This technique has been used by Mozilla (their .exe installer is different for each download, but has the same digital signature), see How can a .exe be modified and still keep a valid digital signature?.

The WinAPI function ImageGetDigestStream has an option DigestLevel to exclude resource information from the hash computation, but how to use this option when actually with signtool.exe or a similar tool?


Solution

  • This is explained by Didier Stevens in an article here: It's in the signature and he also provides a tool "disitool" to manipulate the signature.

    Here are the steps to sign a file using Authenticode, and to append some data to it without breaking the signature:

    A) Create a code siging certificate (you'll be required to enter passwords):

    MakeCert /n "CN=MyOrg" /r /h 0 /eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /sv MyOrg.pvk MyOrg.cer
    

    note: 1.3.6.1.5.5.7.3.3 is szOID_PKIX_KP_CODE_SIGNING and 1.3.6.1.4.1.311.10.3.13 is szOID_KP_LIFETIME_SIGNING. This will create a private key file and a certificate file.

    B) Add certificate to store (needs admin rights, could be a different store):

    Certutil -addStore TrustedPeople MyOrg.cer
    

    C) Create a Pfx file to sign:

    Pvk2Pfx /pvk MyOrg.pvk /pi [Password goes here] /spc MyOrg.cer /pfx MyOrg.pfx
    

    D) Sign your file:

    SignTool.exe sign /fd SHA256 /v /a /f MyOrg.pfx /p [Password goes here] MyFile.exe
    

    At this point MyFile.exe is signed using Authenticode:

    enter image description here

    E) Create some data.txt file. I've created one that just contains the "[Kilroy was here!]" text.

    F) Now run disitool:

    python.exe disitool.py inject --paddata MyFile.exe data.txt MyFile2.exe
    

    And here is the result, MyFile2.exe is still valid without resigning the file:

    enter image description here

    While you can see data.txt's content added to its end:

    enter image description here

    From the original file's end:

    enter image description here

    In my answer here How to read altered certificate data using WinApi?, I explain how to read the extra data using the Windows API.