diff --git a/de4dot.code/PE/FileHeader.cs b/de4dot.code/PE/FileHeader.cs new file mode 100644 index 00000000..cbe5ea64 --- /dev/null +++ b/de4dot.code/PE/FileHeader.cs @@ -0,0 +1,48 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System.IO; + +namespace de4dot.PE { + enum Machine : ushort { + i386 = 0x14C, + ia64 = 0x200, + amd64 = 0x8664, + } + + class FileHeader { + public Machine machine; + public ushort numberOfSections; + public uint timeDateStamp; + public uint pointerToSymbolTable; + public uint numberOfSymbols; + public ushort sizeOfOptionalHeader; + public ushort characteristics; + + public FileHeader(BinaryReader reader) { + machine = (Machine)reader.ReadUInt16(); + numberOfSections = reader.ReadUInt16(); + timeDateStamp = reader.ReadUInt32(); + pointerToSymbolTable = reader.ReadUInt32(); + numberOfSymbols = reader.ReadUInt32(); + sizeOfOptionalHeader = reader.ReadUInt16(); + characteristics = reader.ReadUInt16(); + } + } +} diff --git a/de4dot.code/PE/OptionalHeader.cs b/de4dot.code/PE/OptionalHeader.cs new file mode 100644 index 00000000..b7f5ca1c --- /dev/null +++ b/de4dot.code/PE/OptionalHeader.cs @@ -0,0 +1,115 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System.IO; + +namespace de4dot.PE { + struct DataDirectory { + public uint virtualAddress; + public uint size; + + public override string ToString() { + return string.Format("{0:X8} {1:X8}", virtualAddress, size); + } + } + + class OptionalHeader { + public ushort magic; + public byte majorLinkerVersion; + public byte minorLinkerVersion; + public uint sizeOfCode; + public uint sizeOfInitializedData; + public uint sizeOfUninitializedData; + public uint addressOfEntryPoint; + public uint baseOfCode; + public uint baseOfData; // 32-bit only + public ulong imageBase; + public uint sectionAlignment; + public uint fileAlignment; + public ushort majorOperatingSystemVersion; + public ushort minorOperatingSystemVersion; + public ushort majorImageVersion; + public ushort minorImageVersion; + public ushort majorSubsystemVersion; + public ushort minorSubsystemVersion; + public uint win32VersionValue; + public uint sizeOfImage; + public uint sizeOfHeaders; + public uint checkSum; + public ushort subsystem; + public ushort dllCharacteristics; + public ulong sizeOfStackReserve; + public ulong sizeOfStackCommit; + public ulong sizeOfHeapReserve; + public ulong sizeOfHeapCommit; + public uint loaderFlags; + public uint numberOfRvaAndSizes; + public DataDirectory[] dataDirectories; + + public OptionalHeader(BinaryReader reader) { + magic = reader.ReadUInt16(); + majorLinkerVersion = reader.ReadByte(); + minorLinkerVersion = reader.ReadByte(); + sizeOfCode = reader.ReadUInt32(); + sizeOfInitializedData = reader.ReadUInt32(); + sizeOfUninitializedData = reader.ReadUInt32(); + addressOfEntryPoint = reader.ReadUInt32(); + baseOfCode = reader.ReadUInt32(); + if (is32bit()) + baseOfData = reader.ReadUInt32(); + imageBase = read4Or8(reader); + sectionAlignment = reader.ReadUInt32(); + fileAlignment = reader.ReadUInt32(); + majorOperatingSystemVersion = reader.ReadUInt16(); + minorOperatingSystemVersion = reader.ReadUInt16(); + majorImageVersion = reader.ReadUInt16(); + minorImageVersion = reader.ReadUInt16(); + majorSubsystemVersion = reader.ReadUInt16(); + minorSubsystemVersion = reader.ReadUInt16(); + win32VersionValue = reader.ReadUInt32(); + sizeOfImage = reader.ReadUInt32(); + sizeOfHeaders = reader.ReadUInt32(); + checkSum = reader.ReadUInt32(); + subsystem = reader.ReadUInt16(); + dllCharacteristics = reader.ReadUInt16(); + sizeOfStackReserve = read4Or8(reader); + sizeOfStackCommit = read4Or8(reader); + sizeOfHeapReserve = read4Or8(reader); + sizeOfHeapCommit = read4Or8(reader); + loaderFlags = reader.ReadUInt32(); + numberOfRvaAndSizes = reader.ReadUInt32(); + + dataDirectories = new DataDirectory[16]; + for (int i = 0; i < dataDirectories.Length; i++) { + dataDirectories[i].virtualAddress = reader.ReadUInt32(); + dataDirectories[i].size = reader.ReadUInt32(); + } + } + + ulong read4Or8(BinaryReader reader) { + if (is32bit()) + return reader.ReadUInt32(); + return reader.ReadUInt64(); + } + + public bool is32bit() { + return magic != 0x20B; + } + } +} diff --git a/de4dot.code/PE/PeImage.cs b/de4dot.code/PE/PeImage.cs new file mode 100644 index 00000000..97a7df41 --- /dev/null +++ b/de4dot.code/PE/PeImage.cs @@ -0,0 +1,88 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.IO; + +namespace de4dot.PE { + class PeImage { + BinaryReader reader; + BinaryWriter writer; + FileHeader fileHeader; + OptionalHeader optionalHeader; + SectionHeader[] sectionHeaders; + + public PeImage(byte[] data) + : this(new MemoryStream(data)) { + } + + public PeImage(Stream stream) { + reader = new BinaryReader(stream); + writer = new BinaryWriter(stream); + + init(); + } + + void seek(uint position) { + reader.BaseStream.Position = position; + } + + void skip(int bytes) { + reader.BaseStream.Position += bytes; + } + + void init() { + seek(0); + if (reader.ReadUInt16() != 0x5A4D) + throw new BadImageFormatException("Not a PE file"); + skip(29 * 2); + seek(reader.ReadUInt32()); + + if (reader.ReadUInt32() != 0x4550) + throw new BadImageFormatException("Not a PE file"); + fileHeader = new FileHeader(reader); + optionalHeader = new OptionalHeader(reader); + + sectionHeaders = new SectionHeader[fileHeader.numberOfSections]; + for (int i = 0; i < sectionHeaders.Length; i++) + sectionHeaders[i] = new SectionHeader(reader); + } + + SectionHeader getSectionHeader(uint rva) { + for (int i = 0; i < sectionHeaders.Length; i++) { + var section = sectionHeaders[i]; + if (section.virtualAddress <= rva && rva < section.virtualAddress + section.virtualSize) + return section; + } + return null; + } + + uint rvaToOffset(uint rva) { + var section = getSectionHeader(rva); + if (section == null) + throw new ApplicationException(string.Format("Invalid RVA {0:X8}", rva)); + return rva - section.virtualAddress + section.pointerToRawData; + } + + public void write(uint rva, byte[] data) { + seek(rvaToOffset(rva)); + writer.Write(data); + } + } +} diff --git a/de4dot.code/PE/SectionHeader.cs b/de4dot.code/PE/SectionHeader.cs new file mode 100644 index 00000000..bce7aa02 --- /dev/null +++ b/de4dot.code/PE/SectionHeader.cs @@ -0,0 +1,62 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System.IO; +using System.Text; + +namespace de4dot.PE { + class SectionHeader { + public byte[] name; + public uint virtualSize; + public uint virtualAddress; + public uint sizeOfRawData; + public uint pointerToRawData; + public uint pointerToRelocations; + public uint pointerToLinenumbers; + public ushort numberOfRelocations; + public ushort numberOfLinenumbers; + public uint characteristics; + public string displayName; + + public SectionHeader(BinaryReader reader) { + name = reader.ReadBytes(8); + virtualSize = reader.ReadUInt32(); + virtualAddress = reader.ReadUInt32(); + sizeOfRawData = reader.ReadUInt32(); + pointerToRawData = reader.ReadUInt32(); + pointerToRelocations = reader.ReadUInt32(); + pointerToLinenumbers = reader.ReadUInt32(); + numberOfRelocations = reader.ReadUInt16(); + numberOfLinenumbers = reader.ReadUInt16(); + characteristics = reader.ReadUInt32(); + + var sb = new StringBuilder(name.Length); + foreach (var c in name) { + if (c == 0) + break; + sb.Append((char)c); + } + displayName = sb.ToString(); + } + + public override string ToString() { + return string.Format("{0:X8} {1:X8} {2:X8} - {3}", virtualAddress, virtualSize, sizeOfRawData, displayName); + } + } +} diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 0213a9a4..5fb54e29 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -103,6 +103,10 @@ + + + +