Add PE image reader/writer code
This commit is contained in:
parent
349ebc4e72
commit
794b9dfd77
48
de4dot.code/PE/FileHeader.cs
Normal file
48
de4dot.code/PE/FileHeader.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
115
de4dot.code/PE/OptionalHeader.cs
Normal file
115
de4dot.code/PE/OptionalHeader.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
de4dot.code/PE/PeImage.cs
Normal file
88
de4dot.code/PE/PeImage.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
de4dot.code/PE/SectionHeader.cs
Normal file
62
de4dot.code/PE/SectionHeader.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -103,6 +103,10 @@
|
||||||
<Compile Include="NameRegexes.cs" />
|
<Compile Include="NameRegexes.cs" />
|
||||||
<Compile Include="ObfuscatedFile.cs" />
|
<Compile Include="ObfuscatedFile.cs" />
|
||||||
<Compile Include="Option.cs" />
|
<Compile Include="Option.cs" />
|
||||||
|
<Compile Include="PE\FileHeader.cs" />
|
||||||
|
<Compile Include="PE\OptionalHeader.cs" />
|
||||||
|
<Compile Include="PE\PeImage.cs" />
|
||||||
|
<Compile Include="PE\SectionHeader.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="renamer\DefinitionsRenamer.cs" />
|
<Compile Include="renamer\DefinitionsRenamer.cs" />
|
||||||
|
|
Loading…
Reference in New Issue
Block a user