Momentan arbeite ich wieder an einem Feature dass eine Weile geruht hat: Struktur-Editor/Viewer.
PE-Dateien sind momentan die Vorlage um zu schauen welche Funktionalität notwendig ist. Bisher kann ich dynamische Array definieren bzw. Strukturen variabler Größe, wo andere Teile der Datei diese Größe angeben, bzw. Zeiger darauf verweisen, anstatt dass alle Offsets/Größen fest/konstant sind.
Das nächste Feature wird das dynamische Dekodieren von RVA (relativen virtuellen Addressen) in der
PE Datei sein, mithilfe einer Mapping-Funktion die jeder Pointer-Typ haben kann.
Um Dateien strukturiert anzuzeigen, werden Strukturen in einer deklarativen Sprache (die noch im Fluss ist), der HxD-Struktur-Definition-Syntax (HSD), definiert.
Ein funktionierendes Beispiel für den
PE-Header sieht wie folgt aus:
Code:
types
PVirtualAddress = pointer<UInt32, UInt32>
IMAGE_DATA_DIRECTORY = struct {
VirtualAddress: UInt32;
Size: UInt32;
}
IMAGE_FILE_HEADER = struct {
Machine: UInt16;
NumberOfSections: UInt16;
TimeDateStamp: UInt32;
PointerToSymbolTable: UInt32;
NumberOfSymbols: UInt32;
SizeOfOptionalHeader: UInt16;
Characteristics: UInt16;
}
IMAGE_OPTIONAL_HEADER32 = struct {
Magic: UInt16;
MajorLinkerVersion: UInt8;
MinorLinkerVersion: UInt8;
SizeOfCode: UInt32;
SizeOfInitializedData: UInt32;
SizeOfUninitializedData: UInt32;
AddressOfEntryPoint: UInt32;
BaseOfCode: UInt32;
BaseOfData: UInt32;
ImageBase: UInt32;
SectionAlignment: UInt32;
FileAlignment: UInt32;
MajorOperatingSystemVersion: UInt16;
MinorOperatingSystemVersion: UInt16;
MajorImageVersion: UInt16;
MinorImageVersion: UInt16;
MajorSubsystemVersion: UInt16;
MinorSubsystemVersion: UInt16;
Win32VersionValue: UInt32;
SizeOfImage: UInt32;
SizeOfHeaders: UInt32;
CheckSum: UInt32;
Subsystem: UInt16;
DllCharacteristics: UInt16;
SizeOfStackReserve: UInt32;
SizeOfStackCommit: UInt32;
SizeOfHeapReserve: UInt32;
SizeOfHeapCommit: UInt32;
LoaderFlags: UInt32;
NumberOfRvaAndSizes: UInt32;
DataDirectory: IMAGE_DATA_DIRECTORY[:NumberOfRvaAndSizes];
}
IMAGE_NT_HEADERS32 = struct {
Signature: UInt8[4];
FileHeader: IMAGE_FILE_HEADER;
OptionalHeader: IMAGE_OPTIONAL_HEADER32;
}
PIMAGE_NT_HEADERS32 = pointer<UInt32, IMAGE_NT_HEADERS32>
IMAGE_DOS_HEADER = struct {
e_magic: UInt8[2];
e_cblp: UInt16;
e_cp: UInt16;
e_crlc: UInt16;
e_cparhdr: UInt16;
e_minalloc: UInt16;
e_maxalloc: UInt16;
e_ss: UInt16;
e_sp: UInt16;
e_csum: UInt16;
e_ip: UInt16;
e_cs: UInt16;
e_lfarlc: UInt16;
e_ovno: UInt16;
e_res: UInt16[4];
e_oemid: UInt16;
e_oeminfo: UInt16;
e_res2: UInt16[10];
_lfanew: UInt32;
}
IMAGE_SECTION_HEADER = struct {
Name: Char8Ansi[8];
Misc_PhysicalAddressOrVirtualSize: UInt32;
VirtualAddress: UInt32;
SizeOfRawData: UInt32;
PointerToRawData: UInt32;
PointerToRelocations: UInt32;
PointerToLinenumbers: UInt32;
NumberOfRelocations: UInt16;
NumberOfLinenumbers: UInt16;
Characteristics: UInt32;
}
IMAGE_IMPORT_DESCRIPTOR = struct {
OriginalFirstThunk_ImportLookupTable_RVA: UInt32;
TimeDateStamp: UInt32;
ForwarderChain: UInt32;
Name_RVA: UInt32;
FirstThunk_ImportAddressTable_RVA: UInt32;
}
OVERALL_FILE = struct {
ImageDosHeader: IMAGE_DOS_HEADER;
ImageNtHeaders32: IMAGE_NT_HEADERS32 @ :ImageDosHeader._lfanew;
ImageSectionHeaders: IMAGE_SECTION_HEADER[:ImageNtHeaders32.FileHeader.NumberOfSections];
}
instances
$root: OVERALL_FILE
Das sieht dann nach dem parsen von PropEdit.exe (ein anderes meiner Programme -- kann aber ein beliebiges sein), so wie in den Anhängen aus.