Wow ... there's been lots of interest in signatures lately :-) In response to my last post about reserving a larger section of the PE file for the signature when you create a signature with a larger key, William wants to know if you can extract the actual signature bytes from the PE file.
Absolutely you can, it's even relatively easy to do. Boiled down, the raw strong name signature is simply the array of bytes that are located at the RVA specified by the StrongNameSignature.VirtualAddress field of the CLR header. The signature length is specified by the StrongNameSignature.Size field of the header. So once you have the CLR header of a PE file, its very easy to find the signature itself.
In the spirit of picking the right tool for the job, I'll show how to do this in C++ code, since creating P/Invoke declarations for the various structures needed would take up a large chunk of time. The code for a method that takes a memory mapped PE file and displays its raw signature would look something like this:
OK, that's a chunk and a half of code right there. However, the process its following is relatively straight forward. On lines 9-14, I use the DbgHelp function ImageNtHeader to locate the IMAGE_NT_HEADERS structure in the file. Once we have the NT headers, we need to find the data directories, but their location varies depending upon if the assembly is a PE32 or PE32+ file. So on lines 16 through 30 we check the magic number in the beginning of the optional header, and get the correct pointer to the data directories. If the PE is neither of these two formats, we bomb out.
So now that we've got the table of directory entries, on lines 32 through 52 we make sure that the entry for the COM descriptor directory exists, and if it does use another DbgHelp function ImageRvaToVa in order to convert the RVA of the directory entry to an address within the mapped file. The beginning of this directory entry is the CLR header, in the form of a IMAGE_COR20_HEADER structure.
Once we have our IMAGE_COR20_HEADER, the information about the signature is located in the StrongNameSignature field. In lines 54-73 we check if a signature exists, and if it does, use ImageRvaToVa in order to calculate the location in the file of the signature itself.
Once we have that offset, dumping the signature to the display is easy. Lines 75-83 simple iterate over the memory in the memory mapped file that contains the signature until we've dumped out pCorHeader->StrongNameSignature.Size bytes. At that point, we've displayed the entire signature, so the method returns.