sirp Posted November 4, 2010 Posted November 4, 2010 // © 2005 Richard Grimes// snSig library used to get information about a strong name signature of// a .NET assemblyusing System;using System.IO;// Used to obtain the file offset and the size of the strong name signature// and the strong name data directorypublic class StrongNameSignature{ // Locations and sizes of various things in the PE file const int pePos = 0x003c; const int numSectOffset = 0x02; const int peIdentSize = 0x04; const int coffHeaderSize = 0x14; const int dataDirectoryOffset = 0x60; const int dataDirectoryLength = 0x08; const int clrHeaderIndex = 0x0e; const int strongNameSigOffset = 0x20; const int sectionHeaderSize = 0x28; const int sectionSizeOffSet = 0x08; const int sectionRVAOffset = 0x0c; const int sectionRawOffset = 0x14; int strongNameSigSize = 0; // Returns the size of the strong name signature public int Size { get{return strongNameSigSize;} } int strongNameSig = 0; // Returns the offset in the file of the strong name signature public int Address { get{return strongNameSig;} } int strongNameDataDirectory = 0; // Returns the offset of the strong name data directory public int StrongNameDataDirectory { get{return strongNameDataDirectory;} } FileStream fs; // Passed an open file of a .NET assembly public StrongNameSignature(FileStream file) { fs = file; // Find the pointer to the PE identifier before the COFF header int coffHeader = GetInt(pePos); // Get the number of sections from the COFF header short numSections = GetWord(coffHeader + peIdentSize + numSectOffset); // Calculate the location of the PE header int peHeader = coffHeader + coffHeaderSize + peIdentSize; // Determine the location of the data directories int dataDirectories = peHeader + dataDirectoryOffset; // Determine the location of the CLR directory int clrHeaderDD = dataDirectories + (dataDirectoryLength * clrHeaderIndex); // Read the RVA of the CLR header int clrHeader = GetInt(clrHeaderDD); // Read the size of the CLR header int clrHeaderSize = GetInt(clrHeaderDD + 4); // Note that CLR header is stored in the .text section, so read this section // so that we can convert between RVA and actual file offsets int textRVA = 0; int textRaw = 0; int textSize = 0; // Determine the location of the section headers int sections = clrHeaderDD + (2 * dataDirectoryLength); // Iterate through the section headers until we find the header for the // .text section byte[] bText = {0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00}; for (int idx = 0; idx < numSections; ++idx) { // Read the first eight bytes which will have the name of the section // Note that this is NOT a NUL terminated string, the section name // can be 8 characters. int sectionStart = sections + (idx * sectionHeaderSize); byte[] eightBuf = GetEightBytes(sectionStart); if (!Compare(eightBuf, bText)) continue; // We have the right section so get the values textSize = GetInt(sectionStart + sectionSizeOffSet); textRVA = GetInt(sectionStart + sectionRVAOffset); textRaw = GetInt(sectionStart + sectionRawOffset); } // Convert RVA to file offset clrHeader = clrHeader - textRVA + textRaw; // Calculate the file offset of the strong name data directory strongNameDataDirectory = clrHeader + strongNameSigOffset; // Get the RVA of the strong name signature strongNameSig = GetInt(clrHeader + strongNameSigOffset); // Convert RVA to file offset strongNameSig = strongNameSig - textRVA + textRaw; // Get the size of the strong name signature strongNameSigSize = GetInt(clrHeader + strongNameSigOffset + 4); } // Do a character by character comparison private static bool Compare(byte[] lhs, byte[] rhs) { int size = (lhs.Length > rhs.Length) ? rhs.Length : lhs.Length; for (int idx = 0; idx < size; ++idx) { if (lhs[idx] != rhs[idx]) return false; } return true; } // Read a 16-bit value from the file private short GetWord(int pos) { byte[] wordBuf = new byte[2]; fs.Seek(pos, SeekOrigin.Begin); fs.Read(wordBuf, 0, wordBuf.Length); return BitConverter.ToInt16(wordBuf, 0); } // Read a 32-bit value from the file private int GetInt(int pos) { byte[] intBuf = new byte[4]; fs.Seek(pos, SeekOrigin.Begin); fs.Read(intBuf, 0, intBuf.Length); return BitConverter.ToInt32(intBuf, 0); } // Read an eight byte array from the file private byte[] GetEightBytes(int pos) { byte[] eightBuf = new byte[8]; fs.Seek(pos, SeekOrigin.Begin); fs.Read(eightBuf, 0, eightBuf.Length); return eightBuf; }}
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now