mirror of
https://github.com/vapaamies/KolibriOS.git
synced 2024-11-09 17:50:30 +01:00
Stripped PE Dumper tool added
This commit is contained in:
parent
3317a0088d
commit
36c2d5ee13
@ -10,6 +10,7 @@ unit KolibriOS;
|
||||
interface
|
||||
|
||||
{$I ImageFormats.inc}
|
||||
{$I StrippedPE.inc}
|
||||
|
||||
type
|
||||
TSize = packed record
|
||||
|
81
Lib/StrippedPE.inc
Normal file
81
Lib/StrippedPE.inc
Normal file
@ -0,0 +1,81 @@
|
||||
(*
|
||||
Stripped PE file format definition
|
||||
|
||||
Copyright (c) 2018 0CodErr
|
||||
Copyright (c) 2021 Delphi SDK for KolibriOS team
|
||||
*)
|
||||
|
||||
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
|
||||
PLongWordArray = ^TLongWordArray;
|
||||
TLongWordArray = array[0..0] of LongWord;
|
||||
|
||||
PStrippedImageFileHeader = ^TStrippedImageFileHeader;
|
||||
TStrippedImageFileHeader = packed record
|
||||
Signature: Word;
|
||||
Characteristics: Word;
|
||||
AddressOfEntryPoint: LongWord;
|
||||
ImageBase: LongWord;
|
||||
SectionAlignmentLog2: Byte;
|
||||
FileAlignmentLog2: Byte;
|
||||
MajorOSVersion: Byte;
|
||||
MinorOSVersion: Byte;
|
||||
SizeOfImage: LongWord;
|
||||
SizeOfStackReserve: LongWord;
|
||||
SizeOfHeapReserve: LongWord;
|
||||
SizeOfHeaders: LongWord;
|
||||
Subsystem: Byte;
|
||||
NumberOfRvaAndSizes: Byte;
|
||||
NumberOfSections: Word;
|
||||
end;
|
||||
|
||||
PStrippedImageSectionHeader = ^TStrippedImageSectionHeader;
|
||||
TStrippedImageSectionHeader = packed record
|
||||
Name: array[0..7] of KolibriChar;
|
||||
VirtualSize: LongWord;
|
||||
VirtualAddress: LongWord;
|
||||
SizeOfRawData: LongWord;
|
||||
PointerToRawData: LongWord;
|
||||
Characteristics: LongWord;
|
||||
end;
|
||||
|
||||
PImageDataDirectory = ^TImageDataDirectory;
|
||||
TImageDataDirectory = packed record
|
||||
VirtualAddress: LongWord;
|
||||
Size: LongWord;
|
||||
end;
|
||||
|
||||
PDataDirectoryArray = ^TDataDirectoryArray;
|
||||
TDataDirectoryArray = array[0..SPE_MAX_DIRECTORY_ENTRIES] of TImageDataDirectory;
|
||||
|
||||
PImportDescriptor = ^TImportDescriptor;
|
||||
TImportDescriptor = packed record
|
||||
OriginalFirstThunk: LongWord;
|
||||
TimeDateStamp: LongWord;
|
||||
ForwarderChain: LongWord;
|
||||
Name: LongWord;
|
||||
FirstThunk: LongWord;
|
||||
end;
|
||||
|
||||
PExportDescriptor = ^TExportDescriptor;
|
||||
TExportDescriptor = packed record
|
||||
Characteristics: LongWord;
|
||||
TimeDateStamp: LongWord;
|
||||
MajorVersion: Word;
|
||||
MinorVersion: Word;
|
||||
Name: LongWord;
|
||||
Base: LongWord;
|
||||
NumberOfFunctions: LongWord;
|
||||
NumberOfNames: LongWord;
|
||||
AddressOfFunctions: LongWord;
|
||||
AddressOfNames: LongWord;
|
||||
AddressOfNameOrdinals: LongWord;
|
||||
end;
|
7
Tools/.dof
Normal file
7
Tools/.dof
Normal file
@ -0,0 +1,7 @@
|
||||
[Directories]
|
||||
OutputDir=..\..\Bin\KoW
|
||||
UnitOutputDir=..\..\Bin\KoW\DCU
|
||||
SearchPath=..\..\Lib;..\..\Bin\KoW\DCU
|
||||
Conditionals=Debug
|
||||
UnitAliases=
|
||||
UsePackages=0
|
216
Tools/SPEDump/SPEDump.dpr
Normal file
216
Tools/SPEDump/SPEDump.dpr
Normal file
@ -0,0 +1,216 @@
|
||||
(*
|
||||
Stripped PE File Dumper
|
||||
|
||||
Copyright (c) 2018 0CodErr
|
||||
Copyright (c) 2021 Delphi SDK for KolibriOS team
|
||||
*)
|
||||
|
||||
program SPEDump;
|
||||
|
||||
{$IFNDEF KolibriOS}
|
||||
{$APPTYPE Console}
|
||||
{$ENDIF}
|
||||
|
||||
uses
|
||||
KolibriOS, CRT;
|
||||
|
||||
var
|
||||
FileName: PKolibriChar;
|
||||
I, BytesRead: LongWord;
|
||||
Buffer: PStrippedImageFileHeader;
|
||||
Section: PStrippedImageSectionHeader;
|
||||
DataDir: PDataDirectoryArray;
|
||||
Imp: PImportDescriptor;
|
||||
Exp: PExportDescriptor;
|
||||
Thunk: PLongWord;
|
||||
|
||||
procedure WriteLn(Str: PKolibriChar = nil);
|
||||
begin
|
||||
con_write_asciiz(Str);
|
||||
con_write_asciiz(#10);
|
||||
end;
|
||||
|
||||
function FileIsValid: Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
with Buffer^ do
|
||||
begin
|
||||
if BytesRead < SizeOf(TStrippedImageFileHeader) then
|
||||
Exit;
|
||||
if Signature <> STRIPPED_PE_SIGNATURE then
|
||||
Exit;
|
||||
end;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function RVA2Offset(RVA: LongWord; Header: PStrippedImageFileHeader): LongWord;
|
||||
var
|
||||
I: LongWord;
|
||||
SectionHeader: PStrippedImageSectionHeader;
|
||||
begin
|
||||
with Header^ do
|
||||
begin
|
||||
SectionHeader := PStrippedImageSectionHeader(PKolibriChar(Header) + SizeOf(TStrippedImageFileHeader) + NumberOfRvaAndSizes * SizeOf(TImageDataDirectory));
|
||||
for I := 0 to NumberOfSections do
|
||||
begin
|
||||
with SectionHeader^ do
|
||||
begin
|
||||
if (RVA >= VirtualAddress) And (RVA < VirtualAddress + SizeOfRawData) then
|
||||
begin
|
||||
Result := PointerToRawData + RVA - VirtualAddress;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
Inc(SectionHeader);
|
||||
end;
|
||||
end;
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function StrNLen(Src: PKolibriChar; MaxLen: LongWord): LongWord;
|
||||
begin
|
||||
Result := 0;
|
||||
while (Src^ <> #0) and (Result <> MaxLen) do
|
||||
begin
|
||||
Inc(Src);
|
||||
Inc(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
{$IF defined(KolibriOS) or defined(Debug)}
|
||||
InitConsole('Stripped PE File Dumper', False, LongWord(-1), 30);
|
||||
{$IFEND}
|
||||
|
||||
{$IFDEF KolibriOS}
|
||||
FileName := nil;
|
||||
{$ELSE}
|
||||
FileName := 'EHCI.SYS';
|
||||
{$ENDIF}
|
||||
|
||||
WriteLn('Stripped PE File Dumper version 0.2.1');
|
||||
WriteLn('Copyright (c) 2018 0CodErr');
|
||||
WriteLn('Copyright (c) 2021 Delphi SDK for KolibriOS team');
|
||||
|
||||
if (FileName = nil) or (FileName^ = #0) then
|
||||
begin
|
||||
WriteLn('Usage: SPEDump [<file>]');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
WriteLn;
|
||||
con_printf('Dump of "%s"'#10#10, FileName);
|
||||
|
||||
Buffer := LoadFile(FileName, BytesRead);
|
||||
if Buffer = nil then
|
||||
begin
|
||||
WriteLn('ReadFile Error');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if not FileIsValid then
|
||||
begin
|
||||
WriteLn('File corrupted or invalid');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
WriteLn('File Header');
|
||||
WriteLn('-----------');
|
||||
|
||||
with Buffer^ do
|
||||
begin
|
||||
con_printf(' Signature = %04Xh'#10, Signature);
|
||||
con_printf(' Characteristics = %04Xh'#10, Characteristics);
|
||||
con_printf(' AddressOfEntryPoint = %08Xh'#10, AddressOfEntryPoint);
|
||||
con_printf(' ImageBase = %08Xh'#10, ImageBase);
|
||||
con_printf(' SectionAlignmentLog2 = %u (%08Xh)'#10, SectionAlignmentLog2, 1 shl SectionAlignmentLog2);
|
||||
con_printf(' FileAlignmentLog2 = %u (%08Xh)'#10, FileAlignmentLog2, 1 shl FileAlignmentLog2);
|
||||
con_printf(' MajorOSVersion = %u'#10, MajorOSVersion);
|
||||
con_printf(' MinorOSVersion = %u'#10, MinorOSVersion);
|
||||
con_printf(' SizeOfImage = %08Xh'#10, SizeOfImage);
|
||||
con_printf(' SizeOfStackReserve = %08Xh'#10, SizeOfStackReserve);
|
||||
con_printf(' SizeOfHeapReserve = %08Xh'#10, SizeOfHeapReserve);
|
||||
con_printf(' SizeOfHeaders = %08Xh'#10, SizeOfHeaders);
|
||||
con_printf(' Subsystem = %02Xh'#10, Subsystem);
|
||||
con_printf(' NumberOfRvaAndSizes = %u'#10, NumberOfRvaAndSizes);
|
||||
con_printf(' NumberOfSections = %u'#10, NumberOfSections);
|
||||
|
||||
WriteLn;
|
||||
|
||||
if NumberOfSections > 0 then
|
||||
begin
|
||||
I := 1;
|
||||
Section := PStrippedImageSectionHeader(PKolibriChar(Buffer) + SizeOf(TStrippedImageFileHeader) +
|
||||
NumberOfRvaAndSizes * SizeOf(TImageDataDirectory));
|
||||
repeat
|
||||
con_printf('Section #%u'#10, I);
|
||||
WriteLn('-----------');
|
||||
with Section^ do
|
||||
begin
|
||||
con_write_asciiz(
|
||||
' Name = '); con_write_string(Name, StrNLen(Name, 8));
|
||||
WriteLn;
|
||||
con_printf(' VirtualSize = %08Xh'#10, VirtualSize);
|
||||
con_printf(' VirtualAddress = %08Xh'#10, VirtualAddress);
|
||||
con_printf(' SizeOfRawData = %08Xh'#10, SizeOfRawData);
|
||||
con_printf(' PointerToRawData = %08Xh'#10, PointerToRawData);
|
||||
con_printf(' Flags = %08Xh'#10#10, Characteristics);
|
||||
end;
|
||||
Inc(Section);
|
||||
Inc(I);
|
||||
until I > NumberOfSections;
|
||||
|
||||
DataDir := PDataDirectoryArray(PKolibriChar(Buffer) + SizeOf(TStrippedImageFileHeader));
|
||||
|
||||
if (NumberOfRvaAndSizes > SPE_DIRECTORY_IMPORT) and (DataDir[SPE_DIRECTORY_IMPORT].VirtualAddress <> 0) then
|
||||
begin
|
||||
WriteLn('Imports');
|
||||
WriteLn('-------');
|
||||
Imp := PImportDescriptor(PKolibriChar(Buffer) + RVA2Offset(DataDir[SPE_DIRECTORY_IMPORT].VirtualAddress, Buffer));
|
||||
while Imp.Name <> 0 do
|
||||
begin
|
||||
with Imp^ do
|
||||
begin
|
||||
con_printf(' OriginalFirstThunk = %08Xh'#10, OriginalFirstThunk);
|
||||
con_printf(' TimeDateStamp = %08Xh'#10, TimeDateStamp);
|
||||
con_printf(' ForwarderChain = %08Xh'#10, ForwarderChain);
|
||||
con_printf(' Name = %s'#10, PKolibriChar(Buffer) + RVA2Offset(Name, Buffer));
|
||||
con_printf(' FirstThunk = %08Xh'#10, FirstThunk);
|
||||
end;
|
||||
Thunk := PLongWord(PKolibriChar(Buffer) + RVA2Offset(Imp.FirstThunk, Buffer));
|
||||
while Thunk^ <> 0 do
|
||||
begin
|
||||
con_printf(' %s'#10, PKolibriChar(Buffer) + RVA2Offset(Thunk^, Buffer) + SizeOf(Word));
|
||||
Inc(Thunk);
|
||||
end;
|
||||
WriteLn;
|
||||
Inc(Imp);
|
||||
end;
|
||||
end;
|
||||
|
||||
if (NumberOfRvaAndSizes > SPE_DIRECTORY_EXPORT) and (DataDir[SPE_DIRECTORY_EXPORT].VirtualAddress <> 0) then
|
||||
begin
|
||||
WriteLn('Exports');
|
||||
WriteLn('-------');
|
||||
Exp := PExportDescriptor(RVA2Offset(DataDir[SPE_DIRECTORY_EXPORT].VirtualAddress, Buffer) + LongWord(Buffer));
|
||||
with Exp^ do
|
||||
begin
|
||||
con_printf(' Characteristics = %08Xh'#10, Characteristics);
|
||||
con_printf(' TimeDateStamp = %08Xh'#10, TimeDateStamp);
|
||||
con_printf(' MajorVersion = %u'#10, MajorVersion);
|
||||
con_printf(' MinorVersion = %u'#10, MinorVersion);
|
||||
con_printf(' Name = %s'#10, PKolibriChar(Buffer) + RVA2Offset(Name, Buffer));
|
||||
con_printf(' Base = %08Xh'#10, Base);
|
||||
con_printf(' NumberOfFunctions = %u'#10, NumberOfFunctions);
|
||||
con_printf(' NumberOfNames = %u'#10, NumberOfNames);
|
||||
con_printf(' AddressOfFunctions = %08Xh'#10, AddressOfFunctions);
|
||||
con_printf(' AddressOfNames = %08Xh'#10, AddressOfNames);
|
||||
con_printf(' AddressOfNameOrdinals = %08Xh'#10, AddressOfNameOrdinals);
|
||||
for I := 0 to NumberOfNames - 1 do
|
||||
con_printf(' %s'#10, PKolibriChar(Buffer) +
|
||||
RVA2Offset(PLongWordArray(PKolibriChar(Buffer) + RVA2Offset(AddressOfNames, Buffer))[I], Buffer));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end.
|
1
Tools/SPEDump/build.bat
Normal file
1
Tools/SPEDump/build.bat
Normal file
@ -0,0 +1 @@
|
||||
@call "%~dp0..\build.bat" "%~dp0SPEDump"
|
@ -1,3 +1,11 @@
|
||||
@echo off
|
||||
|
||||
call "%~dp0build-examples.bat"
|
||||
if errorlevel 1 goto exit
|
||||
|
||||
call "%~dp0build-my.bat"
|
||||
if errorlevel 1 goto exit
|
||||
|
||||
call "%~dp0build-tools.bat"
|
||||
|
||||
:exit
|
8
build-tools.bat
Normal file
8
build-tools.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@echo off
|
||||
|
||||
for /d %%f in ("%~dp0Tools\*") do (
|
||||
if exist "%%f\build.bat" call "%%f\build.bat"
|
||||
if errorlevel 1 goto exit
|
||||
)
|
||||
|
||||
:exit
|
@ -18,6 +18,9 @@ if #%1#==## (
|
||||
if errorlevel 1 goto exit
|
||||
|
||||
call %0 My My
|
||||
if errorlevel 1 goto exit
|
||||
|
||||
call %0 Tools Tools
|
||||
goto exit
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user