diff --git a/de4dot.code/PE/Cor20Header.cs b/de4dot.code/PE/Cor20Header.cs
index 8664b6aa..e3b878f8 100644
--- a/de4dot.code/PE/Cor20Header.cs
+++ b/de4dot.code/PE/Cor20Header.cs
@@ -33,13 +33,15 @@ namespace de4dot.PE {
public DataDirectory vtableFixups;
public DataDirectory exportAddressTableJumps;
public DataDirectory managedNativeHeader;
+ public Metadata metadata;
+ BinaryReader reader;
- uint mdOffset, mdHeaderLength;
public uint MetadataOffset {
- get { return mdOffset; }
+ get { return metadata.Offset; }
}
+
public uint MetadataHeaderLength {
- get { return mdHeaderLength; }
+ get { return metadata.HeaderLength; }
}
uint offset;
@@ -52,6 +54,7 @@ namespace de4dot.PE {
}
public Cor20Header(BinaryReader reader) {
+ this.reader = reader;
offset = (uint)reader.BaseStream.Position;
cb = reader.ReadUInt32();
majorRuntimeVersion = reader.ReadUInt16();
@@ -67,30 +70,12 @@ namespace de4dot.PE {
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;
+ public void initMetadataTable() {
+ metadata = new Metadata(reader);
}
- void skipString(BinaryReader reader) {
- while (reader.ReadByte() != 0) {
- // nothing
- }
- reader.BaseStream.Position = (reader.BaseStream.Position + 3) & ~3;
+ public MetadataTables createMetadataTables() {
+ return new MetadataTables(reader, metadata);
}
}
}
diff --git a/de4dot.code/PE/DotNetStream.cs b/de4dot.code/PE/DotNetStream.cs
new file mode 100644
index 00000000..18c5e23d
--- /dev/null
+++ b/de4dot.code/PE/DotNetStream.cs
@@ -0,0 +1,46 @@
+/*
+ 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 DotNetStream : IFileLocation {
+ public string name;
+ public uint fileOffset;
+ public uint length;
+
+ public uint Offset {
+ get { return fileOffset; }
+ }
+
+ public uint Length {
+ get { return length; }
+ }
+
+ public DotNetStream(string name, uint fileOffset, uint length) {
+ this.name = name;
+ this.fileOffset = fileOffset;
+ this.length = length;
+ }
+
+ public override string ToString() {
+ return string.Format("{0:X8} {1:X8} {2}", fileOffset, length, name);
+ }
+ }
+}
diff --git a/de4dot.code/PE/Metadata.cs b/de4dot.code/PE/Metadata.cs
new file mode 100644
index 00000000..a985ea7a
--- /dev/null
+++ b/de4dot.code/PE/Metadata.cs
@@ -0,0 +1,110 @@
+/*
+ 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;
+using System.IO;
+using System.Text;
+
+namespace de4dot.PE {
+ class Metadata : IFileLocation {
+ uint magic;
+ ushort majorVersion, minorVersion;
+ uint reserved;
+ string versionString;
+ ushort flags;
+ DotNetStream[] streams;
+
+ uint offset, headerLength, length;
+
+ public uint Offset {
+ get { return offset; }
+ }
+
+ public uint Length {
+ get { return length; }
+ }
+
+ public uint HeaderLength {
+ get { return headerLength; }
+ }
+
+ public uint HeaderEnd {
+ get { return offset + headerLength; }
+ }
+
+ public Metadata(BinaryReader reader) {
+ magic = reader.ReadUInt32();
+ if (magic != 0x424A5342)
+ return;
+
+ offset = (uint)reader.BaseStream.Position - 4;
+ majorVersion = reader.ReadUInt16();
+ minorVersion = reader.ReadUInt16();
+ reserved = reader.ReadUInt32();
+ versionString = readString(reader, reader.ReadInt32());
+ flags = reader.ReadUInt16();
+ int numStreams = reader.ReadUInt16();
+ streams = new DotNetStream[numStreams];
+ uint lastOffset = offset;
+ for (int i = 0; i < numStreams; i++) {
+ uint fileOffset = offset + reader.ReadUInt32();
+ uint size = reader.ReadUInt32();
+ string name = readAsciizString(reader);
+ streams[i] = new DotNetStream(name, fileOffset, size);
+ lastOffset = Math.Max(lastOffset, fileOffset + size);
+ }
+ lastOffset = Math.Max(lastOffset, (uint)reader.BaseStream.Position);
+ length = lastOffset - offset;
+ headerLength = (uint)reader.BaseStream.Position - offset;
+ }
+
+ public DotNetStream getStream(string name) {
+ foreach (var stream in streams) {
+ if (stream.name == name)
+ return stream;
+ }
+ return null;
+ }
+
+ string readString(BinaryReader reader, int len) {
+ var sb = new StringBuilder(len);
+ var nextPos = reader.BaseStream.Position + len;
+ for (int i = 0; i < len; i++) {
+ byte b = reader.ReadByte();
+ if (b == 0)
+ break;
+ sb.Append((char)b);
+ }
+ reader.BaseStream.Position = nextPos;
+ return sb.ToString();
+ }
+
+ string readAsciizString(BinaryReader reader) {
+ var sb = new StringBuilder();
+ while (true) {
+ byte b = reader.ReadByte();
+ if (b == 0)
+ break;
+ sb.Append((char)b);
+ }
+ reader.BaseStream.Position = (reader.BaseStream.Position + 3) & ~3;
+ return sb.ToString();
+ }
+ }
+}
diff --git a/de4dot.code/PE/MetadataTables.cs b/de4dot.code/PE/MetadataTables.cs
new file mode 100644
index 00000000..8a5f0ee4
--- /dev/null
+++ b/de4dot.code/PE/MetadataTables.cs
@@ -0,0 +1,151 @@
+/*
+ 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;
+using System.IO;
+
+namespace de4dot.PE {
+ using MVT = MetadataVarType;
+
+ class MetadataTables {
+ BinaryReader reader;
+ Metadata metadata;
+ byte heapOffsetSizes;
+ MetadataType[] metadataTypes = new MetadataType[64];
+
+ public MetadataTables(BinaryReader reader, Metadata metadata) {
+ this.reader = reader;
+ this.metadata = metadata;
+ init();
+ }
+
+ public MetadataType getMetadataType(MetadataIndex index) {
+ return metadataTypes[(int)index];
+ }
+
+ void seek(uint fileOffset) {
+ reader.BaseStream.Position = fileOffset;
+ }
+
+ static MetadataVarType[] metadataVarType = new MetadataVarType[] {
+ MVT.byte2, MVT.stringIndex, MVT.guidIndex, MVT.guidIndex, MVT.guidIndex, MVT.end, // 0
+ MVT.resolutionScope, MVT.stringIndex, MVT.stringIndex, MVT.end, // 1
+ MVT.byte4, MVT.stringIndex, MVT.stringIndex, MVT.typeDefOrRef, MVT.fieldIndex, MVT.methodDefIndex, MVT.end, // 2
+ MVT.end, // 3
+ MVT.byte2, MVT.stringIndex, MVT.blobIndex, MVT.end, // 4
+ MVT.end, // 5
+ MVT.byte4, MVT.byte2, MVT.byte2, MVT.stringIndex, MVT.blobIndex, MVT.paramIndex, MVT.end, // 6
+ MVT.end, // 7
+ MVT.byte2, MVT.byte2, MVT.stringIndex, MVT.end, // 8
+ MVT.typeDefIndex, MVT.typeDefOrRef, MVT.end, // 9
+ MVT.memberRefParent, MVT.stringIndex, MVT.blobIndex, MVT.end, // 10
+ MVT.byte1, MVT.byte1, MVT.hasConstant, MVT.blobIndex, MVT.end, // 11
+ MVT.hasCustomAttribute, MVT.customAttributeType, MVT.blobIndex, MVT.end,// 12
+ MVT.hasFieldMarshal, MVT.blobIndex, MVT.end, // 13
+ MVT.byte2, MVT.hasDeclSecurity, MVT.blobIndex, MVT.end, // 14
+ MVT.byte2, MVT.byte4, MVT.typeDefIndex, MVT.end, // 15
+ MVT.byte4, MVT.fieldIndex, MVT.end, // 16
+ MVT.blobIndex, MVT.end, // 17
+ MVT.typeDefIndex, MVT.eventIndex, MVT.end, // 18
+ MVT.end, // 19
+ MVT.byte2, MVT.stringIndex, MVT.typeDefOrRef, MVT.end, // 20
+ MVT.typeDefIndex, MVT.propertyIndex, MVT.end, // 21
+ MVT.end, // 22
+ MVT.byte2, MVT.stringIndex, MVT.blobIndex, MVT.end, // 23
+ MVT.byte2, MVT.methodDefIndex, MVT.hasSemantics, MVT.end, // 24
+ MVT.typeDefIndex, MVT.methodDefOrRef, MVT.methodDefOrRef, MVT.end, // 25
+ MVT.stringIndex, MVT.end, // 26
+ MVT.blobIndex, MVT.end, // 27
+ MVT.byte2, MVT.memberForwarded, MVT.stringIndex, MVT.moduleRefIndex, MVT.end, // 28
+ MVT.byte4, MVT.fieldIndex, MVT.end, // 29
+ MVT.end, // 30
+ MVT.end, // 31
+ MVT.byte4, MVT.byte2, MVT.byte2, MVT.byte2, MVT.byte2, MVT.byte4, MVT.blobIndex, MVT.stringIndex, MVT.stringIndex, MVT.end, // 32
+ MVT.byte4, MVT.end, // 33
+ MVT.byte4, MVT.byte4, MVT.byte4, MVT.end, // 34
+ MVT.byte2, MVT.byte2, MVT.byte2, MVT.byte2, MVT.byte4, MVT.blobIndex, MVT.stringIndex, MVT.stringIndex, MVT.blobIndex, MVT.end, // 35
+ MVT.byte4, MVT.assemblyRefIndex, MVT.end, // 36
+ MVT.byte4, MVT.byte4, MVT.byte4, MVT.assemblyRefIndex, MVT.end, // 37
+ MVT.byte4, MVT.stringIndex, MVT.blobIndex, MVT.end, // 38
+ MVT.byte4, MVT.byte4, MVT.stringIndex, MVT.stringIndex, MVT.implementation, MVT.end,// 39
+ MVT.byte4, MVT.byte4, MVT.stringIndex, MVT.implementation, MVT.end, // 40
+ MVT.typeDefIndex, MVT.typeDefIndex, MVT.end, // 41
+ MVT.byte2, MVT.byte2, MVT.typeOrMethodDef, MVT.stringIndex, MVT.end, // 42
+ MVT.end, // 43
+ MVT.genericParamIndex, MVT.typeDefOrRef, MVT.end, // 44
+ MVT.end, // 45
+ MVT.end, // 46
+ MVT.end, // 47
+ MVT.end, // 48
+ MVT.end, // 49
+ MVT.end, // 50
+ MVT.end, // 51
+ MVT.end, // 52
+ MVT.end, // 53
+ MVT.end, // 54
+ MVT.end, // 55
+ MVT.end, // 56
+ MVT.end, // 57
+ MVT.end, // 58
+ MVT.end, // 59
+ MVT.end, // 60
+ MVT.end, // 61
+ MVT.end, // 62
+ MVT.end, // 63
+
+ MVT.stop
+ };
+
+ void init() {
+ var streamTable = metadata.getStream("#~");
+ if (streamTable == null)
+ throw new ApplicationException("Could not find #~ stream");
+
+ seek(streamTable.Offset);
+ reader.ReadUInt32(); // reserved
+ reader.ReadUInt16(); // major + minor version
+ heapOffsetSizes = reader.ReadByte();
+ reader.ReadByte(); // always 1
+ ulong validMask = reader.ReadUInt64();
+ reader.ReadUInt64(); // sorted
+
+ var numRows = new uint[64];
+ for (int i = 0; validMask != 0; i++, validMask >>= 1) {
+ if ((validMask & 1) != 0)
+ numRows[i] = reader.ReadUInt32();
+ }
+
+ var builder = new MetadataTypeBuilder(heapOffsetSizes, numRows);
+ uint fileOffset = (uint)reader.BaseStream.Position;
+ for (int i = 0, j = 0; ; i++) {
+ if (metadataVarType[i] == MVT.end) {
+ var mdType = builder.create();
+ mdType.rows = numRows[j];
+ mdType.fileOffset = fileOffset;
+ fileOffset += mdType.rows * mdType.totalSize;
+ metadataTypes[j++] = mdType;
+ }
+ else if (metadataVarType[i] == MVT.stop)
+ break;
+ else
+ builder.field(metadataVarType[i]);
+ }
+ }
+ }
+}
diff --git a/de4dot.code/PE/MetadataType.cs b/de4dot.code/PE/MetadataType.cs
new file mode 100644
index 00000000..3e57a278
--- /dev/null
+++ b/de4dot.code/PE/MetadataType.cs
@@ -0,0 +1,89 @@
+/*
+ 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.Collections.Generic;
+
+namespace de4dot.PE {
+ enum MetadataIndex {
+ iModule = 0,
+ iTypeRef = 1,
+ iTypeDef = 2,
+ iField = 4,
+ iMethodDef = 6,
+ iParam = 8,
+ iInterfaceImpl = 9,
+ iMemberRef = 10,
+ iConstant = 11,
+ iCustomAttribute = 12,
+ iFieldMarshal = 13,
+ iDeclSecurity = 14,
+ iClassLayout = 15,
+ iFieldLayout = 16,
+ iStandAloneSig = 17,
+ iEventMap = 18,
+ iEvent = 20,
+ iPropertyMap = 21,
+ iProperty = 23,
+ iMethodSemantics = 24,
+ iMethodImpl = 25,
+ iModuleRef = 26,
+ iTypeSpec = 27,
+ iImplMap = 28,
+ iFieldRVA = 29,
+ iAssembly = 32,
+ iAssemblyProcessor = 33,
+ iAssemblyOS = 34,
+ iAssemblyRef = 35,
+ iAssemblyRefProcessor = 36,
+ iAssemblyRefOS = 37,
+ iFile = 38,
+ iExportedType = 39,
+ iManifestResource = 40,
+ iNestedClass = 41,
+ iGenericParam = 42,
+ iGenericParamConstraint = 44,
+ };
+
+ class MetadataType {
+ public uint fileOffset;
+ public uint rows;
+ public uint totalSize;
+ public List fields;
+
+ public MetadataType(List fields) {
+ this.fields = fields;
+ totalSize = 0;
+ foreach (var field in fields)
+ totalSize += (uint)field.size;
+ }
+
+ public override string ToString() {
+ return string.Format("MDType: {0:X8}, {1} rows, {2} bytes, {3} fields", fileOffset, rows, totalSize, fields.Count);
+ }
+ }
+
+ struct MetadataField {
+ public int offset;
+ public int size;
+
+ public override string ToString() {
+ return string.Format("offset: {0}, size {1}", offset, size);
+ }
+ }
+}
diff --git a/de4dot.code/PE/MetadataTypeBuilder.cs b/de4dot.code/PE/MetadataTypeBuilder.cs
new file mode 100644
index 00000000..c6c42948
--- /dev/null
+++ b/de4dot.code/PE/MetadataTypeBuilder.cs
@@ -0,0 +1,203 @@
+/*
+ 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;
+using System.Collections.Generic;
+
+namespace de4dot.PE {
+ enum MetadataVarType {
+ end,
+ stop,
+ byte1,
+ byte2,
+ byte4,
+ stringIndex, // index into #String heap
+ guidIndex, // index into #GUID heap
+ blobIndex, // index into #Blob heap
+ resolutionScope,
+ typeDefOrRef,
+ fieldIndex,
+ methodDefIndex,
+ paramIndex,
+ typeDefIndex,
+ eventIndex,
+ propertyIndex,
+ moduleRefIndex,
+ assemblyRefIndex,
+ genericParamIndex,
+ memberRefParent,
+ hasConstant,
+ hasCustomAttribute,
+ customAttributeType,
+ hasFieldMarshal,
+ hasDeclSecurity,
+ hasSemantics,
+ methodDefOrRef,
+ memberForwarded,
+ implementation,
+ typeOrMethodDef,
+ };
+
+ class MetadataTypeBuilder {
+ byte heapOffsetSizes;
+ uint[] numRows;
+ List fields;
+ int offset;
+
+ public MetadataTypeBuilder(byte heapOffsetSizes, uint[] numRows) {
+ this.heapOffsetSizes = heapOffsetSizes;
+ this.numRows = numRows;
+ reset();
+ }
+
+ void reset() {
+ offset = 0;
+ fields = new List();
+ }
+
+ public MetadataType create() {
+ var type = new MetadataType(fields);
+ reset();
+ return type;
+ }
+
+ public void field(MetadataVarType type) {
+ int size;
+ switch (type) {
+ case MetadataVarType.byte1:
+ size = 1;
+ break;
+ case MetadataVarType.byte2:
+ size = 2;
+ break;
+ case MetadataVarType.byte4:
+ size = 4;
+ break;
+ case MetadataVarType.stringIndex:
+ size = (heapOffsetSizes & 1) != 0 ? 4 : 2;
+ break;
+ case MetadataVarType.guidIndex:
+ size = (heapOffsetSizes & 2) != 0 ? 4 : 2;
+ break;
+ case MetadataVarType.blobIndex:
+ size = (heapOffsetSizes & 4) != 0 ? 4 : 2;
+ break;
+ case MetadataVarType.resolutionScope:
+ size = getSize(14, new MetadataIndex[] { MetadataIndex.iModule, MetadataIndex.iModuleRef, MetadataIndex.iAssemblyRef, MetadataIndex.iTypeRef });
+ break;
+ case MetadataVarType.typeDefOrRef:
+ size = getSize(14, new MetadataIndex[] { MetadataIndex.iTypeDef, MetadataIndex.iTypeRef, MetadataIndex.iTypeSpec });
+ break;
+ case MetadataVarType.memberRefParent:
+ size = getSize(13, new MetadataIndex[] { MetadataIndex.iTypeDef, MetadataIndex.iTypeRef, MetadataIndex.iModuleRef, MetadataIndex.iMethodDef, MetadataIndex.iTypeSpec });
+ break;
+ case MetadataVarType.hasConstant:
+ size = getSize(14, new MetadataIndex[] { MetadataIndex.iField, MetadataIndex.iParam, MetadataIndex.iProperty });
+ break;
+ case MetadataVarType.hasCustomAttribute:
+ size = getSize(11, new MetadataIndex[] {
+ MetadataIndex.iMethodDef, MetadataIndex.iField, MetadataIndex.iTypeRef,
+ MetadataIndex.iTypeDef, MetadataIndex.iParam, MetadataIndex.iInterfaceImpl,
+ MetadataIndex.iMemberRef, MetadataIndex.iModule /*TODO:, MetadataIndex.iPermission*/,
+ MetadataIndex.iProperty, MetadataIndex.iEvent, MetadataIndex.iStandAloneSig,
+ MetadataIndex.iModuleRef, MetadataIndex.iTypeSpec, MetadataIndex.iAssembly,
+ MetadataIndex.iAssemblyRef, MetadataIndex.iFile, MetadataIndex.iExportedType,
+ MetadataIndex.iManifestResource,
+ });
+ break;
+ case MetadataVarType.customAttributeType:
+ size = getSize(13, new MetadataIndex[] { MetadataIndex.iMethodDef, MetadataIndex.iMemberRef }); // others aren't used
+ break;
+ case MetadataVarType.hasFieldMarshal:
+ size = getSize(15, new MetadataIndex[] { MetadataIndex.iField, MetadataIndex.iParam });
+ break;
+ case MetadataVarType.hasDeclSecurity:
+ size = getSize(14, new MetadataIndex[] { MetadataIndex.iTypeDef, MetadataIndex.iMethodDef, MetadataIndex.iAssembly });
+ break;
+ case MetadataVarType.hasSemantics:
+ size = getSize(15, new MetadataIndex[] { MetadataIndex.iEvent, MetadataIndex.iProperty });
+ break;
+ case MetadataVarType.methodDefOrRef:
+ size = getSize(15, new MetadataIndex[] { MetadataIndex.iMethodDef, MetadataIndex.iMemberRef });
+ break;
+ case MetadataVarType.memberForwarded:
+ size = getSize(15, new MetadataIndex[] { MetadataIndex.iField, MetadataIndex.iMethodDef });
+ break;
+ case MetadataVarType.implementation:
+ size = getSize(14, new MetadataIndex[] { MetadataIndex.iFile, MetadataIndex.iAssemblyRef, MetadataIndex.iExportedType });
+ break;
+ case MetadataVarType.typeOrMethodDef:
+ size = getSize(15, new MetadataIndex[] { MetadataIndex.iTypeDef, MetadataIndex.iMethodDef });
+ break;
+ case MetadataVarType.fieldIndex:
+ size = getSize(MetadataIndex.iField);
+ break;
+ case MetadataVarType.methodDefIndex:
+ size = getSize(MetadataIndex.iMethodDef);
+ break;
+ case MetadataVarType.paramIndex:
+ size = getSize(MetadataIndex.iParam);
+ break;
+ case MetadataVarType.typeDefIndex:
+ size = getSize(MetadataIndex.iTypeDef);
+ break;
+ case MetadataVarType.eventIndex:
+ size = getSize(MetadataIndex.iEvent);
+ break;
+ case MetadataVarType.propertyIndex:
+ size = getSize(MetadataIndex.iProperty);
+ break;
+ case MetadataVarType.moduleRefIndex:
+ size = getSize(MetadataIndex.iModuleRef);
+ break;
+ case MetadataVarType.assemblyRefIndex:
+ size = getSize(MetadataIndex.iAssemblyRef);
+ break;
+ case MetadataVarType.genericParamIndex:
+ size = getSize(MetadataIndex.iGenericParam);
+ break;
+ default:
+ throw new ApplicationException("Unknown type");
+ }
+
+ var field = new MetadataField();
+ field.offset = offset;
+ field.size = size;
+ fields.Add(field);
+ offset += size;
+ }
+
+ uint getMaxRows(MetadataIndex[] indexes) {
+ uint maxRows = 0;
+ for (int i = 0; i < indexes.Length; i++)
+ maxRows = Math.Max(maxRows, numRows[(int)indexes[i]]);
+ return maxRows;
+ }
+
+ int getSize(int bits, MetadataIndex[] indexes) {
+ uint maxNum = 1U << bits;
+ uint maxRows = getMaxRows(indexes);
+ return maxRows <= maxNum ? 2 : 4;
+ }
+
+ int getSize(MetadataIndex index) {
+ return getSize(16, new MetadataIndex[] { index });
+ }
+ }
+}
diff --git a/de4dot.code/PE/PeImage.cs b/de4dot.code/PE/PeImage.cs
index 09302fd3..8cb7cc3e 100644
--- a/de4dot.code/PE/PeImage.cs
+++ b/de4dot.code/PE/PeImage.cs
@@ -30,6 +30,14 @@ namespace de4dot.PE {
Cor20Header cor20Header;
SectionHeader dotNetSection;
+ public BinaryReader Reader {
+ get { return reader; }
+ }
+
+ public Cor20Header Cor20Header {
+ get { return cor20Header; }
+ }
+
public PeImage(byte[] data)
: this(new MemoryStream(data)) {
}
@@ -75,7 +83,7 @@ namespace de4dot.PE {
cor20Header = new Cor20Header(reader);
dotNetSection = getSectionHeader(netOffset);
seekRva(cor20Header.metaData.virtualAddress);
- cor20Header.initMetadataTable(reader);
+ cor20Header.initMetadataTable();
}
}
@@ -125,6 +133,21 @@ namespace de4dot.PE {
writer.Write(data);
}
+ public byte readByte(uint rva) {
+ seekRva(rva);
+ return reader.ReadByte();
+ }
+
+ public ushort readUInt16(uint rva) {
+ seekRva(rva);
+ return reader.ReadUInt16();
+ }
+
+ public uint readUInt32(uint rva) {
+ seekRva(rva);
+ return reader.ReadUInt32();
+ }
+
public int readInt32(uint rva) {
seekRva(rva);
return reader.ReadInt32();
@@ -134,5 +157,21 @@ namespace de4dot.PE {
seekRva(rva);
return reader.ReadBytes(size);
}
+
+ public uint offsetRead(uint offset, int size) {
+ if (size == 2) return offsetReadUInt16(offset);
+ if (size == 4) return offsetReadUInt32(offset);
+ throw new NotImplementedException();
+ }
+
+ public ushort offsetReadUInt16(uint offset) {
+ seek(offset);
+ return reader.ReadUInt16();
+ }
+
+ public uint offsetReadUInt32(uint offset) {
+ seek(offset);
+ return reader.ReadUInt32();
+ }
}
}
diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj
index 81d00452..7d714538 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -113,9 +113,14 @@
+
+
+
+
+