-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import Address tables and started work on Import Hint Name tables.
- Loading branch information
Lloyd Kinsella
committed
Aug 3, 2018
1 parent
4f3fce7
commit c42b900
Showing
12 changed files
with
440 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
src/Workshell.PE/Content/Imports/DelayedImportAddressTable.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public sealed class DelayedImportAddressTable : ImportAddressTableBase<DelayedImportAddressTableEntry> | ||
{ | ||
internal DelayedImportAddressTable(PortableExecutableImage image, uint rva, ulong[] entries) : base(image, rva, entries, true) | ||
{ | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/Workshell.PE/Content/Imports/DelayedImportAddressTableEntry.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public sealed class DelayedImportAddressTableEntry : ImportAddressTableEntryBase | ||
{ | ||
internal DelayedImportAddressTableEntry(PortableExecutableImage image, ulong entryOffset, ulong entryValue, uint entryAddress, ushort entryOrdinal, bool isOrdinal) : base(image, entryOffset, entryValue, entryAddress, entryOrdinal, isOrdinal, true) | ||
{ | ||
} | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
src/Workshell.PE/Content/Imports/DelayedImportAddressTables.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using Workshell.PE.Extensions; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public sealed class DelayedImportAddressTables: ImportAddressTablesBase<DelayedImportAddressTable, DelayedImportAddressTableEntry> | ||
{ | ||
internal DelayedImportAddressTables(PortableExecutableImage image, DataDirectory directory, Location location, Tuple<uint, ulong[]>[] tables) : base(image, directory, location, tables, false) | ||
{ | ||
} | ||
|
||
#region Static Methods | ||
|
||
public static async Task<DelayedImportAddressTables> GetLookupTableAsync(PortableExecutableImage image, DelayedImportDirectory directory = null) | ||
{ | ||
return await GetTableAsync(image, directory, (entry) => entry.DelayNameTable).ConfigureAwait(false); | ||
} | ||
|
||
public static async Task<DelayedImportAddressTables> GetAddressTableAsync(PortableExecutableImage image, DelayedImportDirectory directory = null) | ||
{ | ||
return await GetTableAsync(image, directory, (entry) => entry.DelayAddressTable).ConfigureAwait(false); | ||
} | ||
|
||
private static async Task<DelayedImportAddressTables> GetTableAsync(PortableExecutableImage image, DelayedImportDirectory directory, Func<DelayedImportDirectoryEntry, uint> thunkHandler) | ||
{ | ||
if (directory == null) | ||
directory = await DelayedImportDirectory.LoadAsync(image).ConfigureAwait(false); | ||
|
||
var calc = image.GetCalculator(); | ||
var stream = image.GetStream(); | ||
var tables = new List<Tuple<uint, ulong[]>>(); | ||
|
||
foreach (var dirEntry in directory) | ||
{ | ||
var thunk = thunkHandler(dirEntry); | ||
|
||
if (thunk == 0) | ||
continue; | ||
|
||
var entries = new List<ulong>(); | ||
var offset = calc.RVAToOffset(thunk); | ||
|
||
stream.Seek(offset.ToInt64(), SeekOrigin.Begin); | ||
|
||
while (true) | ||
{ | ||
var entry = (!image.Is64Bit ? await stream.ReadUInt32Async().ConfigureAwait(false) : await stream.ReadUInt64Async().ConfigureAwait(false)); | ||
|
||
entries.Add(entry); | ||
|
||
if (entry == 0) | ||
break; | ||
} | ||
|
||
var table = new Tuple<uint, ulong[]>(thunk, entries.ToArray()); | ||
|
||
tables.Add(table); | ||
} | ||
|
||
var rva = 0u; | ||
|
||
if (tables.Count > 0) | ||
rva = tables.MinBy(table => table.Item1).Item1; | ||
|
||
var imageBase = image.NTHeaders.OptionalHeader.ImageBase; | ||
var va = imageBase + rva; | ||
var fileOffset = calc.RVAToOffset(rva); | ||
var fileSize = 0ul; | ||
|
||
foreach (var table in tables) | ||
{ | ||
var size = (table.Item2.Length + 1) * (!image.Is64Bit ? sizeof(uint) : sizeof(ulong)); | ||
|
||
fileSize += size.ToUInt32(); | ||
} | ||
|
||
var section = calc.RVAToSection(rva); | ||
var location = new Location(fileOffset, rva, va, fileSize, fileSize, section); | ||
var result = new DelayedImportAddressTables(image, directory.Directory, location, tables.ToArray()); | ||
|
||
return result; | ||
} | ||
|
||
#endregion | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/Workshell.PE/Content/Imports/DelayedImportHintNameEntry.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public sealed class DelayedImportHintNameEntry : ImportHintNameEntryBase | ||
{ | ||
internal DelayedImportHintNameEntry(PortableExecutableImage image, ulong offset, uint size, ushort entryHint, string entryName, bool isPadded) : base(image, offset, size, entryHint, entryName, isPadded, true) | ||
{ | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using Workshell.PE.Extensions; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public sealed class ImportAddressTables: ImportAddressTablesBase<ImportAddressTable, ImportAddressTableEntry> | ||
{ | ||
internal ImportAddressTables(PortableExecutableImage image, DataDirectory directory, Location location, Tuple<uint, ulong[]>[] tables) : base(image, directory, location, tables, false) | ||
{ | ||
} | ||
|
||
#region Static Methods | ||
|
||
public static async Task<ImportAddressTables> GetLookupTableAsync(PortableExecutableImage image, ImportDirectory directory = null) | ||
{ | ||
return await GetTableAsync(image, directory, (entry) => entry.OriginalFirstThunk).ConfigureAwait(false); | ||
} | ||
|
||
public static async Task<ImportAddressTables> GetAddressTableAsync(PortableExecutableImage image, ImportDirectory directory = null) | ||
{ | ||
return await GetTableAsync(image, directory, (entry) => entry.FirstThunk).ConfigureAwait(false); | ||
} | ||
|
||
private static async Task<ImportAddressTables> GetTableAsync(PortableExecutableImage image, ImportDirectory directory, Func<ImportDirectoryEntry, uint> thunkHandler) | ||
{ | ||
if (directory == null) | ||
directory = await ImportDirectory.LoadAsync(image).ConfigureAwait(false); | ||
|
||
var calc = image.GetCalculator(); | ||
var stream = image.GetStream(); | ||
var tables = new List<Tuple<uint, ulong[]>>(); | ||
|
||
foreach (var dirEntry in directory) | ||
{ | ||
var thunk = thunkHandler(dirEntry); | ||
|
||
if (thunk == 0) | ||
continue; | ||
|
||
var entries = new List<ulong>(); | ||
var offset = calc.RVAToOffset(thunk); | ||
|
||
stream.Seek(offset.ToInt64(), SeekOrigin.Begin); | ||
|
||
while (true) | ||
{ | ||
var entry = (!image.Is64Bit ? await stream.ReadUInt32Async().ConfigureAwait(false) : await stream.ReadUInt64Async().ConfigureAwait(false)); | ||
|
||
entries.Add(entry); | ||
|
||
if (entry == 0) | ||
break; | ||
} | ||
|
||
var table = new Tuple<uint, ulong[]>(thunk, entries.ToArray()); | ||
|
||
tables.Add(table); | ||
} | ||
|
||
var rva = 0u; | ||
|
||
if (tables.Count > 0) | ||
rva = tables.MinBy(table => table.Item1).Item1; | ||
|
||
var imageBase = image.NTHeaders.OptionalHeader.ImageBase; | ||
var va = imageBase + rva; | ||
var fileOffset = calc.RVAToOffset(rva); | ||
var fileSize = 0ul; | ||
|
||
foreach (var table in tables) | ||
{ | ||
var size = table.Item2.Length * (!image.Is64Bit ? sizeof(uint) : sizeof(ulong)); | ||
|
||
fileSize += size.ToUInt32(); | ||
} | ||
|
||
var section = calc.RVAToSection(rva); | ||
var location = new Location(fileOffset, rva, va, fileSize, fileSize, section); | ||
var result = new ImportAddressTables(image, directory.Directory, location, tables.ToArray()); | ||
|
||
return result; | ||
} | ||
|
||
#endregion | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
src/Workshell.PE/Content/Imports/ImportAddressTablesBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public abstract class ImportAddressTablesBase<TTable, TTableEntry> : DataContent, IEnumerable<TTable> | ||
where TTable : ImportAddressTableBase<TTableEntry> | ||
where TTableEntry : ImportAddressTableEntryBase | ||
{ | ||
private readonly TTable[] _tables; | ||
|
||
protected internal ImportAddressTablesBase(PortableExecutableImage image, DataDirectory directory, Location location, Tuple<uint, ulong[]>[] tables, bool isDelayed) : base(image, directory, location) | ||
{ | ||
_tables = new TTable[tables.Length]; | ||
|
||
var type = typeof(TTable); | ||
var ctors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); | ||
var ctor = ctors.First(); | ||
|
||
for (var i = 0; i < tables.Length; i++) | ||
{ | ||
var tuple = tables[i]; | ||
var table = (TTable)ctor.Invoke(new object[] { image, tuple.Item1, tuple.Item2 }); | ||
|
||
_tables[i] = table; | ||
} | ||
|
||
Count = _tables.Length; | ||
IsDelayed = isDelayed; | ||
} | ||
|
||
#region Methods | ||
|
||
public IEnumerator<TTable> GetEnumerator() | ||
{ | ||
foreach (var table in _tables) | ||
yield return table; | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
public int Count { get; } | ||
public TTable this[int index] => _tables[index]; | ||
public bool IsDelayed { get; } | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public sealed class ImportHintNameEntry : ImportHintNameEntryBase | ||
{ | ||
internal ImportHintNameEntry(PortableExecutableImage image, ulong offset, uint size, ushort entryHint, string entryName, bool isPadded) : base(image, offset, size, entryHint, entryName, isPadded, false) | ||
{ | ||
} | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
src/Workshell.PE/Content/Imports/ImportHintNameEntryBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Workshell.PE.Extensions; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public abstract class ImportHintNameEntryBase : ISupportsLocation, ISupportsBytes | ||
{ | ||
private readonly PortableExecutableImage _image; | ||
|
||
protected internal ImportHintNameEntryBase(PortableExecutableImage image, ulong offset, uint size, ushort entryHint, string entryName, bool isPadded, bool isDelayed) | ||
{ | ||
_image = image; | ||
|
||
var calc = image.GetCalculator(); | ||
var rva = calc.OffsetToRVA(offset); | ||
var va = image.NTHeaders.OptionalHeader.ImageBase + rva; | ||
|
||
Location = new Location(calc, offset, rva, va, size, size); | ||
Hint = entryHint; | ||
Name = entryName; | ||
IsPadded = isPadded; | ||
IsDelayed = isDelayed; | ||
} | ||
|
||
#region Methods | ||
|
||
public override string ToString() | ||
{ | ||
return $"0x{hint:X4} {name}"; | ||
} | ||
|
||
public byte[] GetBytes() | ||
{ | ||
return GetBytesAsync().GetAwaiter().GetResult(); | ||
} | ||
|
||
public async Task<byte[]> GetBytesAsync() | ||
{ | ||
var stream = _image.GetStream(); | ||
var buffer = await stream.ReadBytesAsync(Location).ConfigureAwait(false); | ||
|
||
return buffer; | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
public Location Location { get; } | ||
public ushort Hint { get; } | ||
public string Name { get; } | ||
public bool IsPadded { get; } | ||
public bool IsDelayed { get; } | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Workshell.PE.Content | ||
{ | ||
public sealed class ImportHintNameTable : ImportHintNameTableBase<ImportHintNameEntry> | ||
{ | ||
internal ImportHintNameTable(PortableExecutableImage image, DataDirectory directory, Location location, Tuple<ulong, uint, ushort, string, bool>[] entries) : base(image, directory, location, entries, false) | ||
{ | ||
} | ||
|
||
#region Static Methods | ||
|
||
#endregion | ||
} | ||
} |
Oops, something went wrong.