0
mirror of https://github.com/sampletext32/ParkanPlayground.git synced 2025-06-19 07:59:47 +03:00

clarify rva members

This commit is contained in:
bird_egop
2025-04-12 18:49:23 +03:00
parent d73cccd3c5
commit 60f63c2c06
10 changed files with 132 additions and 101 deletions

View File

@ -9,8 +9,8 @@ public class ExportDirectory
public uint TimeDateStamp; // Time and date stamp
public ushort MajorVersion; // Major version
public ushort MinorVersion; // Minor version
public uint Name; // RVA of the name of the DLL
public string DllName; // The actual name of the DLL
public uint DllNameRva; // RVA of the name of the DLL
public string DllName; // The actual name of the DLL
public uint Base; // Ordinal base
public uint NumberOfFunctions; // Number of functions
public uint NumberOfNames; // Number of names

View File

@ -7,7 +7,7 @@ public class ExportedFunction
{
public string Name; // Function name
public ushort Ordinal; // Function ordinal
public uint Address; // Function RVA
public uint AddressRva; // Function RVA
public bool IsForwarder; // True if this is a forwarder
public string ForwarderName; // Name of the forwarded function

View File

@ -5,12 +5,12 @@ namespace X86Disassembler.PE;
/// </summary>
public class ImportDescriptor
{
public uint OriginalFirstThunk; // RVA to original first thunk
public uint TimeDateStamp; // Time and date stamp
public uint ForwarderChain; // Forwarder chain
public uint Name; // RVA to the name of the DLL
public string DllName; // The actual name of the DLL
public uint FirstThunk; // RVA to first thunk
public uint OriginalFirstThunkRva; // RVA to original first thunk
public uint TimeDateStamp; // Time and date stamp
public uint ForwarderChain; // Forwarder chain
public uint DllNameRva; // RVA to the name of the DLL
public string DllName; // The actual name of the DLL
public uint FirstThunkRva; // RVA to first thunk
public List<ImportedFunction> Functions { get; } = new List<ImportedFunction>();

View File

@ -9,7 +9,7 @@ public class ImportedFunction
public ushort Hint; // Hint value
public bool IsOrdinal; // True if imported by ordinal
public ushort Ordinal; // Ordinal value (if imported by ordinal)
public uint ThunkRVA; // RVA of the thunk for this function
public uint ThunkRva; // RVA of the thunk for this function
/// <summary>
/// Initializes a new instance of the ImportedFunction class

View File

@ -21,27 +21,27 @@ public class OptionalHeader
public uint BaseOfData; // Base of data section (PE32 only)
// Windows-specific fields
public ulong ImageBase; // Image base address (uint for PE32, ulong for PE32+)
public uint SectionAlignment; // Section alignment
public uint FileAlignment; // File alignment
public ushort MajorOperatingSystemVersion; // Major OS version
public ushort MinorOperatingSystemVersion; // Minor OS version
public ushort MajorImageVersion; // Major image version
public ushort MinorImageVersion; // Minor image version
public ushort MajorSubsystemVersion; // Major subsystem version
public ushort MinorSubsystemVersion; // Minor subsystem version
public uint Win32VersionValue; // Win32 version value
public uint SizeOfImage; // Size of image
public uint SizeOfHeaders; // Size of headers
public uint CheckSum; // Checksum
public ushort Subsystem; // Subsystem
public ushort DllCharacteristics; // DLL characteristics
public ulong SizeOfStackReserve; // Size of stack reserve (uint for PE32, ulong for PE32+)
public ulong SizeOfStackCommit; // Size of stack commit (uint for PE32, ulong for PE32+)
public ulong SizeOfHeapReserve; // Size of heap reserve (uint for PE32, ulong for PE32+)
public ulong SizeOfHeapCommit; // Size of heap commit (uint for PE32, ulong for PE32+)
public uint LoaderFlags; // Loader flags
public uint NumberOfRvaAndSizes; // Number of RVA and sizes
public ulong ImageBase; // Image base address (uint for PE32, ulong for PE32+)
public uint SectionAlignment; // Section alignment
public uint FileAlignment; // File alignment
public ushort MajorOperatingSystemVersion; // Major OS version
public ushort MinorOperatingSystemVersion; // Minor OS version
public ushort MajorImageVersion; // Major image version
public ushort MinorImageVersion; // Minor image version
public ushort MajorSubsystemVersion; // Major subsystem version
public ushort MinorSubsystemVersion; // Minor subsystem version
public uint Win32VersionValue; // Win32 version value
public uint SizeOfImage; // Size of image
public uint SizeOfHeaders; // Size of headers
public uint CheckSum; // Checksum
public ushort Subsystem; // Subsystem
public ushort DllCharacteristics; // DLL characteristics
public ulong SizeOfStackReserve; // Size of stack reserve (uint for PE32, ulong for PE32+)
public ulong SizeOfStackCommit; // Size of stack commit (uint for PE32, ulong for PE32+)
public ulong SizeOfHeapReserve; // Size of heap reserve (uint for PE32, ulong for PE32+)
public ulong SizeOfHeapCommit; // Size of heap commit (uint for PE32, ulong for PE32+)
public uint LoaderFlags; // Loader flags
public uint NumberOfRvaAndSizes; // Number of RVA and sizes
public DataDirectory[] DataDirectories; // Data directories
@ -58,7 +58,7 @@ public class OptionalHeader
SizeOfHeapCommit = 0u;
// Initialize array to avoid nullability warning
DataDirectories = new DataDirectory[0];
DataDirectories = [];
}
/// <summary>

View File

@ -8,39 +8,39 @@ namespace X86Disassembler.PE;
public class PEFormat
{
// DOS Header constants
private const ushort DOS_SIGNATURE = 0x5A4D; // 'MZ'
private const uint PE_SIGNATURE = 0x00004550; // 'PE\0\0'
private const ushort DOS_SIGNATURE = 0x5A4D; // 'MZ'
private const uint PE_SIGNATURE = 0x00004550; // 'PE\0\0'
// Optional Header Magic values
private const ushort PE32_MAGIC = 0x10B; // 32-bit executable
private const ushort PE32PLUS_MAGIC = 0x20B; // 64-bit executable
private const ushort PE32_MAGIC = 0x10B; // 32-bit executable
private const ushort PE32PLUS_MAGIC = 0x20B; // 64-bit executable
// Section characteristics flags
private const uint IMAGE_SCN_CNT_CODE = 0x00000020; // Section contains code
private const uint IMAGE_SCN_MEM_EXECUTE = 0x20000000; // Section is executable
private const uint IMAGE_SCN_MEM_READ = 0x40000000; // Section is readable
private const uint IMAGE_SCN_MEM_WRITE = 0x80000000; // Section is writable
private const uint IMAGE_SCN_CNT_CODE = 0x00000020; // Section contains code
private const uint IMAGE_SCN_MEM_EXECUTE = 0x20000000; // Section is executable
private const uint IMAGE_SCN_MEM_READ = 0x40000000; // Section is readable
private const uint IMAGE_SCN_MEM_WRITE = 0x80000000; // Section is writable
// Data directories
private const int IMAGE_DIRECTORY_ENTRY_EXPORT = 0; // Export Directory
private const int IMAGE_DIRECTORY_ENTRY_IMPORT = 1; // Import Directory
private const int IMAGE_DIRECTORY_ENTRY_RESOURCE = 2; // Resource Directory
private const int IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3; // Exception Directory
private const int IMAGE_DIRECTORY_ENTRY_SECURITY = 4; // Security Directory
private const int IMAGE_DIRECTORY_ENTRY_BASERELOC = 5; // Base Relocation Table
private const int IMAGE_DIRECTORY_ENTRY_DEBUG = 6; // Debug Directory
private const int IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7; // Architecture Specific Data
private const int IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8; // RVA of GP
private const int IMAGE_DIRECTORY_ENTRY_TLS = 9; // TLS Directory
private const int IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10; // Load Configuration Directory
private const int IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11; // Bound Import Directory
private const int IMAGE_DIRECTORY_ENTRY_IAT = 12; // Import Address Table
private const int IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13; // Delay Load Import Descriptors
private const int IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14; // COM Runtime descriptor
private const int IMAGE_DIRECTORY_ENTRY_EXPORT = 0; // Export Directory
private const int IMAGE_DIRECTORY_ENTRY_IMPORT = 1; // Import Directory
private const int IMAGE_DIRECTORY_ENTRY_RESOURCE = 2; // Resource Directory
private const int IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3; // Exception Directory
private const int IMAGE_DIRECTORY_ENTRY_SECURITY = 4; // Security Directory
private const int IMAGE_DIRECTORY_ENTRY_BASERELOC = 5; // Base Relocation Table
private const int IMAGE_DIRECTORY_ENTRY_DEBUG = 6; // Debug Directory
private const int IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7; // Architecture Specific Data
private const int IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8; // RVA of GP
private const int IMAGE_DIRECTORY_ENTRY_TLS = 9; // TLS Directory
private const int IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10; // Load Configuration Directory
private const int IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11; // Bound Import Directory
private const int IMAGE_DIRECTORY_ENTRY_IAT = 12; // Import Address Table
private const int IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13; // Delay Load Import Descriptors
private const int IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14; // COM Runtime descriptor
// PE file data
private byte[] _fileData;
// Parser instances
private readonly DOSHeaderParser _dosHeaderParser;
private readonly FileHeaderParser _fileHeaderParser;
@ -49,19 +49,19 @@ public class PEFormat
private PEUtility _peUtility;
private ExportDirectoryParser _exportDirectoryParser;
private ImportDescriptorParser _importDescriptorParser;
// Parsed headers
public DOSHeader DosHeader { get; private set; }
public FileHeader FileHeader { get; private set; }
public OptionalHeader OptionalHeader { get; private set; }
public List<SectionHeader> SectionHeaders { get; private set; }
public bool Is64Bit { get; private set; }
// Export and Import information
public ExportDirectory ExportDirectory { get; private set; }
public List<ExportedFunction> ExportedFunctions { get; private set; }
public List<ImportDescriptor> ImportDescriptors { get; private set; }
/// <summary>
/// Initializes a new instance of the PEFormat class
/// </summary>
@ -72,25 +72,25 @@ public class PEFormat
SectionHeaders = new List<SectionHeader>();
ExportedFunctions = new List<ExportedFunction>();
ImportDescriptors = new List<ImportDescriptor>();
// Initialize parsers
_dosHeaderParser = new DOSHeaderParser();
_fileHeaderParser = new FileHeaderParser();
_optionalHeaderParser = new OptionalHeaderParser();
_sectionHeaderParser = new SectionHeaderParser();
// Initialize properties to avoid nullability warnings
DosHeader = new DOSHeader();
FileHeader = new FileHeader();
OptionalHeader = new OptionalHeader();
ExportDirectory = new ExportDirectory();
// These will be initialized during Parse()
_peUtility = null!;
_exportDirectoryParser = null!;
_importDescriptorParser = null!;
}
/// <summary>
/// Parses the PE file structure
/// </summary>
@ -104,55 +104,60 @@ public class PEFormat
{
// Parse DOS header
DosHeader = _dosHeaderParser.Parse(reader);
// Move to PE header
reader.BaseStream.Seek(DosHeader.e_lfanew, SeekOrigin.Begin);
// Verify PE signature
uint peSignature = reader.ReadUInt32();
if (peSignature != PE_SIGNATURE)
{
throw new InvalidDataException("Invalid PE signature");
}
// Parse File Header
FileHeader = _fileHeaderParser.Parse(reader);
// Parse Optional Header
OptionalHeader = _optionalHeaderParser.Parse(reader);
Is64Bit = OptionalHeader.Is64Bit();
// Parse Section Headers
for (int i = 0; i < FileHeader.NumberOfSections; i++)
{
SectionHeaders.Add(_sectionHeaderParser.Parse(reader));
}
// Initialize utility after section headers are parsed
_peUtility = new PEUtility(SectionHeaders, OptionalHeader.SizeOfHeaders);
_exportDirectoryParser = new ExportDirectoryParser(_peUtility);
_importDescriptorParser = new ImportDescriptorParser(_peUtility);
// Parse Export Directory
if (OptionalHeader.DataDirectories.Length > IMAGE_DIRECTORY_ENTRY_EXPORT &&
if (OptionalHeader.DataDirectories.Length > IMAGE_DIRECTORY_ENTRY_EXPORT &&
OptionalHeader.DataDirectories[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress != 0)
{
uint exportDirRva = OptionalHeader.DataDirectories[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
uint exportDirSize = OptionalHeader.DataDirectories[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
ExportDirectory = _exportDirectoryParser.Parse(reader, exportDirRva);
ExportedFunctions = _exportDirectoryParser.ParseExportedFunctions(reader, ExportDirectory, exportDirRva, exportDirSize);
ExportedFunctions = _exportDirectoryParser.ParseExportedFunctions(
reader,
ExportDirectory,
exportDirRva,
exportDirSize
);
}
// Parse Import Descriptors
if (OptionalHeader.DataDirectories.Length > IMAGE_DIRECTORY_ENTRY_IMPORT &&
if (OptionalHeader.DataDirectories.Length > IMAGE_DIRECTORY_ENTRY_IMPORT &&
OptionalHeader.DataDirectories[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress != 0)
{
uint importDirRva = OptionalHeader.DataDirectories[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
ImportDescriptors = _importDescriptorParser.Parse(reader, importDirRva);
}
}
return true;
}
catch (Exception ex)
@ -161,7 +166,7 @@ public class PEFormat
return false;
}
}
/// <summary>
/// Gets the raw data for a specific section
/// </summary>
@ -173,15 +178,21 @@ public class PEFormat
{
throw new ArgumentOutOfRangeException(nameof(sectionIndex));
}
SectionHeader section = SectionHeaders[sectionIndex];
byte[] sectionData = new byte[section.SizeOfRawData];
Array.Copy(_fileData, section.PointerToRawData, sectionData, 0, section.SizeOfRawData);
Array.Copy(
_fileData,
section.PointerToRawData,
sectionData,
0,
section.SizeOfRawData
);
return sectionData;
}
/// <summary>
/// Gets the raw data for a section by name
/// </summary>
@ -196,10 +207,10 @@ public class PEFormat
return GetSectionData(i);
}
}
throw new ArgumentException($"Section '{sectionName}' not found");
}
/// <summary>
/// Gets all code sections
/// </summary>
@ -207,18 +218,19 @@ public class PEFormat
public List<int> GetCodeSections()
{
List<int> codeSections = new List<int>();
for (int i = 0; i < SectionHeaders.Count; i++)
{
if (SectionHeaders[i].ContainsCode())
if (SectionHeaders[i]
.ContainsCode())
{
codeSections.Add(i);
}
}
return codeSections;
}
/// <summary>
/// Checks if a section contains code
/// </summary>

View File

@ -30,7 +30,7 @@ public class ExportDirectoryParser
directory.TimeDateStamp = reader.ReadUInt32();
directory.MajorVersion = reader.ReadUInt16();
directory.MinorVersion = reader.ReadUInt16();
directory.Name = reader.ReadUInt32();
directory.DllNameRva = reader.ReadUInt32();
directory.Base = reader.ReadUInt32();
directory.NumberOfFunctions = reader.ReadUInt32();
directory.NumberOfNames = reader.ReadUInt32();
@ -41,7 +41,7 @@ public class ExportDirectoryParser
// Read the DLL name
try
{
uint dllNameRVA = directory.Name;
uint dllNameRVA = directory.DllNameRva;
uint dllNameOffset = _utility.RvaToOffset(dllNameRVA);
reader.BaseStream.Seek(dllNameOffset, SeekOrigin.Begin);
@ -134,7 +134,7 @@ public class ExportDirectoryParser
ExportedFunction function = new ExportedFunction();
function.Ordinal = (ushort)(i + directory.Base);
function.Address = functionRVA;
function.AddressRva = functionRVA;
// Check if this function has a name
if (ordinalToName.TryGetValue(i, out string? name))

View File

@ -50,11 +50,11 @@ public class ImportDescriptorParser
ImportDescriptor descriptor = new ImportDescriptor
{
OriginalFirstThunk = originalFirstThunk,
OriginalFirstThunkRva = originalFirstThunk,
TimeDateStamp = timeDateStamp,
ForwarderChain = forwarderChain,
Name = nameRva,
FirstThunk = firstThunk,
DllNameRva = nameRva,
FirstThunkRva = firstThunk,
DllName = "Unknown" // Default name in case we can't read it
};
@ -111,7 +111,7 @@ public class ImportDescriptorParser
try
{
// Use OriginalFirstThunk if available, otherwise use FirstThunk
uint thunkRva = descriptor.OriginalFirstThunk != 0 ? descriptor.OriginalFirstThunk : descriptor.FirstThunk;
uint thunkRva = descriptor.OriginalFirstThunkRva != 0 ? descriptor.OriginalFirstThunkRva : descriptor.FirstThunkRva;
if (thunkRva == 0)
{
@ -133,7 +133,7 @@ public class ImportDescriptorParser
ImportedFunction function = new ImportedFunction
{
ThunkRVA = thunkRva + (uint)(functionCount * 4)
ThunkRva = thunkRva + (uint)(functionCount * 4)
};
// Check if imported by ordinal (high bit set)

View File

@ -99,7 +99,7 @@ internal class Program
for (int i = 0; i < peFormat.ExportedFunctions.Count; i++)
{
var function = peFormat.ExportedFunctions[i];
Console.WriteLine($" {i}: {function.Name} (Ordinal={function.Ordinal}, RVA=0x{function.Address:X8})");
Console.WriteLine($" {i}: {function.Name} (Ordinal={function.Ordinal}, RVA=0x{function.AddressRva:X8})");
}
}