Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. (************************************************************
  2.  
  3.             Simple Stripped PE Binary File Dumper
  4.  
  5.  ************************************************************)
  6. Unit SPEDump;
  7. (* -------------------------------------------------------- *)
  8. Interface
  9. (* -------------------------------------------------------- *)
  10. Uses KolibriOS;
  11. (* -------------------------------------------------------- *)
  12. Type
  13.   Dword = LongWord;
  14.  
  15.   PDword = ^Dword;
  16.  
  17.   TDwordArray = Packed Array[0..0] Of Dword;
  18.  
  19.   PDwordArray = ^TDwordArray;
  20.  
  21. Const
  22.   STRIPPED_PE_SIGNATURE   = $4503; // 'PE' Xor 'S'
  23.   SPE_DIRECTORY_IMPORT    = 0;
  24.   SPE_DIRECTORY_EXPORT    = 1;
  25.   SPE_DIRECTORY_BASERELOC = 2;
  26.  
  27.   SPE_MAX_DIRECTORY_ENTRIES = SPE_DIRECTORY_BASERELOC;
  28.  
  29. Type
  30.   TStrippedPEHeader = Packed Record
  31.     Signature:           Word;
  32.     Characteristics:     Word;
  33.     AddressOfEntryPoint: Dword;
  34.     ImageBase:           Dword;
  35.     SectionAlignmentLog: Byte;
  36.     FileAlignmentLog:    Byte;
  37.     MajorOSVersion:      Byte;
  38.     MinorOSVersion:      Byte;
  39.     SizeOfImage:         Dword;
  40.     SizeOfStackReserve:  Dword;
  41.     SizeOfHeapReserve:   Dword;
  42.     SizeOfHeaders:       Dword;
  43.     Subsystem:           Byte;
  44.     NumberOfRvaAndSizes: Byte;
  45.     NumberOfSections:    Word;
  46.   End;
  47.  
  48.   PStrippedPEHeader = ^TStrippedPEHeader;
  49.  
  50.   TStrippedSectionHeader = Packed Record
  51.     Name: Packed Array[0..7] Of Char;
  52.     VirtualSize:          Dword;
  53.     VirtualAddress:       Dword;
  54.     SizeOfRawData:        Dword;
  55.     PointerToRawData:     Dword;
  56.     Characteristics:      Dword;
  57.   End;
  58.  
  59.   PStrippedSectionHeader = ^TStrippedSectionHeader;
  60.  
  61.   TDataDirectory = Packed Record
  62.     VirtualAddress: Dword;
  63.     Size:           Dword;
  64.   End;
  65.  
  66.   PDataDirectory = ^TDataDirectory;
  67.  
  68.   TDataDirectoryArray = Packed Array[0..SPE_MAX_DIRECTORY_ENTRIES] Of TDataDirectory;
  69.  
  70.   PDataDirectoryArray = ^TDataDirectoryArray;
  71.  
  72.   TImportDescriptor = Packed Record
  73.     OriginalFirstThunk: Dword;
  74.     TimeDateStamp:      Dword;
  75.     ForwarderChain:     Dword;
  76.     Name:               Dword;
  77.     FirstThunk:         Dword;
  78.   End;
  79.  
  80.   PImportDescriptor = ^TImportDescriptor;
  81.  
  82.   TExportDescriptor = Packed Record
  83.     Characteristics:       Dword;
  84.     TimeDateStamp:         Dword;
  85.     MajorVersion:          Word;
  86.     MinorVersion:          Word;
  87.     Name:                  Dword;
  88.     Base:                  Dword;
  89.     NumberOfFunctions:     Dword;
  90.     NumberOfNames:         Dword;
  91.     AddressOfFunctions:    Dword;
  92.     AddressOfNames:        Dword;
  93.     AddressOfNameOrdinals: Dword;
  94.   End;
  95.  
  96.   PExportDescriptor = ^TExportDescriptor;
  97.  
  98. Var
  99.   FileName:         PChar;
  100.   FileHandle:       Integer;
  101.   FileLength:       Dword;
  102.   BytesRead:        Dword;
  103.   Buffer:           PStrippedPEHeader;
  104.   Section:          PStrippedSectionHeader;
  105.   DataDirectory:    PDataDirectoryArray;
  106.   ImportDescriptor: PImportDescriptor;
  107.   ExportDescriptor: PExportDescriptor;
  108.   Thunk:            PDword;
  109.  
  110. (* --------------------- Console stuff -------------------- *)
  111.   hConsole:         Pointer;
  112.   ConsoleInit:      Procedure(WndWidth, WndHeight, ScrWidth, ScrHeight: Dword; Caption: PChar); StdCall;
  113.   ConsoleExit:      Procedure(bCloseWindow: Boolean); StdCall;
  114.   Printf:           Function(Const Format: PChar): Integer; CDecl VarArgs;
  115.   GetCh:            Function: Integer; StdCall;
  116.   WriteN:           Procedure(Const Str: PChar; Count: Dword); StdCall;
  117.   Write:            Procedure(Const Str: PChar); StdCall;
  118.  
  119. (* -------------------------------------------------------- *)
  120. Procedure Main;
  121. Function  FileIsValid: Boolean;
  122. Procedure WriteHex(Number: Dword);
  123. Procedure WriteLn(Text: PChar);
  124. (* -------------------------------------------------------- *)
  125. Implementation
  126. (* -------------------------------------------------------- *)
  127. Function FileIsValid : Boolean;
  128. Begin
  129.   FileIsValid := FALSE;
  130.   With Buffer^ Do Begin
  131.     If BytesRead < SizeOf(TStrippedPEHeader) Then Exit;
  132.     If Signature <> STRIPPED_PE_SIGNATURE Then Exit;
  133.   End;
  134.   FileIsValid := TRUE;
  135. End;
  136. (* -------------------------------------------------------- *)
  137. Function RVA2Offset(RVA: Dword; StrippedPEHeader: PStrippedPEHeader): Dword;
  138. Var
  139.   i: Dword;
  140.   StrippedSectionHeader: PStrippedSectionHeader;
  141. Begin
  142.   With StrippedPEHeader^ Do Begin
  143.     StrippedSectionHeader := PStrippedSectionHeader(Dword(StrippedPEHeader) + SizeOf(TStrippedPEHeader) + NumberOfRvaAndSizes * SizeOf(TDataDirectory));
  144.     For i := 0 To NumberOfSections Do Begin
  145.       With StrippedSectionHeader^ Do Begin
  146.         If (RVA >= VirtualAddress) And (RVA < VirtualAddress + SizeOfRawData) Then Begin
  147.           Result := PointerToRawData + RVA - VirtualAddress;
  148.           Exit;
  149.         End;
  150.       End;
  151.       Inc(StrippedSectionHeader);
  152.     End;
  153.   End;
  154.   Result := 0;
  155. End;
  156. (* -------------------------------------------------------- *)
  157. Procedure WriteHex(Number: Dword); Begin Printf('%X', Number); End;
  158. (* -------------------------------------------------------- *)
  159. Procedure WriteLn(Text: PChar); Begin Printf('%s'#10, Text); End;
  160. (* -------------------------------------------------------- *)
  161. Procedure Main;
  162. Const
  163.   CmdLine = PPChar(28);
  164. Var
  165.   i: Dword;
  166. Begin
  167.   hConsole    := LoadLibrary('/sys/lib/console.obj');
  168.   ConsoleInit := GetProcAddress(hConsole, 'con_init');
  169.   ConsoleExit := GetProcAddress(hConsole, 'con_exit');
  170.   Printf      := GetProcAddress(hConsole, 'con_printf');
  171.   GetCh       := GetProcAddress(hConsole, 'con_getch');
  172.   WriteN      := GetProcAddress(hConsole, 'con_write_string');
  173.   Write       := GetProcAddress(hConsole, 'con_write_asciiz');
  174.   ConsoleInit($FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, 'SPEDump');
  175.  
  176.   (*             skip spaces             *)
  177.   i := 0; While CmdLine^[i] = ' ' Do Inc(i);
  178.   FileName := @CmdLine^[i];
  179.  
  180.   WriteLn('Simple Stripped PE Binary File Dumper Version 0.1; 2018.');
  181.   If FileName[0] = #0 Then Begin
  182.     WriteLn('Usage: SPEDump [<file>]')
  183.   End Else Begin
  184.     WriteLn(''); Write('Dump of "'); Write(FileName); WriteLn('"'); WriteLn('');    
  185.     Buffer := PStrippedPEHeader(LoadFile(FileName, BytesRead));
  186.     If Buffer <> Nil Then Begin        
  187.    
  188.       If FileIsValid Then Begin
  189.         WriteLn('File header');
  190.         WriteLn('-----------');
  191.  
  192.         With Buffer^ Do Begin
  193.           Write('  Signature             = '); WriteHex(Signature);           WriteLn('');
  194.           Write('  Characteristics       = '); WriteHex(Characteristics);     WriteLn('');
  195.           Write('  AddressOfEntryPoint   = '); WriteHex(AddressOfEntryPoint); WriteLn('');
  196.           Write('  ImageBase             = '); WriteHex(ImageBase);           WriteLn('');
  197.           Write('  SectionAlignmentLog   = '); WriteHex(SectionAlignmentLog); WriteLn('');
  198.           Write('  FileAlignmentLog      = '); WriteHex(FileAlignmentLog);    WriteLn('');
  199.           Write('  MajorOSVersion        = '); WriteHex(MajorOSVersion);      WriteLn('');
  200.           Write('  MinorOSVersion        = '); WriteHex(MinorOSVersion);      WriteLn('');
  201.           Write('  SizeOfImage           = '); WriteHex(SizeOfImage);         WriteLn('');
  202.           Write('  SizeOfStackReserve    = '); WriteHex(SizeOfStackReserve);  WriteLn('');
  203.           Write('  SizeOfHeapReserve     = '); WriteHex(SizeOfHeapReserve);   WriteLn('');
  204.           Write('  SizeOfHeaders         = '); WriteHex(SizeOfHeaders);       WriteLn('');
  205.           Write('  Subsystem             = '); WriteHex(Subsystem);           WriteLn('');
  206.           Write('  NumberOfRvaAndSizes   = '); WriteHex(NumberOfRvaAndSizes); WriteLn('');
  207.           Write('  NumberOfSections      = '); WriteHex(NumberOfSections);    WriteLn('');
  208.  
  209.           WriteLn('');
  210.  
  211.           If NumberOfSections > 0 Then Begin
  212.             i := 1;
  213.             Section := PStrippedSectionHeader(Dword(Buffer) + SizeOf(TStrippedPEHeader) + NumberOfRvaAndSizes * SizeOf(TDataDirectory));
  214.             Repeat
  215.               Write('Section #'); WriteHex(i); WriteLn('');
  216.               WriteLn('-----------');
  217.               With Section^ Do Begin                          
  218.                 Write('  Name                  = ');
  219.                 (* Handle situation when Name length = 8 Then Name is NOT ASCIIZ *)
  220.                 If Name[High(Name)] <> #0 Then WriteN(Name, 8) Else Write(Name);                                  
  221.                 WriteLn('');                
  222.                 Write('  VirtualSize           = '); WriteHex(VirtualSize);      WriteLn('');
  223.                 Write('  VirtualAddress        = '); WriteHex(VirtualAddress);   WriteLn('');
  224.                 Write('  SizeOfRawData         = '); WriteHex(SizeOfRawData);    WriteLn('');
  225.                 Write('  PointerToRawData      = '); WriteHex(PointerToRawData); WriteLn('');
  226.                 Write('  Flags                 = '); WriteHex(Characteristics);  WriteLn('');
  227.               End;
  228.               WriteLn('');
  229.               inc(Section);
  230.               inc(i);
  231.             Until i > NumberOfSections;
  232.  
  233.             DataDirectory := PDataDirectoryArray(Dword(Buffer) + SizeOf(TStrippedPEHeader));
  234.  
  235.             If NumberOfRvaAndSizes > SPE_DIRECTORY_IMPORT Then Begin
  236.               If DataDirectory[SPE_DIRECTORY_IMPORT].VirtualAddress <> 0 Then Begin
  237.                 WriteLn('Imports');
  238.                 WriteLn('-------');
  239.                 ImportDescriptor := PImportDescriptor(RVA2Offset(DataDirectory[SPE_DIRECTORY_IMPORT].VirtualAddress, Buffer) + Dword(Buffer));
  240.                 While ImportDescriptor.Name <> 0 Do Begin
  241.                   With ImportDescriptor^ Do Begin
  242.                     Write('  OriginalFirstThunk    = '); WriteHex(OriginalFirstThunk); WriteLn('');
  243.                     Write('  TimeDateStamp         = '); WriteHex(TimeDateStamp);      WriteLn('');
  244.                     Write('  ForwarderChain        = '); WriteHex(ForwarderChain);     WriteLn('');
  245.                     Write('  Name                  = '); WriteLn(PChar(RVA2Offset(Name, Buffer) + Dword(Buffer)));
  246.                     Write('  FirstThunk            = '); WriteHex(FirstThunk);         WriteLn('');
  247.                   End;
  248.                   Thunk := PDword(RVA2Offset(ImportDescriptor.FirstThunk, Buffer) + Dword(Buffer));
  249.                   While Thunk^ <> 0 Do Begin
  250.                     Write('    '); WriteLn(PChar(RVA2Offset(Thunk^, Buffer) + Dword(Buffer) + SizeOf(Word)));
  251.                     Inc(Thunk);
  252.                   End;
  253.                   WriteLn('');
  254.                   Inc(ImportDescriptor);
  255.                 End;
  256.               End;
  257.             End;
  258.  
  259.             If NumberOfRvaAndSizes > SPE_DIRECTORY_EXPORT Then Begin
  260.               If DataDirectory[SPE_DIRECTORY_EXPORT].VirtualAddress <> 0 Then Begin
  261.                 WriteLn('Exports');
  262.                 WriteLn('-------');
  263.                 ExportDescriptor := PExportDescriptor(RVA2Offset(DataDirectory[SPE_DIRECTORY_EXPORT].VirtualAddress, Buffer) + Dword(Buffer));
  264.                 With ExportDescriptor^ Do Begin
  265.                   Write('  Characteristics       = '); WriteHex(Characteristics);       WriteLn('');
  266.                   Write('  TimeDateStamp         = '); WriteHex(TimeDateStamp);         WriteLn('');
  267.                   Write('  MajorVersion          = '); WriteHex(MajorVersion);          WriteLn('');
  268.                   Write('  MinorVersion          = '); WriteHex(MinorVersion);          WriteLn('');
  269.                   Write('  Name                  = '); WriteLn(PChar(RVA2Offset(Name, Buffer) + Dword(Buffer)));
  270.                   Write('  Base                  = '); WriteHex(Base);                  WriteLn('');
  271.                   Write('  NumberOfFunctions     = '); WriteHex(NumberOfFunctions);     WriteLn('');
  272.                   Write('  NumberOfNames         = '); WriteHex(NumberOfNames);         WriteLn('');
  273.                   Write('  AddressOfFunctions    = '); WriteHex(AddressOfFunctions);    WriteLn('');
  274.                   Write('  AddressOfNames        = '); WriteHex(AddressOfNames);        WriteLn('');
  275.                   Write('  AddressOfNameOrdinals = '); WriteHex(AddressOfNameOrdinals); WriteLn('');
  276.                   For i := 0 To NumberOfNames - 1 Do Begin
  277.                     Write('    '); WriteLn(PChar(RVA2Offset(PDwordArray(RVA2Offset(AddressOfNames, Buffer) + Dword(Buffer))^[i], Buffer)) + Dword(Buffer));
  278.                   End;
  279.                 End;
  280.               End;
  281.             End;
  282.  
  283.           End;
  284.         End;
  285.       End Else Begin
  286.         WriteLn('File corrupted or invalid.')
  287.       End;
  288.     End Else Begin
  289.       WriteLn('ReadFile Error.');
  290.     End;
  291.   End;
  292.   GetCh;
  293.   ConsoleExit(TRUE);
  294.   ThreadTerminate;
  295. End;
  296. (* -------------------------------------------------------- *)
  297. End.