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 @@ + + + + +