From 65737448c63048af1150ecb0452edfcd0968e04e Mon Sep 17 00:00:00 2001 From: Lloyd Kinsella Date: Sat, 18 Jun 2016 16:46:23 +0100 Subject: [PATCH] More work on the Address table classes. --- .../Content/Imports/ImportAddressTable.cs | 142 +++++++++--------- 1 file changed, 70 insertions(+), 72 deletions(-) diff --git a/Src/Workshell.PE/Content/Imports/ImportAddressTable.cs b/Src/Workshell.PE/Content/Imports/ImportAddressTable.cs index cc37f75..2fecc40 100644 --- a/Src/Workshell.PE/Content/Imports/ImportAddressTable.cs +++ b/Src/Workshell.PE/Content/Imports/ImportAddressTable.cs @@ -126,20 +126,21 @@ public sealed class ImportAddressTable : IEnumerable, I private Location location; private ImportAddressTableEntry[] entries; - internal ImportAddressTable(ImportAddressTables addressTables, ImportDirectoryEntry directoryEntry, ulong tableOffset, ulong[] tableEntries) + internal ImportAddressTable(ImportAddressTables addressTables, ImportDirectoryEntry directoryEntry, uint tableRVA/*, ulong tableOffset*/, ulong[] tableEntries) { bool is_64bit = addressTables.DataDirectory.Directories.Image.Is64Bit; LocationCalculator calc = addressTables.DataDirectory.Directories.Image.GetCalculator(); - uint rva = directoryEntry.OriginalFirstThunk; + uint rva = tableRVA; ulong image_base = addressTables.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; ulong va = image_base + rva; + ulong offset = calc.RVAToOffset(rva); ulong size = (tableEntries.Count() * (is_64bit ? sizeof(ulong) : sizeof(uint))).ToUInt64(); Section section = calc.RVAToSection(rva); tables = addressTables; dir_entry = directoryEntry; - location = new Location(tableOffset,rva,va,size,size,section); - entries = LoadEntries(is_64bit,tableOffset,tableEntries); + location = new Location(offset, rva, va, size, size, section); + entries = LoadEntries(is_64bit, offset, tableEntries); } #region Methods @@ -274,40 +275,22 @@ public ImportAddressTableEntry this[int index] } - public sealed class ImportAddressTables : ExecutableImageContent, IEnumerable, ISupportsLocation, ISupportsBytes + public sealed class ImportAddressTables : ExecutableImageContent, IEnumerable, ISupportsBytes { private ImportAddressTable[] tables; - internal ImportAddressTables(DataDirectory dataDirectory, Location dataLocation, Tuple[] addressTables) : base(dataDirectory,dataLocation) + internal ImportAddressTables(DataDirectory dataDirectory, Location dataLocation, Tuple[] addressTables) : base(dataDirectory,dataLocation) { tables = new ImportAddressTable[addressTables.Length]; - /* - LoadTables(tablesInfo); - - ulong lowest_offset = 0; - - if (tablesInfo.Count() > 0) - lowest_offset = tablesInfo.MinBy(table => table.Item1).Item1; - - LocationCalculator calc = content.DataDirectory.Directories.Reader.GetCalculator(); - uint rva = calc.OffsetToRVA(content.Section,lowest_offset); - ulong va = calc.OffsetToVA(content.Section,lowest_offset); - ulong size = 0; - - foreach (var table in tables) - size += table.Location.FileSize; - - location = new Location(lowest_offset,rva,va,size,size); - */ - LocationCalculator calc = DataDirectory.Directories.Image.GetCalculator(); for (var i = 0; i < addressTables.Length; i++) { - ulong offset = calc.RVAToOffset(addressTables[i].Item1.OriginalFirstThunk); - ImportAddressTable table = new ImportAddressTable(this, addressTables[i].Item1, offset, addressTables[i].Item2); + Tuple tuple = addressTables[i]; + ulong offset = calc.RVAToOffset(tuple.Item1); + ImportAddressTable table = new ImportAddressTable(this, tuple.Item2, tuple.Item1, tuple.Item3); tables[i] = table; } @@ -320,7 +303,7 @@ public static ImportAddressTables GetLookupTable(ImportDirectory directory) LocationCalculator calc = directory.DataDirectory.Directories.Image.GetCalculator(); bool is_64bit = directory.DataDirectory.Directories.Image.Is64Bit; Stream stream = directory.DataDirectory.Directories.Image.GetStream(); - List> tables = new List>(); + List> tables = new List>(); foreach (ImportDirectoryEntry dir_entry in directory) { @@ -342,7 +325,63 @@ public static ImportAddressTables GetLookupTable(ImportDirectory directory) break; } - Tuple table = new Tuple(dir_entry, entries.ToArray()); + Tuple table = new Tuple(dir_entry.OriginalFirstThunk, dir_entry, entries.ToArray()); + + tables.Add(table); + } + + uint rva = 0; + + if (tables.Count > 0) + rva = tables.MinBy(table => table.Item1).Item1; + + ulong image_base = directory.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; + ulong va = image_base + rva; + ulong file_offset = calc.RVAToOffset(rva); + ulong file_size = 0; + + foreach (var table in tables) + { + int size = table.Item3.Length * (!is_64bit ? sizeof(uint) : sizeof(ulong)); + + file_size += size.ToUInt32(); + } + + Section section = calc.RVAToSection(rva); + Location location = new Location(file_offset, rva, va, file_size, file_size, section); + ImportAddressTables result = new ImportAddressTables(directory.DataDirectory, location, tables.ToArray()); + + return result; + } + + public static ImportAddressTables GetAddressTable(ImportDirectory directory) + { + LocationCalculator calc = directory.DataDirectory.Directories.Image.GetCalculator(); + bool is_64bit = directory.DataDirectory.Directories.Image.Is64Bit; + Stream stream = directory.DataDirectory.Directories.Image.GetStream(); + List> tables = new List>(); + + foreach (ImportDirectoryEntry dir_entry in directory) + { + if (dir_entry.FirstThunk == 0) + continue; + + List entries = new List(); + ulong offset = calc.RVAToOffset(dir_entry.FirstThunk); + + stream.Seek(offset.ToInt64(), SeekOrigin.Begin); + + while (true) + { + ulong entry = (!is_64bit ? Utils.ReadUInt32(stream) : Utils.ReadUInt64(stream)); + + entries.Add(entry); + + if (entry == 0) + break; + } + + Tuple table = new Tuple(dir_entry.FirstThunk, dir_entry, entries.ToArray()); tables.Add(table); } @@ -350,7 +389,7 @@ public static ImportAddressTables GetLookupTable(ImportDirectory directory) uint rva = 0; if (tables.Count > 0) - rva = tables.MinBy(table => table.Item1.OriginalFirstThunk).Item1.OriginalFirstThunk; + rva = tables.MinBy(table => table.Item1).Item1; ulong image_base = directory.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; ulong va = image_base + rva; @@ -359,7 +398,7 @@ public static ImportAddressTables GetLookupTable(ImportDirectory directory) foreach (var table in tables) { - int size = table.Item2.Length * (!is_64bit ? sizeof(uint) : sizeof(ulong)); + int size = table.Item3.Length * (!is_64bit ? sizeof(uint) : sizeof(ulong)); file_size += size.ToUInt32(); } @@ -401,47 +440,6 @@ public byte[] GetBytes() return buffer; } - /* - private void LoadTables(IEnumerable> tablesInfo) - { - List list = new List(); - bool is_64bit = content.DataDirectory.Directories.Reader.Is64Bit; - Stream stream = content.DataDirectory.Directories.Reader.GetStream(); - - foreach(Tuple table_info in tablesInfo) - { - stream.Seek(Convert.ToInt64(table_info.Item1),SeekOrigin.Begin); - - List entries = new List(); - - while (true) - { - ulong entry; - - if (!is_64bit) - { - entry = Utils.ReadUInt32(stream); - } - else - { - entry = Utils.ReadUInt64(stream); - } - - entries.Add(entry); - - if (entry == 0) - break; - } - - ImportAddressTable table = new ImportAddressTable(this,table_info.Item2,table_info.Item1,entries); - - list.Add(table); - } - - tables = list.ToArray(); - } - */ - #endregion #region Properties