diff --git a/de4dot.code/PE/Cor20Header.cs b/de4dot.code/PE/Cor20Header.cs
new file mode 100644
index 00000000..8664b6aa
--- /dev/null
+++ b/de4dot.code/PE/Cor20Header.cs
@@ -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 .
+*/
+
+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;
+ }
+ }
+}
diff --git a/de4dot.code/PE/DataDirectory.cs b/de4dot.code/PE/DataDirectory.cs
new file mode 100644
index 00000000..9dfe6a49
--- /dev/null
+++ b/de4dot.code/PE/DataDirectory.cs
@@ -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 .
+*/
+
+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);
+ }
+ }
+}
diff --git a/de4dot.code/PE/FileHeader.cs b/de4dot.code/PE/FileHeader.cs
index cbe5ea64..8bff853c 100644
--- a/de4dot.code/PE/FileHeader.cs
+++ b/de4dot.code/PE/FileHeader.cs
@@ -26,7 +26,7 @@ namespace de4dot.PE {
amd64 = 0x8664,
}
- class FileHeader {
+ class FileHeader : IFileLocation {
public Machine machine;
public ushort numberOfSections;
public uint timeDateStamp;
@@ -35,7 +35,17 @@ namespace de4dot.PE {
public ushort sizeOfOptionalHeader;
public ushort characteristics;
+ uint offset;
+ public uint Offset {
+ get { return offset; }
+ }
+
+ public uint Length {
+ get { return 5 * 4; }
+ }
+
public FileHeader(BinaryReader reader) {
+ offset = (uint)reader.BaseStream.Position;
machine = (Machine)reader.ReadUInt16();
numberOfSections = reader.ReadUInt16();
timeDateStamp = reader.ReadUInt32();
diff --git a/de4dot.code/PE/IFileLocation.cs b/de4dot.code/PE/IFileLocation.cs
new file mode 100644
index 00000000..a69f422d
--- /dev/null
+++ b/de4dot.code/PE/IFileLocation.cs
@@ -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 .
+*/
+
+namespace de4dot.PE {
+ interface IFileLocation {
+ uint Offset { get; }
+ uint Length { get; }
+ }
+}
diff --git a/de4dot.code/PE/OptionalHeader.cs b/de4dot.code/PE/OptionalHeader.cs
index b7f5ca1c..91dbf3ce 100644
--- a/de4dot.code/PE/OptionalHeader.cs
+++ b/de4dot.code/PE/OptionalHeader.cs
@@ -20,16 +20,7 @@
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 {
+ class OptionalHeader : IFileLocation {
public ushort magic;
public byte majorLinkerVersion;
public byte minorLinkerVersion;
@@ -62,7 +53,17 @@ namespace de4dot.PE {
public uint numberOfRvaAndSizes;
public DataDirectory[] dataDirectories;
+ uint offset, length;
+ public uint Offset {
+ get { return offset; }
+ }
+
+ public uint Length {
+ get { return length; }
+ }
+
public OptionalHeader(BinaryReader reader) {
+ offset = (uint)reader.BaseStream.Position;
magic = reader.ReadUInt16();
majorLinkerVersion = reader.ReadByte();
minorLinkerVersion = reader.ReadByte();
@@ -96,10 +97,9 @@ namespace de4dot.PE {
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();
- }
+ for (int i = 0; i < dataDirectories.Length; i++)
+ dataDirectories[i].read(reader);
+ length = (uint)reader.BaseStream.Position - offset;
}
ulong read4Or8(BinaryReader reader) {
diff --git a/de4dot.code/PE/PeImage.cs b/de4dot.code/PE/PeImage.cs
index efb4cd89..09302fd3 100644
--- a/de4dot.code/PE/PeImage.cs
+++ b/de4dot.code/PE/PeImage.cs
@@ -27,6 +27,8 @@ namespace de4dot.PE {
FileHeader fileHeader;
OptionalHeader optionalHeader;
SectionHeader[] sectionHeaders;
+ Cor20Header cor20Header;
+ SectionHeader dotNetSection;
public PeImage(byte[] data)
: this(new MemoryStream(data)) {
@@ -43,6 +45,10 @@ namespace de4dot.PE {
reader.BaseStream.Position = position;
}
+ void seekRva(uint rva) {
+ seek(rvaToOffset(rva));
+ }
+
void skip(int bytes) {
reader.BaseStream.Position += bytes;
}
@@ -62,6 +68,15 @@ namespace de4dot.PE {
sectionHeaders = new SectionHeader[fileHeader.numberOfSections];
for (int i = 0; i < sectionHeaders.Length; i++)
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) {
@@ -80,18 +95,43 @@ namespace de4dot.PE {
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) {
- seek(rvaToOffset(rva));
+ seekRva(rva);
writer.Write(data);
}
public int readInt32(uint rva) {
- seek(rvaToOffset(rva));
+ seekRva(rva);
return reader.ReadInt32();
}
public byte[] readBytes(uint rva, int size) {
- seek(rvaToOffset(rva));
+ seekRva(rva);
return reader.ReadBytes(size);
}
}
diff --git a/de4dot.code/PE/SectionHeader.cs b/de4dot.code/PE/SectionHeader.cs
index bce7aa02..052df9d8 100644
--- a/de4dot.code/PE/SectionHeader.cs
+++ b/de4dot.code/PE/SectionHeader.cs
@@ -21,7 +21,7 @@ using System.IO;
using System.Text;
namespace de4dot.PE {
- class SectionHeader {
+ class SectionHeader : IFileLocation {
public byte[] name;
public uint virtualSize;
public uint virtualAddress;
@@ -34,7 +34,17 @@ namespace de4dot.PE {
public uint characteristics;
public string displayName;
+ uint offset;
+ public uint Offset {
+ get { return offset; }
+ }
+
+ public uint Length {
+ get { return 10 * 4; }
+ }
+
public SectionHeader(BinaryReader reader) {
+ offset = (uint)reader.BaseStream.Position;
name = reader.ReadBytes(8);
virtualSize = reader.ReadUInt32();
virtualAddress = reader.ReadUInt32();
@@ -55,6 +65,10 @@ namespace de4dot.PE {
displayName = sb.ToString();
}
+ public bool isInside(uint offset, uint length) {
+ return offset >= pointerToRawData && offset + length <= pointerToRawData + sizeOfRawData;
+ }
+
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 7548bd53..81d00452 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -109,7 +109,10 @@
+
+
+