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,
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
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;
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -109,7 +109,10 @@
|
|||
<Compile Include="NameRegexes.cs" />
|
||||
<Compile Include="ObfuscatedFile.cs" />
|
||||
<Compile Include="Option.cs" />
|
||||
<Compile Include="PE\Cor20Header.cs" />
|
||||
<Compile Include="PE\DataDirectory.cs" />
|
||||
<Compile Include="PE\FileHeader.cs" />
|
||||
<Compile Include="PE\IFileLocation.cs" />
|
||||
<Compile Include="PE\OptionalHeader.cs" />
|
||||
<Compile Include="PE\PeImage.cs" />
|
||||
<Compile Include="PE\SectionHeader.cs" />
|
||||
|
|
Loading…
Reference in New Issue
Block a user