public void WritePortableExecutable(BinaryWriter writer) { writer.BaseStream.Seek(0, SeekOrigin.Begin); DOSHeader.Write(writer); writer.Write(_dosStubBytes); COFFHeader.Write(writer); PEHeaderOffset = (uint)writer.BaseStream.Position; PEHeader.Write(writer); for (var i = 0; i < COFFHeader.NumberOfSections; i++) { SectionHeaders[i].Write(writer); } writer.Write(_filler); for (var i = 0; i < COFFHeader.NumberOfSections; i++) { writer.Write(Sections[i]); } writer.Write(_remainingBytes); // Write Import Directory: var importDirectoryEntry = PEHeader.DataDirectories[(int)DataDirectoryName.Import]; if (importDirectoryEntry.VirtualAddress > 0) { var importDirectoryFileOffset = GetOffsetFromRVA(importDirectoryEntry.VirtualAddress); writer.Seek((int)importDirectoryFileOffset, SeekOrigin.Begin); ImportDirectory.Write(writer); } // Update PE checksum: writer.Seek(0, SeekOrigin.Begin); var fileBytes = new byte[writer.BaseStream.Length]; writer.BaseStream.Read(fileBytes, 0, (int)writer.BaseStream.Length); var checksumOffset = PEHeaderOffset + PEHeader.ChecksumRelativeAddress; var checksum = PortableExecutableUtils.CalculcateChecksum(fileBytes, checksumOffset); writer.Seek((int)checksumOffset, SeekOrigin.Begin); writer.Write(checksum); writer.Flush(); }
public void Parse(BinaryReader reader) { DOSHeader = DOSHeader.Parse(reader); var dosStubSize = (int)(DOSHeader.CoffHeaderOffset - reader.BaseStream.Position); _dosStubBytes = reader.ReadBytes(dosStubSize); COFFHeader = COFFHeader.Parse(reader); PEHeaderOffset = (uint)reader.BaseStream.Position; PEHeader = PEHeader.Parse(reader); for (var i = 0; i < COFFHeader.NumberOfSections; i++) { SectionHeaders.Add(PESectionHeader.Parse(reader)); } var fillerSize = (int)(SectionHeaders[0].PointerToRawData - reader.BaseStream.Position); _filler = reader.ReadBytes(fillerSize); for (var i = 0; i < COFFHeader.NumberOfSections; i++) { var sectionBytes = reader.ReadBytes((int)SectionHeaders[i].SizeOfRawData); Sections.Add(sectionBytes); } var remainingByteCount = (int)(reader.BaseStream.Length - reader.BaseStream.Position); _remainingBytes = reader.ReadBytes(remainingByteCount); // file ends here // Parse Import Directory: var importDirectoryEntry = PEHeader.DataDirectories[(int)DataDirectoryName.Import]; if (importDirectoryEntry.VirtualAddress > 0) { var importDirectoryFileOffset = GetOffsetFromRVA(importDirectoryEntry.VirtualAddress); reader.BaseStream.Seek(importDirectoryFileOffset, SeekOrigin.Begin); ImportDirectory = ImportDirectory.Parse(reader); } }
public static PEHeader Parse(BinaryReader reader) { var signature = (PEHeaderType)reader.ReadUInt16(); if (!Enum.IsDefined(typeof(PEHeaderType), signature)) { throw new Exception("Invalid PE header signature"); } var header = new PEHeader { Type = signature, LinkerVersion = new Version(reader.ReadByte(), reader.ReadByte()), SizeOfCode = reader.ReadUInt32(), SizeOfInitializedData = reader.ReadUInt32(), SizeOfUninitializedData = reader.ReadUInt32(), AddressOfEntryPoint = reader.ReadUInt32(), BaseOfCode = reader.ReadUInt32() }; if (signature == PEHeaderType.PE64) { header.ImageBase = reader.ReadUInt64(); } else { header.BaseOfData = reader.ReadUInt32(); header.ImageBase = reader.ReadUInt32(); } header.SectionAlignment = reader.ReadUInt32(); header.FileAlignment = reader.ReadUInt32(); header.OperatingSystemVersion = new Version(reader.ReadUInt16(), reader.ReadUInt16()); header.ImageVersion = new Version(reader.ReadUInt16(), reader.ReadUInt16()); header.SubsystemVersion = new Version(reader.ReadUInt16(), reader.ReadUInt16()); header.Win32VersionValue = reader.ReadUInt32(); header.SizeOfImage = reader.ReadUInt32(); header.SizeOfHeaders = reader.ReadUInt32(); header.Checksum = reader.ReadUInt32(); header.Subsystem = (PESubsystem)reader.ReadUInt16(); header.DllCharacteristics = (PEDllCharacteristics)reader.ReadUInt16(); if (signature == PEHeaderType.PE64) { header.SizeOfStackReserve = reader.ReadUInt64(); header.SizeOfStackCommit = reader.ReadUInt64(); header.SizeOfHeapReserve = reader.ReadUInt64(); header.SizeOfHeapCommit = reader.ReadUInt64(); } else { header.SizeOfStackReserve = reader.ReadUInt32(); header.SizeOfStackCommit = reader.ReadUInt32(); header.SizeOfHeapReserve = reader.ReadUInt32(); header.SizeOfHeapCommit = reader.ReadUInt32(); } header.LoaderFlags = reader.ReadUInt32(); header.DataDirectories = new PEDataDirectory[reader.ReadUInt32()]; for (var i = 0; i < header.DataDirectories.Length; i++) { header.DataDirectories[i] = PEDataDirectory.Parse(reader); } return(header); }