mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2025-05-21 12:51:18 +03:00
Fix import directory parsing to properly resolve all DLL names and functions
This commit is contained in:
parent
f5bacc018c
commit
8dfc0b1a7b
@ -335,120 +335,164 @@ namespace X86Disassembler
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
reader.BaseStream.Seek(RvaToOffset(rva), SeekOrigin.Begin);
|
uint importTableOffset = RvaToOffset(rva);
|
||||||
|
reader.BaseStream.Seek(importTableOffset, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
int descriptorCount = 0;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
ImportDescriptor descriptor = new ImportDescriptor();
|
descriptorCount++;
|
||||||
|
|
||||||
descriptor.OriginalFirstThunk = reader.ReadUInt32();
|
// Read the import descriptor
|
||||||
descriptor.TimeDateStamp = reader.ReadUInt32();
|
uint originalFirstThunk = reader.ReadUInt32();
|
||||||
descriptor.ForwarderChain = reader.ReadUInt32();
|
uint timeDateStamp = reader.ReadUInt32();
|
||||||
descriptor.Name = reader.ReadUInt32();
|
uint forwarderChain = reader.ReadUInt32();
|
||||||
descriptor.FirstThunk = reader.ReadUInt32();
|
uint nameRva = reader.ReadUInt32();
|
||||||
|
uint firstThunk = reader.ReadUInt32();
|
||||||
|
|
||||||
// Check if we've reached the end of the import descriptors
|
// Check if we've reached the end of the import descriptors
|
||||||
if (descriptor.OriginalFirstThunk == 0 && descriptor.Name == 0 && descriptor.FirstThunk == 0)
|
if (originalFirstThunk == 0 && nameRva == 0 && firstThunk == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImportDescriptor descriptor = new ImportDescriptor
|
||||||
|
{
|
||||||
|
OriginalFirstThunk = originalFirstThunk,
|
||||||
|
TimeDateStamp = timeDateStamp,
|
||||||
|
ForwarderChain = forwarderChain,
|
||||||
|
Name = nameRva,
|
||||||
|
FirstThunk = firstThunk,
|
||||||
|
DllName = "Unknown" // Default name in case we can't read it
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try to read the DLL name
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Read the DLL name
|
if (nameRva != 0)
|
||||||
uint dllNameOffset = RvaToOffset(descriptor.Name);
|
|
||||||
reader.BaseStream.Seek(dllNameOffset, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
List<byte> nameBytes = new List<byte>();
|
|
||||||
byte b;
|
|
||||||
while ((b = reader.ReadByte()) != 0)
|
|
||||||
{
|
{
|
||||||
nameBytes.Add(b);
|
uint nameOffset = RvaToOffset(nameRva);
|
||||||
}
|
reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
|
||||||
descriptor.DllName = Encoding.ASCII.GetString(nameBytes.ToArray());
|
|
||||||
|
// Read the null-terminated ASCII string
|
||||||
// Read the imported functions (use FirstThunk if OriginalFirstThunk is 0)
|
StringBuilder nameBuilder = new StringBuilder();
|
||||||
uint thunkRVA = descriptor.OriginalFirstThunk != 0 ? descriptor.OriginalFirstThunk : descriptor.FirstThunk;
|
byte b;
|
||||||
|
|
||||||
if (thunkRVA != 0)
|
while ((b = reader.ReadByte()) != 0)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
uint thunkOffset = RvaToOffset(thunkRVA);
|
nameBuilder.Append((char)b);
|
||||||
uint currentThunkOffset = thunkOffset;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
reader.BaseStream.Seek(currentThunkOffset, SeekOrigin.Begin);
|
|
||||||
uint thunk = reader.ReadUInt32();
|
|
||||||
|
|
||||||
if (thunk == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImportedFunction function = new ImportedFunction();
|
|
||||||
function.ThunkRVA = thunkRVA + (currentThunkOffset - thunkOffset);
|
|
||||||
|
|
||||||
// Check if the function is imported by ordinal
|
|
||||||
if ((thunk & 0x80000000) != 0)
|
|
||||||
{
|
|
||||||
function.IsOrdinal = true;
|
|
||||||
function.Ordinal = (ushort)(thunk & 0xFFFF);
|
|
||||||
function.Name = $"Ordinal_{function.Ordinal}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Read the function name and hint
|
|
||||||
try
|
|
||||||
{
|
|
||||||
uint nameOffset = RvaToOffset(thunk);
|
|
||||||
reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
function.Hint = reader.ReadUInt16();
|
|
||||||
|
|
||||||
List<byte> funcNameBytes = new List<byte>();
|
|
||||||
byte c;
|
|
||||||
while ((c = reader.ReadByte()) != 0)
|
|
||||||
{
|
|
||||||
funcNameBytes.Add(c);
|
|
||||||
}
|
|
||||||
function.Name = Encoding.ASCII.GetString(funcNameBytes.ToArray());
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
function.Name = $"Function_at_{thunk:X8}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptor.Functions.Add(function);
|
|
||||||
|
|
||||||
currentThunkOffset += 4; // Move to the next thunk
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// Skip this thunk table if there's an error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descriptor.DllName = nameBuilder.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
// If we can't read the DLL name, use a placeholder
|
// If we can't read the name, keep the default "Unknown"
|
||||||
descriptor.DllName = $"DLL_at_{descriptor.Name:X8}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse the imported functions
|
||||||
|
ParseImportedFunctions(reader, descriptor);
|
||||||
|
|
||||||
descriptors.Add(descriptor);
|
descriptors.Add(descriptor);
|
||||||
|
|
||||||
|
// Return to the import table to read the next descriptor
|
||||||
|
reader.BaseStream.Seek(importTableOffset + (descriptorCount * 20), SeekOrigin.Begin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"Error parsing import descriptors: {ex.Message}");
|
||||||
// Return whatever descriptors we've managed to parse
|
// Return whatever descriptors we've managed to parse
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptors;
|
return descriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the imported functions for a given import descriptor
|
||||||
|
/// </summary>
|
||||||
|
private void ParseImportedFunctions(BinaryReader reader, ImportDescriptor descriptor)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Use OriginalFirstThunk if available, otherwise use FirstThunk
|
||||||
|
uint thunkRva = descriptor.OriginalFirstThunk != 0 ? descriptor.OriginalFirstThunk : descriptor.FirstThunk;
|
||||||
|
|
||||||
|
if (thunkRva == 0)
|
||||||
|
{
|
||||||
|
return; // No functions to parse
|
||||||
|
}
|
||||||
|
|
||||||
|
uint thunkOffset = RvaToOffset(thunkRva);
|
||||||
|
int functionCount = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
reader.BaseStream.Seek(thunkOffset + (functionCount * 4), SeekOrigin.Begin);
|
||||||
|
uint thunkData = reader.ReadUInt32();
|
||||||
|
|
||||||
|
if (thunkData == 0)
|
||||||
|
{
|
||||||
|
break; // End of the function list
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportedFunction function = new ImportedFunction
|
||||||
|
{
|
||||||
|
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
|
||||||
|
try
|
||||||
|
{
|
||||||
|
uint hintNameOffset = 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)
|
||||||
|
{
|
||||||
|
nameBuilder.Append((char)b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function.Name = nameBuilder.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(function.Name))
|
||||||
|
{
|
||||||
|
function.Name = $"Function_at_{thunkData:X8}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
function.Name = $"Function_at_{thunkData:X8}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor.Functions.Add(function);
|
||||||
|
functionCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error parsing imported functions for {descriptor.DllName}: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses the exported functions using the export directory information
|
/// Parses the exported functions using the export directory information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user