Add .NET metadata reader (ported from C++)
This commit is contained in:
parent
89f90d3e75
commit
0e70d020b4
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
46
de4dot.code/PE/DotNetStream.cs
Normal file
46
de4dot.code/PE/DotNetStream.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
110
de4dot.code/PE/Metadata.cs
Normal file
110
de4dot.code/PE/Metadata.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
151
de4dot.code/PE/MetadataTables.cs
Normal file
151
de4dot.code/PE/MetadataTables.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
89
de4dot.code/PE/MetadataType.cs
Normal file
89
de4dot.code/PE/MetadataType.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<MetadataField> fields;
|
||||
|
||||
public MetadataType(List<MetadataField> 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);
|
||||
}
|
||||
}
|
||||
}
|
203
de4dot.code/PE/MetadataTypeBuilder.cs
Normal file
203
de4dot.code/PE/MetadataTypeBuilder.cs
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<MetadataField> fields;
|
||||
int offset;
|
||||
|
||||
public MetadataTypeBuilder(byte heapOffsetSizes, uint[] numRows) {
|
||||
this.heapOffsetSizes = heapOffsetSizes;
|
||||
this.numRows = numRows;
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
offset = 0;
|
||||
fields = new List<MetadataField>();
|
||||
}
|
||||
|
||||
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 });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,9 +113,14 @@
|
|||
<Compile Include="PE\DataDirectory.cs" />
|
||||
<Compile Include="PE\FileHeader.cs" />
|
||||
<Compile Include="PE\IFileLocation.cs" />
|
||||
<Compile Include="PE\Metadata.cs" />
|
||||
<Compile Include="PE\MetadataTables.cs" />
|
||||
<Compile Include="PE\MetadataType.cs" />
|
||||
<Compile Include="PE\MetadataTypeBuilder.cs" />
|
||||
<Compile Include="PE\OptionalHeader.cs" />
|
||||
<Compile Include="PE\PeImage.cs" />
|
||||
<Compile Include="PE\SectionHeader.cs" />
|
||||
<Compile Include="PE\DotNetStream.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="renamer\DefinitionsRenamer.cs" />
|
||||
|
|
Loading…
Reference in New Issue
Block a user