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="ObfuscatedFile.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="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="renamer\DefinitionsRenamer.cs" />
|
||||
|
|
Loading…
Reference in New Issue
Block a user