private IEnumerable <byte> ComputeAuthenticodeHashFromPeFile(HashAlgorithm hash) { // 3. Hash the image header from its base to immediately before the start of the checksum address, // as specified in Optional Header Windows-Specific Fields. int offset = Convert.ToInt32(_peFile.ImageNtHeaders.OptionalHeader.Offset) + 0x40; hash.TransformBlock(_peFile.Buff, 0, offset, new byte[offset], 0); // 4. Skip over the checksum, which is a 4-byte field. offset += 0x4; // 6. Get the Attribute Certificate Table address and size from the Certificate Table entry. // For details, see section 5.7 of the PE/COFF specification. Structures.IMAGE_DATA_DIRECTORY certificateTable = _peFile.ImageNtHeaders.OptionalHeader.DataDirectory[4]; // 5. Hash everything from the end of the checksum field to immediately before the start of the Certificate Table entry, // as specified in Optional Header Data Directories. int length = Convert.ToInt32(certificateTable.Offset) - offset; hash.TransformBlock(_peFile.Buff, offset, length, new byte[length], 0); offset += length + 0x8;//end of Attribute Certificate Table addres // 7. Exclude the Certificate Table entry from the calculation and // hash everything from the end of the Certificate Table entry to the end of image header, // including Section Table (headers). The Certificate Table entry is 8 bytes long, as specified in Optional Header Data Directories. length = Convert.ToInt32(_peFile.ImageNtHeaders.OptionalHeader.SizeOfHeaders) - offset;// end optional header hash.TransformBlock(_peFile.Buff, offset, length, new byte[length], 0); // 8-13. Hash everything between end of header and certificate int sizeOfHeaders = Convert.ToInt32(_peFile.ImageNtHeaders.OptionalHeader.SizeOfHeaders); length = Convert.ToInt32(_peFile.WinCertificate.Offset) - sizeOfHeaders; hash.TransformBlock(_peFile.Buff, sizeOfHeaders, length, new byte[length], 0); // 14. Create a value called FILE_SIZE, which is not part of the signature. // Set this value to the image’s file size, acquired from the underlying file system. // If FILE_SIZE is greater than SUM_OF_BYTES_HASHED, the file contains extra data that must be added to the hash. // This data begins at the SUM_OF_BYTES_HASHED file offset, and its length is: // (File Size) – ((Size of AttributeCertificateTable) + SUM_OF_BYTES_HASHED) // Note: The size of Attribute Certificate Table is specified // in the second ULONG value in the Certificate Table entry (32 bit: offset 132, 64 bit: offset 148) in Optional Header Data Directories. // 14. Hash everything from the end of the certificate to the end of the file. int fileSize = _peFile.Buff.Length; int sizeOfAttributeCertificateTable = Convert.ToInt32(certificateTable.Size); offset = sizeOfAttributeCertificateTable + Convert.ToInt32(_peFile.WinCertificate.Offset); if (fileSize > offset) { length = fileSize - offset; if (length != 0) { hash.TransformBlock(_peFile.Buff, offset, length, new byte[length], 0); } } // 15. Finalize the hash algorithm context. hash.TransformFinalBlock(_peFile.Buff, 0, 0); return(hash.Hash); }
private Dictionary <uint, Structures.IMAGE_DATA_DIRECTORY> ConstructDataDirectories(bool ignoreHeaderNumbers) { Dictionary <uint, Structures.IMAGE_DATA_DIRECTORY> rawdatadirs = new Dictionary <uint, Structures.IMAGE_DATA_DIRECTORY>(); for (int i = 0; i < (ignoreHeaderNumbers ? 0x10 : (optionalheadersig == 0x10b ? optionalHeader32.NumberOfRvaAndSizes : optionalHeader64.NumberOfRvaAndSizes)); i++) { uint byteoffset = (uint)image.Stream.Position; Structures.IMAGE_DATA_DIRECTORY datadir = image.ReadStructure <Structures.IMAGE_DATA_DIRECTORY>(); rawdatadirs.Add(byteoffset, datadir); } return(rawdatadirs); }
internal DataDirectory(DataDirectoryName name, Section targetSection, uint headerOffset, Structures.IMAGE_DATA_DIRECTORY rawDataDir) { this.name = name; this.headerOffset = headerOffset; this.rawDataDir = rawDataDir; if (rawDataDir.RVA == 0) { targetOffset = new Offset(0, 0, 0); } else { OffsetConverter converter = new OffsetConverter(targetSection); this.targetOffset = Offset.FromRva(rawDataDir.RVA, targetSection.ParentAssembly); this.targetSection = targetSection; } }
internal DataDirectory(DataDirectoryName name, Section[] assemblySections, uint offset, Structures.IMAGE_DATA_DIRECTORY rawDataDir) { this.rawDataDir = rawDataDir; this.name = name; if (rawDataDir.RVA == 0) { targetOffset = new Offset(0, 0, 0); } else { this.headerOffset = offset; targetSection = Section.GetSectionByRva(assemblySections, rawDataDir.RVA); if (targetSection == null) { this.TargetOffset = new Offset(0, rawDataDir.RVA, 0); } else { this.targetOffset = Offset.FromRva(rawDataDir.RVA, assemblySections[0].ParentAssembly); } } }
internal DataDirectory(DataDirectoryName name, Section targetSection, uint headerOffset, Structures.IMAGE_DATA_DIRECTORY rawDataDir) { this._name = name; this._headerOffset = headerOffset; this._rawDataDir = rawDataDir; if (rawDataDir.RVA == 0 || targetSection == null) { _targetOffset = new Offset(0, 0, 0); } else { this._targetOffset = Offset.FromRva(rawDataDir.RVA, targetSection.ParentAssembly); this._targetSection = targetSection; } }