public Relocations(BinaryReader reader, MModule mod) { uint start, end; if (mod.ModHeaders.OSHeaders.PEHeader.DataDirs[5].Rva == 0) { return; } start = mod.ModHeaders.Rva2Offset(mod.ModHeaders.OSHeaders.PEHeader.DataDirs[5].Rva); end = start + mod.ModHeaders.OSHeaders.PEHeader.DataDirs[5].Size; //fill in Region props Start = start; Length = end - start; reader.BaseStream.Position = start; RelocationBlock block; ArrayList arr = new ArrayList(); while (reader.BaseStream.Position < end) { block = new RelocationBlock(reader); arr.Add(block); } _blox = (RelocationBlock[])arr.ToArray(typeof(RelocationBlock)); }
public ImportAddress(uint n, BinaryReader reader, MModule mod) { if ((n & 0x80000000) != 0) { _ByOrdinal = true; } else { _ByOrdinal = false; } if (_ByOrdinal) { _Ordinal = n & 0x7fffffff; } else { uint nameOffs = n & 0x7fffffff; long offs = reader.BaseStream.Position; reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(nameOffs); reader.ReadInt16(); //hint byte b = reader.ReadByte(); while (b != 0) { _Name += (char)b; b = reader.ReadByte(); } reader.BaseStream.Position = offs; } }
public MDBlob(BinaryReader reader) { //read length indicator _length = MModule.DecodeInt32(reader); _data = reader.ReadBytes(_length); }
public MDTables(BinaryReader reader, MModule mod) { _mod = mod; SetupSchema(reader); //reader may now be accessed randomly to fill in actual strings etc. }
public ExportDirTable(BinaryReader reader, MModule mod) { _ExportFlags = reader.ReadUInt32(); _TimeStamp = reader.ReadUInt32(); _MajorVersion = reader.ReadUInt16(); _MinorVersion = reader.ReadUInt16(); _Name = mod.StringFromRVA(reader, reader.ReadUInt32()); _OrdinalBase = reader.ReadUInt32(); _AddressTableEntries = reader.ReadUInt32(); _NamePointerCount = reader.ReadUInt32(); _ExportAddressTableRVA = reader.ReadUInt32(); _NamePointerRVA = reader.ReadUInt32(); _OrdinalRVA = reader.ReadUInt32(); }
public ImpExports(BinaryReader reader, MModule mod) { ArrayList ides = new ArrayList(); ImportDirectoryEntry ide = null; _exports = new ExportRecord[0]; _ith = new ImportDirectoryEntry[0]; //imports if (mod.ModHeaders.OSHeaders.PEHeader.DataDirs[1].Rva != 0) { uint start, end; start = mod.ModHeaders.Rva2Offset(mod.ModHeaders.OSHeaders.PEHeader.DataDirs[1].Rva); end = mod.ModHeaders.OSHeaders.PEHeader.DataDirs[1].Size + start; reader.BaseStream.Position = start; while (reader.BaseStream.Position < end) { ide = new ImportDirectoryEntry(reader, mod); //in older PEs it seems there is no null terminating entry, but in .NET ones there is. if (ide.Name == null) { break; } ides.Add(ide); } _ith = (ImportDirectoryEntry[])ides.ToArray(typeof(ImportDirectoryEntry)); } //exports if (mod.ModHeaders.OSHeaders.PEHeader.DataDirs[0].Rva != 0) { reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(mod.ModHeaders.OSHeaders.PEHeader.DataDirs[0].Rva); _extab = new ExportDirTable(reader, mod); _expAddrTab = new uint[_extab.AddressTableEntries]; _expNameTab = new string[_extab.NamePointerCount]; _expOrdTab = new uint[_extab.NamePointerCount]; reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(_extab.ExportAddressTableRVA); for (int i = 0; i < _extab.AddressTableEntries; ++i) { _expAddrTab[i] = reader.ReadUInt32(); } reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(_extab.OrdinalRVA); for (int i = 0; i < _extab.NamePointerCount; ++i) { _expOrdTab[i] = reader.ReadUInt16(); } reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(_extab.NamePointerRVA); for (int i = 0; i < _extab.NamePointerCount; ++i) { _expNameTab[i] = mod.StringFromRVA(reader, reader.ReadUInt32()); } //assemble array of exportrecords uint len = _extab.AddressTableEntries; if (len > _extab.NamePointerCount) { len = _extab.NamePointerCount; } _exports = new ExportRecord[len]; for (int i = 0; i < len; ++i) { _exports[i] = new ExportRecord(_expOrdTab[i], _expAddrTab[i], _expNameTab[i]); } } }
public ImportDirectoryEntry(BinaryReader reader, MModule mod) { Start = reader.BaseStream.Position; uint iltRVA = reader.ReadUInt32(); _DateTimeStamp = reader.ReadUInt32(); _ForwarderChain = reader.ReadUInt32(); uint nameRVA = reader.ReadUInt32(); _Name = mod.StringFromRVA(reader, nameRVA); uint iatRVA = reader.ReadUInt32(); //can also get this from the PEHeader's data dirs Length = reader.BaseStream.Position - Start; long offs = reader.BaseStream.Position; // remember our position at the end of the imp dir entry record if (nameRVA == 0) { //indicate that this is not valid, because we reached the null terminating record //or because we are hopelessly lost _Name = null; return; } try { //get imp look table from RVA ArrayList arr; uint tableOffs, field; if (iltRVA != 0) { arr = new ArrayList(); tableOffs = mod.ModHeaders.Rva2Offset(iltRVA); reader.BaseStream.Position = tableOffs; field = reader.ReadUInt32(); while (field != 0) { arr.Add(new ImportAddress(field, reader, mod)); field = reader.ReadUInt32(); } _ImportLookupTable = (ImportAddress[])arr.ToArray(typeof(ImportAddress)); } //get imp Addr table from RVA if (iatRVA != 0) { arr = new ArrayList(); tableOffs = mod.ModHeaders.Rva2Offset(iatRVA); reader.BaseStream.Position = tableOffs; field = reader.ReadUInt32(); while (field != 0) { arr.Add(field); field = reader.ReadUInt32(); } _ImportAddressTable = (uint[])arr.ToArray(typeof(uint)); } } catch { } finally { //restore stream pos reader.BaseStream.Position = offs; } }
/// <summary> /// Decodes assembly metadata, headers and tables to required values ad file offsets /// </summary> /// <param name="fileName">Assembly path and filename</param> /// <param name="cliHeaderFlag">Reference to CLI Header flag value</param> /// <param name="cliHeaderFlagOffset">Reference to CLI Header flag file offset</param> /// <param name="strongNameSignatureOffset">Reference to CLI Header strong name signature file offset</param> /// <param name="publicKeyIndexOffset">Reference to Public Key Index in Assembly Table file offset</param> /// <param name="publicKeyOffset">Reference to Public Key file offset</param> /// <param name="assemblyFlag">Reference to Assembly Table Flag value</param> /// <param name="assemblyFlagOffset">Reference to Assembly Table Flag file offset</param> /// <param name="compiledRuntimeVersion">Reference to string with compiled runtime version</param> /// <param name="assemblyReferences">Reference to array to hold assembly references</param> /// <param name="blobIndexSize">Blob Index size in bytes</param> /// <returns>Returns a bool indicating if assembly data can be retieved successfully</returns> public static bool GetAssemblyData(string fileName, ref uint cliHeaderFlag, ref long cliHeaderFlagOffset, ref long strongNameSignatureOffset, ref long publicKeyIndexOffset, ref long publicKeyOffset, ref uint assemblyFlag, ref long assemblyFlagOffset, ref string compiledRuntimeVersion, ref ArrayList assemblyReferences, ref int blobIndexSize, bool getSigOnly) { MModule mod; BinaryReader r; FileStream stream = null; cliHeaderFlag = 0; cliHeaderFlagOffset = 0; strongNameSignatureOffset = 0; publicKeyIndexOffset = 0; publicKeyOffset = 0; compiledRuntimeVersion = String.Empty; assemblyFlag = 0; assemblyFlagOffset = 0; assemblyReferences.Clear(); try { if (File.Exists(fileName)) { stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); r = new BinaryReader(stream); mod = new MModule(r); try { if (mod.ModHeaders.COR20Header != null) { cliHeaderFlag = mod.ModHeaders.COR20Header.Flags; cliHeaderFlagOffset = mod.ModHeaders.COR20Header.Start + CLI_HEADER_FLAGS_OFFSET; // if Strong Name Signature RVA is zero, no Strong Signature is available strongNameSignatureOffset = (mod.ModHeaders.COR20Header.StrongNameSignature.Rva == 0 ? 0 : mod.ModHeaders.COR20Header.StrongNameSignature.Start); compiledRuntimeVersion = mod.ModHeaders.MetaDataHeaders.StorageSigAndHeader.VersionString.Replace("\0", String.Empty); blobIndexSize = mod.MDTables.GetBlobIndexSize(); // next loop sum tables byte length till reaching Assembly Table - this would give Assembly Table start offset long assemblyTableOffset = mod.ModHeaders.MetaDataTableHeader.End; for (int tablesCounter = 0; tablesCounter < (int) Types.Assembly; tablesCounter++) { assemblyTableOffset += mod.MDTables.Tables[tablesCounter].RawData.Length; } Table tableAssembly = mod.MDTables.GetTable(Types.Assembly); if (tableAssembly.Count > 0) // this should be 1 { if (tableAssembly[0][6].RawData == 0) { // Index for public key points no nothing publicKeyOffset = 0; } else { publicKeyOffset = mod.BlobHeap.Start + tableAssembly[0][6].RawData + 1; } assemblyFlag = (uint) tableAssembly[0][5].Data; if (assemblyTableOffset > 0) { publicKeyIndexOffset = assemblyTableOffset + ASSEMBLY_TABLE_PUBLIC_KEY_INDEX_OFFSET; assemblyFlagOffset = assemblyTableOffset + ASSEMBLY_TABLE_FLAGS_OFFSET; } } if (getSigOnly) return true; // next loop sum tables byte length till reaching Assembly References Table - this would give Assembly References Table start offset long referenceTableOffset = mod.ModHeaders.MetaDataTableHeader.End; for (int tablesCounter = 0; tablesCounter < (int) Types.AssemblyRef; tablesCounter++) { referenceTableOffset += mod.MDTables.Tables[tablesCounter].RawData.Length; } if (referenceTableOffset > 0) { Table tableAssemblyReferences = mod.MDTables.GetTable(Types.AssemblyRef); if (tableAssemblyReferences.Count > 0) { for (int referencesCounter = 0; referencesCounter < tableAssemblyReferences.Count; referencesCounter++) { AssemblyReference reference = new AssemblyReference(tableAssemblyReferences[referencesCounter][6].Data.ToString(), tableAssemblyReferences[referencesCounter][0].Data + "." + tableAssemblyReferences[referencesCounter][1].Data + "." + tableAssemblyReferences[referencesCounter][2].Data + "." + tableAssemblyReferences[referencesCounter][3].Data, tableAssemblyReferences[referencesCounter][5].Data.ToString(), referenceTableOffset + (referencesCounter*tableAssemblyReferences.RowSize)); assemblyReferences.Add(reference); } } } } else { return false; } } finally { r.Close(); } } } finally { if (stream != null) { stream.Close(); } } return true; }
public ImportDirectoryEntry(BinaryReader reader, MModule mod) { Start = reader.BaseStream.Position; uint iltRVA = reader.ReadUInt32(); _DateTimeStamp = reader.ReadUInt32(); _ForwarderChain = reader.ReadUInt32(); uint nameRVA = reader.ReadUInt32(); _Name = mod.StringFromRVA(reader, nameRVA); uint iatRVA = reader.ReadUInt32(); //can also get this from the PEHeader's data dirs Length = reader.BaseStream.Position - Start; long offs = reader.BaseStream.Position; // remember our position at the end of the imp dir entry record if (nameRVA == 0) { //indicate that this is not valid, because we reached the null terminating record //or because we are hopelessly lost _Name = null; return; } try { //get imp look table from RVA ArrayList arr; uint tableOffs, field; if (iltRVA != 0) { arr = new ArrayList(); tableOffs = mod.ModHeaders.Rva2Offset(iltRVA); reader.BaseStream.Position = tableOffs; field = reader.ReadUInt32(); while (field != 0) { arr.Add(new ImportAddress(field, reader, mod)); field = reader.ReadUInt32(); } _ImportLookupTable = (ImportAddress[]) arr.ToArray(typeof (ImportAddress)); } //get imp Addr table from RVA if (iatRVA != 0) { arr = new ArrayList(); tableOffs = mod.ModHeaders.Rva2Offset(iatRVA); reader.BaseStream.Position = tableOffs; field = reader.ReadUInt32(); while (field != 0) { arr.Add(field); field = reader.ReadUInt32(); } _ImportAddressTable = (uint[]) arr.ToArray(typeof (uint)); } } catch { } finally { //restore stream pos reader.BaseStream.Position = offs; } }
public ImportAddress(uint n, BinaryReader reader, MModule mod) { if ((n & 0x80000000) != 0) { _ByOrdinal = true; } else { _ByOrdinal = false; } if (_ByOrdinal) { _Ordinal = n & 0x7fffffff; } else { uint nameOffs = n & 0x7fffffff; long offs = reader.BaseStream.Position; reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(nameOffs); reader.ReadInt16(); //hint byte b = reader.ReadByte(); while (b != 0) { _Name += (char) b; b = reader.ReadByte(); } reader.BaseStream.Position = offs; } }
public ImpExports(BinaryReader reader, MModule mod) { ArrayList ides = new ArrayList(); ImportDirectoryEntry ide = null; _exports = new ExportRecord[0]; _ith = new ImportDirectoryEntry[0]; //imports if (mod.ModHeaders.OSHeaders.PEHeader.DataDirs[1].Rva != 0) { uint start, end; start = mod.ModHeaders.Rva2Offset(mod.ModHeaders.OSHeaders.PEHeader.DataDirs[1].Rva); end = mod.ModHeaders.OSHeaders.PEHeader.DataDirs[1].Size + start; reader.BaseStream.Position = start; while (reader.BaseStream.Position < end) { ide = new ImportDirectoryEntry(reader, mod); //in older PEs it seems there is no null terminating entry, but in .NET ones there is. if (ide.Name == null) { break; } ides.Add(ide); } _ith = (ImportDirectoryEntry[]) ides.ToArray(typeof (ImportDirectoryEntry)); } //exports if (mod.ModHeaders.OSHeaders.PEHeader.DataDirs[0].Rva != 0) { reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(mod.ModHeaders.OSHeaders.PEHeader.DataDirs[0].Rva); _extab = new ExportDirTable(reader, mod); _expAddrTab = new uint[_extab.AddressTableEntries]; _expNameTab = new string[_extab.NamePointerCount]; _expOrdTab = new uint[_extab.NamePointerCount]; reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(_extab.ExportAddressTableRVA); for (int i = 0; i < _extab.AddressTableEntries; ++i) { _expAddrTab[i] = reader.ReadUInt32(); } reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(_extab.OrdinalRVA); for (int i = 0; i < _extab.NamePointerCount; ++i) { _expOrdTab[i] = reader.ReadUInt16(); } reader.BaseStream.Position = mod.ModHeaders.Rva2Offset(_extab.NamePointerRVA); for (int i = 0; i < _extab.NamePointerCount; ++i) { _expNameTab[i] = mod.StringFromRVA(reader, reader.ReadUInt32()); } //assemble array of exportrecords uint len = _extab.AddressTableEntries; if (len > _extab.NamePointerCount) { len = _extab.NamePointerCount; } _exports = new ExportRecord[len]; for (int i = 0; i < len; ++i) { _exports[i] = new ExportRecord(_expOrdTab[i], _expAddrTab[i], _expNameTab[i]); } } }
public Relocations(BinaryReader reader, MModule mod) { uint start, end; if (mod.ModHeaders.OSHeaders.PEHeader.DataDirs[5].Rva == 0) { return; } start = mod.ModHeaders.Rva2Offset(mod.ModHeaders.OSHeaders.PEHeader.DataDirs[5].Rva); end = start + mod.ModHeaders.OSHeaders.PEHeader.DataDirs[5].Size; //fill in Region props Start = start; Length = end - start; reader.BaseStream.Position = start; RelocationBlock block; ArrayList arr = new ArrayList(); while (reader.BaseStream.Position < end) { block = new RelocationBlock(reader); arr.Add(block); } _blox = (RelocationBlock[]) arr.ToArray(typeof (RelocationBlock)); }