0
mirror of https://github.com/sampletext32/ParkanPlayground.git synced 2025-07-01 20:40:27 +03:00
Files
ParkanPlayground/X86Disassembler/PE/Parsers/ImportDescriptorParser.cs

162 lines
5.1 KiB
C#
Raw Normal View History

using System.Text;
2025-04-20 19:54:52 +03:00
using X86Disassembler.PE.Types;
namespace X86Disassembler.PE.Parsers;
/// <summary>
/// Parser for Import Descriptors in a PE file
/// </summary>
public class ImportDescriptorParser
{
private readonly PEUtility _utility;
2025-04-20 19:54:52 +03:00
public ImportDescriptorParser(PEUtility utility)
{
_utility = utility;
}
2025-04-20 19:54:52 +03:00
/// <summary>
/// Parse the Import Descriptors from the binary reader
/// </summary>
/// <param name="reader">The binary reader</param>
/// <param name="rva">The RVA of the Import Directory</param>
/// <returns>List of Import Descriptors</returns>
public List<ImportDescriptor> Parse(BinaryReader reader, uint rva)
{
2025-04-20 19:54:52 +03:00
var descriptors = new List<ImportDescriptor>();
uint importTableOffset = _utility.RvaToOffset(rva);
reader.BaseStream.Seek(importTableOffset, SeekOrigin.Begin);
int descriptorCount = 0;
while (true)
{
2025-04-20 19:54:52 +03:00
descriptorCount++;
// Read the import descriptor
uint originalFirstThunk = reader.ReadUInt32();
uint timeDateStamp = reader.ReadUInt32();
uint forwarderChain = reader.ReadUInt32();
uint nameRva = reader.ReadUInt32();
uint firstThunk = reader.ReadUInt32();
// Check if we've reached the end of the import descriptors
if (originalFirstThunk == 0 && nameRva == 0 && firstThunk == 0)
{
2025-04-20 19:54:52 +03:00
break;
}
ImportDescriptor descriptor = new ImportDescriptor
{
OriginalFirstThunkRva = originalFirstThunk,
TimeDateStamp = timeDateStamp,
ForwarderChain = forwarderChain,
DllNameRva = nameRva,
FirstThunkRva = firstThunk,
DllName = "Unknown"
};
if (nameRva != 0)
{
uint nameOffset = _utility.RvaToOffset(nameRva);
reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
// Read the null-terminated ASCII string
StringBuilder nameBuilder = new StringBuilder();
byte b;
while ((b = reader.ReadByte()) != 0)
{
2025-04-20 19:54:52 +03:00
nameBuilder.Append((char) b);
}
2025-04-20 19:54:52 +03:00
descriptor.DllName = nameBuilder.ToString();
}
2025-04-20 19:54:52 +03:00
// Parse the imported functions
ParseImportedFunctions(reader, descriptor);
descriptors.Add(descriptor);
// Return to the import table to read the next descriptor
reader.BaseStream.Seek(importTableOffset + (descriptorCount * 20), SeekOrigin.Begin);
}
2025-04-20 19:54:52 +03:00
return descriptors;
}
2025-04-20 19:54:52 +03:00
/// <summary>
/// Parse the imported functions for a given import descriptor
/// </summary>
/// <param name="reader">The binary reader</param>
/// <param name="descriptor">The Import Descriptor</param>
private void ParseImportedFunctions(BinaryReader reader, ImportDescriptor descriptor)
{
2025-04-20 19:54:52 +03:00
// Use OriginalFirstThunk if available, otherwise use FirstThunk
uint thunkRva = descriptor.OriginalFirstThunkRva != 0
? descriptor.OriginalFirstThunkRva
: descriptor.FirstThunkRva;
if (thunkRva == 0)
{
return; // No functions to parse
}
uint thunkOffset = _utility.RvaToOffset(thunkRva);
int functionCount = 0;
while (true)
{
2025-04-20 19:54:52 +03:00
reader.BaseStream.Seek(thunkOffset + (functionCount * 4), SeekOrigin.Begin);
uint thunkData = reader.ReadUInt32();
if (thunkData == 0)
{
2025-04-20 19:54:52 +03:00
break; // End of the function list
}
2025-04-20 19:54:52 +03:00
ImportedFunction function = new ImportedFunction
{
2025-04-20 19:54:52 +03:00
ThunkRva = thunkRva + (uint) (functionCount * 4)
};
// Check if imported by ordinal (high bit set)
if ((thunkData & 0x80000000) != 0)
{
function.IsOrdinal = true;
function.Ordinal = (ushort) (thunkData & 0xFFFF);
function.Name = $"Ordinal {function.Ordinal}";
}
else
{
// Imported by name - the thunkData is an RVA to a hint/name structure
uint hintNameOffset = _utility.RvaToOffset(thunkData);
reader.BaseStream.Seek(hintNameOffset, SeekOrigin.Begin);
// Read the hint (2 bytes)
function.Hint = reader.ReadUInt16();
// Read the function name (null-terminated ASCII string)
StringBuilder nameBuilder = new StringBuilder();
byte b;
while ((b = reader.ReadByte()) != 0)
{
2025-04-20 19:54:52 +03:00
nameBuilder.Append((char) b);
}
2025-04-20 19:54:52 +03:00
function.Name = nameBuilder.ToString();
if (string.IsNullOrEmpty(function.Name))
{
2025-04-20 19:54:52 +03:00
function.Name = $"Function_at_{thunkData:X8}";
}
}
2025-04-20 19:54:52 +03:00
descriptor.Functions.Add(function);
functionCount++;
}
}
2025-04-20 19:54:52 +03:00
}