[prev in list] [next in list] [prev in thread] [next in thread] 

List:       ms-cryptoapi
Subject:    Re: Has anyone figured out how to hand code portable executable
From:       Peter Gutmann <pgut001 () CS ! AUCKLAND ! AC ! NZ>
Date:       2000-11-21 0:18:26
[Download RAW message or body]


Tim Anderson <TimA@PREDATOR-SOFTWARE.COM> writes:

>I'd still like to verify a digital signature using the hammer and tongs
>method, not using WinVerifyTrust. The thing signcode sticks on the end of an
>EXE/DLL/OCX is a pkcs7 signature, but the gory details of how to decipher it
>with the cryptoapi and what exactly they run the hash on are sorely lacking...

I reverse-engineered the format ages ago when I was writing some code to forge
Authenticode sign... never mind :-).  Here are my notes on the topic.  This was
current as of about three years ago, some things may have changed since then.

Peter.

-- Snip --

Format of a Signed File
-----------------------

A signed file is a standard Windows PE executable with signature data appended
to it.  A PE file begins with a 16-bit MSDOS executable stub (which just prints
a message that you can't run the program and exits).  Following this is the
real data, organised in a COFF-like format.  The general COFF header which is
always present is followed by another header which contains information on
executables (it's referred to as an optional header, but it's always present
for executables).  This header defines a number of data directories which
contain data sections within the executable.  One of these directory entries is
an (undocumented) IMAGE_DIRECTORY_ENTRY_SECURITY, which is used to store the
signature: Hash the entire file, add a security directory entry large enough to
contain the signature, and write the signature at that position in the file.

The signing process is as follows:

1. Hash the file, skipping the file checksum (another undocumented attribute,
   but there are standard Windows functions to calculate it) and the
   IMAGE_DIRECTORY_ENTRY_SECURITY entry.
2. Generate the signature and append it to the file.
3. Write the signature position and size (padded out to a multiple of 16 bytes)
   into the IMAGE_DIRECTORY_ENTRY_SECURITY.  The signature position is the end
   of the file, since it's simply appended to the existing data.
4. Update the file checksum.

The security information begins with a 32-bit length (which is ignored) and a
32-bit flags field which should be set to 0x00020200.  Most of the flags are
unused, although changing the first 0x02 to a 1 gives an invalid signature, and
changing the second one to anything other than 0x02 results in the signature
check silently failing with no error message or other indication.

Immediately following this is a complex PKCS #7 signature record which contains
a detached signature for the rest of the file.  The outer wrapper is PKCS #7
signedData, with the content being an spcIndirectDataContext (an MS-defined
data type) which contains an (obsolete) spcPelmageData record and an MD5 hash
of the file.  This is followed by a certificate chain containing a complete
chain of certs from a known CA to an end-users AuthentiCode signing
certificate.  Following this is information on the signer (that is, data to
identify the AuthentiCode certificate which signed the whole thing), an
identifier for the hash algorithm used (again, MD5), and some authenticated
attributes.  These contain more MS-defined attributes, typically spcSpOpusInfo
and spcStatementType which are used to provide information on the signer (eg
whether they're using an individual or commercial signing certificate).  Also
included is a messageDigest attribute which contains the MD5 hash of the
previous spcIndirectDataContext content.  Finally, the authenticated attributes
are hashed and signed, with the signature being included at the end of the
collection of signature information.

To create the signature, you need to hash the entire file (skipping the
checksum and IMAGE_DIRECTORY_ENTRY_SECURITY as explained above) and write the
hash info the spcIndirectDataContext content record.  Then hash this and write
the hash and other attributes into the authenticated attributes.  Finally, hash
the authenticated attributes and append the signature to the end of the
signature record.  This means that each collection of data is covered by its
own hash, which is then passed up the chain to the next level until it reaches
the signature.

----------------------------------------------------------------
Users Guide http://msdn.microsoft.com/workshop/essentials/mail.asp
contains important info including how to unsubscribe.  Save time, search
the archives at http://discuss.microsoft.com/archives/index.html

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic