Add .NET header and a method to more safely write to a .NET PE image
This commit is contained in:
parent
61b1f7a06a
commit
9c83c22469
96
de4dot.code/PE/Cor20Header.cs
Normal file
96
de4dot.code/PE/Cor20Header.cs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
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 {
|
||||||
|
class Cor20Header : IFileLocation {
|
||||||
|
public uint cb;
|
||||||
|
public ushort majorRuntimeVersion;
|
||||||
|
public ushort minorRuntimeVersion;
|
||||||
|
public DataDirectory metaData;
|
||||||
|
public uint flags;
|
||||||
|
public uint entryPointToken;
|
||||||
|
public DataDirectory resources;
|
||||||
|
public DataDirectory strongNameSignature;
|
||||||
|
public DataDirectory codeManagerTable;
|
||||||
|
public DataDirectory vtableFixups;
|
||||||
|
public DataDirectory exportAddressTableJumps;
|
||||||
|
public DataDirectory managedNativeHeader;
|
||||||
|
|
||||||
|
uint mdOffset, mdHeaderLength;
|
||||||
|
public uint MetadataOffset {
|
||||||
|
get { return mdOffset; }
|
||||||
|
}
|
||||||
|
public uint MetadataHeaderLength {
|
||||||
|
get { return mdHeaderLength; }
|
||||||
|
}
|
||||||
|
|
||||||
|
uint offset;
|
||||||
|
public uint Offset {
|
||||||
|
get { return offset; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Length {
|
||||||
|
get { return 18 * 4; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cor20Header(BinaryReader reader) {
|
||||||
|
offset = (uint)reader.BaseStream.Position;
|
||||||
|
cb = reader.ReadUInt32();
|
||||||
|
majorRuntimeVersion = reader.ReadUInt16();
|
||||||
|
minorRuntimeVersion = reader.ReadUInt16();
|
||||||
|
metaData.read(reader);
|
||||||
|
flags = reader.ReadUInt32();
|
||||||
|
entryPointToken = reader.ReadUInt32();
|
||||||
|
resources.read(reader);
|
||||||
|
strongNameSignature.read(reader);
|
||||||
|
codeManagerTable.read(reader);
|
||||||
|
vtableFixups.read(reader);
|
||||||
|
exportAddressTableJumps.read(reader);
|
||||||
|
managedNativeHeader.read(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initMetadataTable(BinaryReader reader) {
|
||||||
|
if (reader.ReadUInt32() != 0x424A5342)
|
||||||
|
return;
|
||||||
|
mdOffset = (uint)reader.BaseStream.Position - 4;
|
||||||
|
reader.ReadUInt16(); // major version
|
||||||
|
reader.ReadUInt16(); // minor version
|
||||||
|
reader.ReadUInt32(); // reserved
|
||||||
|
int slen = reader.ReadInt32();
|
||||||
|
reader.BaseStream.Position += slen;
|
||||||
|
reader.ReadUInt16(); // flags
|
||||||
|
int streams = reader.ReadUInt16();
|
||||||
|
for (int i = 0; i < streams; i++) {
|
||||||
|
uint offset = reader.ReadUInt32();
|
||||||
|
uint size = reader.ReadUInt32();
|
||||||
|
skipString(reader);
|
||||||
|
}
|
||||||
|
mdHeaderLength = (uint)reader.BaseStream.Position - mdOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipString(BinaryReader reader) {
|
||||||
|
while (reader.ReadByte() != 0) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
reader.BaseStream.Position = (reader.BaseStream.Position + 3) & ~3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
de4dot.code/PE/DataDirectory.cs
Normal file
36
de4dot.code/PE/DataDirectory.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
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 void read(BinaryReader reader) {
|
||||||
|
virtualAddress = reader.ReadUInt32();
|
||||||
|
size = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
return string.Format("{0:X8} {1:X8}", virtualAddress, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ namespace de4dot.PE {
|
||||||
amd64 = 0x8664,
|
amd64 = 0x8664,
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileHeader {
|
class FileHeader : IFileLocation {
|
||||||
public Machine machine;
|
public Machine machine;
|
||||||
public ushort numberOfSections;
|
public ushort numberOfSections;
|
||||||
public uint timeDateStamp;
|
public uint timeDateStamp;
|
||||||
|
@ -35,7 +35,17 @@ namespace de4dot.PE {
|
||||||
public ushort sizeOfOptionalHeader;
|
public ushort sizeOfOptionalHeader;
|
||||||
public ushort characteristics;
|
public ushort characteristics;
|
||||||
|
|
||||||
|
uint offset;
|
||||||
|
public uint Offset {
|
||||||
|
get { return offset; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Length {
|
||||||
|
get { return 5 * 4; }
|
||||||
|
}
|
||||||
|
|
||||||
public FileHeader(BinaryReader reader) {
|
public FileHeader(BinaryReader reader) {
|
||||||
|
offset = (uint)reader.BaseStream.Position;
|
||||||
machine = (Machine)reader.ReadUInt16();
|
machine = (Machine)reader.ReadUInt16();
|
||||||
numberOfSections = reader.ReadUInt16();
|
numberOfSections = reader.ReadUInt16();
|
||||||
timeDateStamp = reader.ReadUInt32();
|
timeDateStamp = reader.ReadUInt32();
|
||||||
|
|
25
de4dot.code/PE/IFileLocation.cs
Normal file
25
de4dot.code/PE/IFileLocation.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace de4dot.PE {
|
||||||
|
interface IFileLocation {
|
||||||
|
uint Offset { get; }
|
||||||
|
uint Length { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,16 +20,7 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace de4dot.PE {
|
namespace de4dot.PE {
|
||||||
struct DataDirectory {
|
class OptionalHeader : IFileLocation {
|
||||||
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 ushort magic;
|
||||||
public byte majorLinkerVersion;
|
public byte majorLinkerVersion;
|
||||||
public byte minorLinkerVersion;
|
public byte minorLinkerVersion;
|
||||||
|
@ -62,7 +53,17 @@ namespace de4dot.PE {
|
||||||
public uint numberOfRvaAndSizes;
|
public uint numberOfRvaAndSizes;
|
||||||
public DataDirectory[] dataDirectories;
|
public DataDirectory[] dataDirectories;
|
||||||
|
|
||||||
|
uint offset, length;
|
||||||
|
public uint Offset {
|
||||||
|
get { return offset; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Length {
|
||||||
|
get { return length; }
|
||||||
|
}
|
||||||
|
|
||||||
public OptionalHeader(BinaryReader reader) {
|
public OptionalHeader(BinaryReader reader) {
|
||||||
|
offset = (uint)reader.BaseStream.Position;
|
||||||
magic = reader.ReadUInt16();
|
magic = reader.ReadUInt16();
|
||||||
majorLinkerVersion = reader.ReadByte();
|
majorLinkerVersion = reader.ReadByte();
|
||||||
minorLinkerVersion = reader.ReadByte();
|
minorLinkerVersion = reader.ReadByte();
|
||||||
|
@ -96,10 +97,9 @@ namespace de4dot.PE {
|
||||||
numberOfRvaAndSizes = reader.ReadUInt32();
|
numberOfRvaAndSizes = reader.ReadUInt32();
|
||||||
|
|
||||||
dataDirectories = new DataDirectory[16];
|
dataDirectories = new DataDirectory[16];
|
||||||
for (int i = 0; i < dataDirectories.Length; i++) {
|
for (int i = 0; i < dataDirectories.Length; i++)
|
||||||
dataDirectories[i].virtualAddress = reader.ReadUInt32();
|
dataDirectories[i].read(reader);
|
||||||
dataDirectories[i].size = reader.ReadUInt32();
|
length = (uint)reader.BaseStream.Position - offset;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong read4Or8(BinaryReader reader) {
|
ulong read4Or8(BinaryReader reader) {
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace de4dot.PE {
|
||||||
FileHeader fileHeader;
|
FileHeader fileHeader;
|
||||||
OptionalHeader optionalHeader;
|
OptionalHeader optionalHeader;
|
||||||
SectionHeader[] sectionHeaders;
|
SectionHeader[] sectionHeaders;
|
||||||
|
Cor20Header cor20Header;
|
||||||
|
SectionHeader dotNetSection;
|
||||||
|
|
||||||
public PeImage(byte[] data)
|
public PeImage(byte[] data)
|
||||||
: this(new MemoryStream(data)) {
|
: this(new MemoryStream(data)) {
|
||||||
|
@ -43,6 +45,10 @@ namespace de4dot.PE {
|
||||||
reader.BaseStream.Position = position;
|
reader.BaseStream.Position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void seekRva(uint rva) {
|
||||||
|
seek(rvaToOffset(rva));
|
||||||
|
}
|
||||||
|
|
||||||
void skip(int bytes) {
|
void skip(int bytes) {
|
||||||
reader.BaseStream.Position += bytes;
|
reader.BaseStream.Position += bytes;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +68,15 @@ namespace de4dot.PE {
|
||||||
sectionHeaders = new SectionHeader[fileHeader.numberOfSections];
|
sectionHeaders = new SectionHeader[fileHeader.numberOfSections];
|
||||||
for (int i = 0; i < sectionHeaders.Length; i++)
|
for (int i = 0; i < sectionHeaders.Length; i++)
|
||||||
sectionHeaders[i] = new SectionHeader(reader);
|
sectionHeaders[i] = new SectionHeader(reader);
|
||||||
|
|
||||||
|
uint netOffset = optionalHeader.dataDirectories[14].virtualAddress;
|
||||||
|
if (netOffset != 0) {
|
||||||
|
seekRva(netOffset);
|
||||||
|
cor20Header = new Cor20Header(reader);
|
||||||
|
dotNetSection = getSectionHeader(netOffset);
|
||||||
|
seekRva(cor20Header.metaData.virtualAddress);
|
||||||
|
cor20Header.initMetadataTable(reader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionHeader getSectionHeader(uint rva) {
|
SectionHeader getSectionHeader(uint rva) {
|
||||||
|
@ -80,18 +95,43 @@ namespace de4dot.PE {
|
||||||
return rva - section.virtualAddress + section.pointerToRawData;
|
return rva - section.virtualAddress + section.pointerToRawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool intersect(uint offset1, uint length1, uint offset2, uint length2) {
|
||||||
|
return !(offset1 + length1 <= offset2 || offset2 + length2 <= offset1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect(uint offset, uint length, IFileLocation location) {
|
||||||
|
return intersect(offset, length, location.Offset, location.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool dotNetSafeWrite(uint rva, byte[] data) {
|
||||||
|
if (cor20Header != null) {
|
||||||
|
uint offset = rvaToOffset(rva);
|
||||||
|
uint length = (uint)data.Length;
|
||||||
|
|
||||||
|
if (!dotNetSection.isInside(offset, length))
|
||||||
|
return false;
|
||||||
|
if (intersect(offset, length, cor20Header))
|
||||||
|
return false;
|
||||||
|
if (intersect(offset, length, cor20Header.MetadataOffset, cor20Header.MetadataHeaderLength))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(rva, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void write(uint rva, byte[] data) {
|
public void write(uint rva, byte[] data) {
|
||||||
seek(rvaToOffset(rva));
|
seekRva(rva);
|
||||||
writer.Write(data);
|
writer.Write(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readInt32(uint rva) {
|
public int readInt32(uint rva) {
|
||||||
seek(rvaToOffset(rva));
|
seekRva(rva);
|
||||||
return reader.ReadInt32();
|
return reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] readBytes(uint rva, int size) {
|
public byte[] readBytes(uint rva, int size) {
|
||||||
seek(rvaToOffset(rva));
|
seekRva(rva);
|
||||||
return reader.ReadBytes(size);
|
return reader.ReadBytes(size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace de4dot.PE {
|
namespace de4dot.PE {
|
||||||
class SectionHeader {
|
class SectionHeader : IFileLocation {
|
||||||
public byte[] name;
|
public byte[] name;
|
||||||
public uint virtualSize;
|
public uint virtualSize;
|
||||||
public uint virtualAddress;
|
public uint virtualAddress;
|
||||||
|
@ -34,7 +34,17 @@ namespace de4dot.PE {
|
||||||
public uint characteristics;
|
public uint characteristics;
|
||||||
public string displayName;
|
public string displayName;
|
||||||
|
|
||||||
|
uint offset;
|
||||||
|
public uint Offset {
|
||||||
|
get { return offset; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Length {
|
||||||
|
get { return 10 * 4; }
|
||||||
|
}
|
||||||
|
|
||||||
public SectionHeader(BinaryReader reader) {
|
public SectionHeader(BinaryReader reader) {
|
||||||
|
offset = (uint)reader.BaseStream.Position;
|
||||||
name = reader.ReadBytes(8);
|
name = reader.ReadBytes(8);
|
||||||
virtualSize = reader.ReadUInt32();
|
virtualSize = reader.ReadUInt32();
|
||||||
virtualAddress = reader.ReadUInt32();
|
virtualAddress = reader.ReadUInt32();
|
||||||
|
@ -55,6 +65,10 @@ namespace de4dot.PE {
|
||||||
displayName = sb.ToString();
|
displayName = sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool isInside(uint offset, uint length) {
|
||||||
|
return offset >= pointerToRawData && offset + length <= pointerToRawData + sizeOfRawData;
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return string.Format("{0:X8} {1:X8} {2:X8} - {3}", virtualAddress, virtualSize, sizeOfRawData, displayName);
|
return string.Format("{0:X8} {1:X8} {2:X8} - {3}", virtualAddress, virtualSize, sizeOfRawData, displayName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,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\Cor20Header.cs" />
|
||||||
|
<Compile Include="PE\DataDirectory.cs" />
|
||||||
<Compile Include="PE\FileHeader.cs" />
|
<Compile Include="PE\FileHeader.cs" />
|
||||||
|
<Compile Include="PE\IFileLocation.cs" />
|
||||||
<Compile Include="PE\OptionalHeader.cs" />
|
<Compile Include="PE\OptionalHeader.cs" />
|
||||||
<Compile Include="PE\PeImage.cs" />
|
<Compile Include="PE\PeImage.cs" />
|
||||||
<Compile Include="PE\SectionHeader.cs" />
|
<Compile Include="PE\SectionHeader.cs" />
|
||||||
|
|
Loading…
Reference in New Issue
Block a user