0,0 → 1,297 |
(************************************************************ |
|
Simple Stripped PE Binary File Dumper |
|
************************************************************) |
Unit SPEDump; |
(* -------------------------------------------------------- *) |
Interface |
(* -------------------------------------------------------- *) |
Uses KolibriOS; |
(* -------------------------------------------------------- *) |
Type |
Dword = LongWord; |
|
PDword = ^Dword; |
|
TDwordArray = Packed Array[0..0] Of Dword; |
|
PDwordArray = ^TDwordArray; |
|
Const |
STRIPPED_PE_SIGNATURE = $4503; // 'PE' Xor 'S' |
SPE_DIRECTORY_IMPORT = 0; |
SPE_DIRECTORY_EXPORT = 1; |
SPE_DIRECTORY_BASERELOC = 2; |
|
SPE_MAX_DIRECTORY_ENTRIES = SPE_DIRECTORY_BASERELOC; |
|
Type |
TStrippedPEHeader = Packed Record |
Signature: Word; |
Characteristics: Word; |
AddressOfEntryPoint: Dword; |
ImageBase: Dword; |
SectionAlignmentLog: Byte; |
FileAlignmentLog: Byte; |
MajorOSVersion: Byte; |
MinorOSVersion: Byte; |
SizeOfImage: Dword; |
SizeOfStackReserve: Dword; |
SizeOfHeapReserve: Dword; |
SizeOfHeaders: Dword; |
Subsystem: Byte; |
NumberOfRvaAndSizes: Byte; |
NumberOfSections: Word; |
End; |
|
PStrippedPEHeader = ^TStrippedPEHeader; |
|
TStrippedSectionHeader = Packed Record |
Name: Packed Array[0..7] Of Char; |
VirtualSize: Dword; |
VirtualAddress: Dword; |
SizeOfRawData: Dword; |
PointerToRawData: Dword; |
Characteristics: Dword; |
End; |
|
PStrippedSectionHeader = ^TStrippedSectionHeader; |
|
TDataDirectory = Packed Record |
VirtualAddress: Dword; |
Size: Dword; |
End; |
|
PDataDirectory = ^TDataDirectory; |
|
TDataDirectoryArray = Packed Array[0..SPE_MAX_DIRECTORY_ENTRIES] Of TDataDirectory; |
|
PDataDirectoryArray = ^TDataDirectoryArray; |
|
TImportDescriptor = Packed Record |
OriginalFirstThunk: Dword; |
TimeDateStamp: Dword; |
ForwarderChain: Dword; |
Name: Dword; |
FirstThunk: Dword; |
End; |
|
PImportDescriptor = ^TImportDescriptor; |
|
TExportDescriptor = Packed Record |
Characteristics: Dword; |
TimeDateStamp: Dword; |
MajorVersion: Word; |
MinorVersion: Word; |
Name: Dword; |
Base: Dword; |
NumberOfFunctions: Dword; |
NumberOfNames: Dword; |
AddressOfFunctions: Dword; |
AddressOfNames: Dword; |
AddressOfNameOrdinals: Dword; |
End; |
|
PExportDescriptor = ^TExportDescriptor; |
|
Var |
FileName: PChar; |
FileHandle: Integer; |
FileLength: Dword; |
BytesRead: Dword; |
Buffer: PStrippedPEHeader; |
Section: PStrippedSectionHeader; |
DataDirectory: PDataDirectoryArray; |
ImportDescriptor: PImportDescriptor; |
ExportDescriptor: PExportDescriptor; |
Thunk: PDword; |
|
(* --------------------- Console stuff -------------------- *) |
hConsole: Pointer; |
ConsoleInit: Procedure(WndWidth, WndHeight, ScrWidth, ScrHeight: Dword; Caption: PChar); StdCall; |
ConsoleExit: Procedure(bCloseWindow: Boolean); StdCall; |
Printf: Function(Const Format: PChar): Integer; CDecl VarArgs; |
GetCh: Function: Integer; StdCall; |
WriteN: Procedure(Const Str: PChar; Count: Dword); StdCall; |
Write: Procedure(Const Str: PChar); StdCall; |
|
(* -------------------------------------------------------- *) |
Procedure Main; |
Function FileIsValid: Boolean; |
Procedure WriteHex(Number: Dword); |
Procedure WriteLn(Text: PChar); |
(* -------------------------------------------------------- *) |
Implementation |
(* -------------------------------------------------------- *) |
Function FileIsValid : Boolean; |
Begin |
FileIsValid := FALSE; |
With Buffer^ Do Begin |
If BytesRead < SizeOf(TStrippedPEHeader) Then Exit; |
If Signature <> STRIPPED_PE_SIGNATURE Then Exit; |
End; |
FileIsValid := TRUE; |
End; |
(* -------------------------------------------------------- *) |
Function RVA2Offset(RVA: Dword; StrippedPEHeader: PStrippedPEHeader): Dword; |
Var |
i: Dword; |
StrippedSectionHeader: PStrippedSectionHeader; |
Begin |
With StrippedPEHeader^ Do Begin |
StrippedSectionHeader := PStrippedSectionHeader(Dword(StrippedPEHeader) + SizeOf(TStrippedPEHeader) + NumberOfRvaAndSizes * SizeOf(TDataDirectory)); |
For i := 0 To NumberOfSections Do Begin |
With StrippedSectionHeader^ Do Begin |
If (RVA >= VirtualAddress) And (RVA < VirtualAddress + SizeOfRawData) Then Begin |
Result := PointerToRawData + RVA - VirtualAddress; |
Exit; |
End; |
End; |
Inc(StrippedSectionHeader); |
End; |
End; |
Result := 0; |
End; |
(* -------------------------------------------------------- *) |
Procedure WriteHex(Number: Dword); Begin Printf('%X', Number); End; |
(* -------------------------------------------------------- *) |
Procedure WriteLn(Text: PChar); Begin Printf('%s'#10, Text); End; |
(* -------------------------------------------------------- *) |
Procedure Main; |
Const |
CmdLine = PPChar(28); |
Var |
i: Dword; |
Begin |
hConsole := LoadLibrary('/sys/lib/console.obj'); |
ConsoleInit := GetProcAddress(hConsole, 'con_init'); |
ConsoleExit := GetProcAddress(hConsole, 'con_exit'); |
Printf := GetProcAddress(hConsole, 'con_printf'); |
GetCh := GetProcAddress(hConsole, 'con_getch'); |
WriteN := GetProcAddress(hConsole, 'con_write_string'); |
Write := GetProcAddress(hConsole, 'con_write_asciiz'); |
ConsoleInit($FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, 'SPEDump'); |
|
(* skip spaces *) |
i := 0; While CmdLine^[i] = ' ' Do Inc(i); |
FileName := @CmdLine^[i]; |
|
WriteLn('Simple Stripped PE Binary File Dumper Version 0.1; 2018.'); |
If FileName[0] = #0 Then Begin |
WriteLn('Usage: SPEDump [<file>]') |
End Else Begin |
WriteLn(''); Write('Dump of "'); Write(FileName); WriteLn('"'); WriteLn(''); |
Buffer := PStrippedPEHeader(LoadFile(FileName, BytesRead)); |
If Buffer <> Nil Then Begin |
|
If FileIsValid Then Begin |
WriteLn('File header'); |
WriteLn('-----------'); |
|
With Buffer^ Do Begin |
Write(' Signature = '); WriteHex(Signature); WriteLn(''); |
Write(' Characteristics = '); WriteHex(Characteristics); WriteLn(''); |
Write(' AddressOfEntryPoint = '); WriteHex(AddressOfEntryPoint); WriteLn(''); |
Write(' ImageBase = '); WriteHex(ImageBase); WriteLn(''); |
Write(' SectionAlignmentLog = '); WriteHex(SectionAlignmentLog); WriteLn(''); |
Write(' FileAlignmentLog = '); WriteHex(FileAlignmentLog); WriteLn(''); |
Write(' MajorOSVersion = '); WriteHex(MajorOSVersion); WriteLn(''); |
Write(' MinorOSVersion = '); WriteHex(MinorOSVersion); WriteLn(''); |
Write(' SizeOfImage = '); WriteHex(SizeOfImage); WriteLn(''); |
Write(' SizeOfStackReserve = '); WriteHex(SizeOfStackReserve); WriteLn(''); |
Write(' SizeOfHeapReserve = '); WriteHex(SizeOfHeapReserve); WriteLn(''); |
Write(' SizeOfHeaders = '); WriteHex(SizeOfHeaders); WriteLn(''); |
Write(' Subsystem = '); WriteHex(Subsystem); WriteLn(''); |
Write(' NumberOfRvaAndSizes = '); WriteHex(NumberOfRvaAndSizes); WriteLn(''); |
Write(' NumberOfSections = '); WriteHex(NumberOfSections); WriteLn(''); |
|
WriteLn(''); |
|
If NumberOfSections > 0 Then Begin |
i := 1; |
Section := PStrippedSectionHeader(Dword(Buffer) + SizeOf(TStrippedPEHeader) + NumberOfRvaAndSizes * SizeOf(TDataDirectory)); |
Repeat |
Write('Section #'); WriteHex(i); WriteLn(''); |
WriteLn('-----------'); |
With Section^ Do Begin |
Write(' Name = '); |
(* Handle situation when Name length = 8 Then Name is NOT ASCIIZ *) |
If Name[High(Name)] <> #0 Then WriteN(Name, 8) Else Write(Name); |
WriteLn(''); |
Write(' VirtualSize = '); WriteHex(VirtualSize); WriteLn(''); |
Write(' VirtualAddress = '); WriteHex(VirtualAddress); WriteLn(''); |
Write(' SizeOfRawData = '); WriteHex(SizeOfRawData); WriteLn(''); |
Write(' PointerToRawData = '); WriteHex(PointerToRawData); WriteLn(''); |
Write(' Flags = '); WriteHex(Characteristics); WriteLn(''); |
End; |
WriteLn(''); |
inc(Section); |
inc(i); |
Until i > NumberOfSections; |
|
DataDirectory := PDataDirectoryArray(Dword(Buffer) + SizeOf(TStrippedPEHeader)); |
|
If NumberOfRvaAndSizes > SPE_DIRECTORY_IMPORT Then Begin |
If DataDirectory[SPE_DIRECTORY_IMPORT].VirtualAddress <> 0 Then Begin |
WriteLn('Imports'); |
WriteLn('-------'); |
ImportDescriptor := PImportDescriptor(RVA2Offset(DataDirectory[SPE_DIRECTORY_IMPORT].VirtualAddress, Buffer) + Dword(Buffer)); |
While ImportDescriptor.Name <> 0 Do Begin |
With ImportDescriptor^ Do Begin |
Write(' OriginalFirstThunk = '); WriteHex(OriginalFirstThunk); WriteLn(''); |
Write(' TimeDateStamp = '); WriteHex(TimeDateStamp); WriteLn(''); |
Write(' ForwarderChain = '); WriteHex(ForwarderChain); WriteLn(''); |
Write(' Name = '); WriteLn(PChar(RVA2Offset(Name, Buffer) + Dword(Buffer))); |
Write(' FirstThunk = '); WriteHex(FirstThunk); WriteLn(''); |
End; |
Thunk := PDword(RVA2Offset(ImportDescriptor.FirstThunk, Buffer) + Dword(Buffer)); |
While Thunk^ <> 0 Do Begin |
Write(' '); WriteLn(PChar(RVA2Offset(Thunk^, Buffer) + Dword(Buffer) + SizeOf(Word))); |
Inc(Thunk); |
End; |
WriteLn(''); |
Inc(ImportDescriptor); |
End; |
End; |
End; |
|
If NumberOfRvaAndSizes > SPE_DIRECTORY_EXPORT Then Begin |
If DataDirectory[SPE_DIRECTORY_EXPORT].VirtualAddress <> 0 Then Begin |
WriteLn('Exports'); |
WriteLn('-------'); |
ExportDescriptor := PExportDescriptor(RVA2Offset(DataDirectory[SPE_DIRECTORY_EXPORT].VirtualAddress, Buffer) + Dword(Buffer)); |
With ExportDescriptor^ Do Begin |
Write(' Characteristics = '); WriteHex(Characteristics); WriteLn(''); |
Write(' TimeDateStamp = '); WriteHex(TimeDateStamp); WriteLn(''); |
Write(' MajorVersion = '); WriteHex(MajorVersion); WriteLn(''); |
Write(' MinorVersion = '); WriteHex(MinorVersion); WriteLn(''); |
Write(' Name = '); WriteLn(PChar(RVA2Offset(Name, Buffer) + Dword(Buffer))); |
Write(' Base = '); WriteHex(Base); WriteLn(''); |
Write(' NumberOfFunctions = '); WriteHex(NumberOfFunctions); WriteLn(''); |
Write(' NumberOfNames = '); WriteHex(NumberOfNames); WriteLn(''); |
Write(' AddressOfFunctions = '); WriteHex(AddressOfFunctions); WriteLn(''); |
Write(' AddressOfNames = '); WriteHex(AddressOfNames); WriteLn(''); |
Write(' AddressOfNameOrdinals = '); WriteHex(AddressOfNameOrdinals); WriteLn(''); |
For i := 0 To NumberOfNames - 1 Do Begin |
Write(' '); WriteLn(PChar(RVA2Offset(PDwordArray(RVA2Offset(AddressOfNames, Buffer) + Dword(Buffer))^[i], Buffer)) + Dword(Buffer)); |
End; |
End; |
End; |
End; |
|
End; |
End; |
End Else Begin |
WriteLn('File corrupted or invalid.') |
End; |
End Else Begin |
WriteLn('ReadFile Error.'); |
End; |
End; |
GetCh; |
ConsoleExit(TRUE); |
ThreadTerminate; |
End; |
(* -------------------------------------------------------- *) |
End. |