TChag-Pe‎ > ‎

Unit1.pas

{
------------------- Tchag-Pe ---------------------------------------------------

version 1.1
updated : 04/16/2003

Tchag-Pe is a tool that extracts the internal structure of PE
(Portable Executable win32) files.

Features:

Extract Full information of PE file(*.exe *.dll *.ocx *.cpl *.bpl *.scr ...)
Review of all :
            - the sections and their contents.
            - the exported and imported functions.
            - the recources and their locations and sizes
Giving you the real Offset of each item in the file (Rva To Offset)

By : Chagdali Ismail

http://chagdali.free.fr

------------------------------------------------------------------------------
}



unit Unit1;

interface

uses
  Windows,SysUtils, Classes, Graphics, Controls, Forms,
  StdCtrls,ComCtrls,Messages, Menus, ExtCtrls, Dialogs;



type
 
  TF_Main = class(TForm)
    Op: TOpenDialog;
    ScrollBox1: TScrollBox;
    Panel1: TPanel;
    MM: TMainMenu;
    File1: TMenuItem;
    OpenFile1: TMenuItem;
    Edit3: TMenuItem;
    N1: TMenuItem;
    Tab2: TTabControl;
    m: TRichEdit;
    St: TStatusBar;
    Sav: TMenuItem;
    Exit1: TMenuItem;
    About1: TMenuItem;
    Copy1: TMenuItem;
    selectAll1: TMenuItem;
    N4: TMenuItem;
    sv: TSaveDialog;
    procedure go_load;
    procedure go_header;
    procedure go_sections;
    procedure Go_Resour;
    procedure go_export;
    procedure go_import;
    procedure open_Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure SavClick(Sender: TObject);
    procedure Exit1Click(Sender: TObject);
    procedure About1Click(Sender: TObject);
    procedure Copy1Click(Sender: TObject);
    procedure selectAll1Click(Sender: TObject);
  end;

var
     F_Main       : TF_Main;
     ns,nr,nc,nx  : word;
     pe_file,s    : string;
     fh,fm        : thandle;
     Fp           : Pointer;
     oo           : TstringList;
implementation

uses Pe_Ref,func,Unit2;

{$R *.DFM}

//------------------------------------------------------------------------------
//----------------------------------open_file-----------------------------------

procedure TF_Main.open_Click(Sender: TObject);
begin
if not op.Execute then exit else
begin
  pe_file:=op.FileName;
  go_load;
end;
end;
//--------------------------------go_load---------------------------------------

procedure TF_Main.go_load;
begin
try
  m.Lines.Clear;
  Fh:=CreateFile(PChar(pe_file), GENERIC_READ, FILE_SHARE_READ,nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  fm:=CreateFileMapping(fh, nil, PAGE_READONLY, 0, 0, nil);
  fp:=MapViewOfFile(fm, FILE_MAP_READ, 0, 0, 0);
  P_Dos:=P_DOS_HEADER(Fp);
  P_nt:=P_NT_HEADER(Cardinal(P_Dos)+P_Dos.e_lfanew);
  if (P_nt.Signature = $00004550)and (not IsBadReadPtr(P_nt, sizeof(P_NT_HEADER)))then
  begin
  st.SimpleText:=' Loading ... ';
  Application.ProcessMessages;
  oo:=TStringList.Create;
  oo.Add('');
  oo.Add('                           TChag-Pe   Version 1.1');
  oo.Add('');
  oo.Add('');
  oo.Add(' File : '+ExtractFileName(pe_file));
  oo.Add('');
  oo.Add('*=========================================================================*');
  oo.Add(' PE-Header At:                '+inttohex(p_dos.e_lfanew,8));
  oo.Add('');
  oo.Add('');
  oo.Add('');
  go_header;
  go_sections;
  go_export;
  go_import;
  Go_Resour;
  oo.Add('');
  m.Lines:=oo;
  m.SelStart:=0;
  oo.Free;
  UnmapViewOfFile(Fp);
  CloseHandle(Fm);
  CloseHandle(Fh);
  st.SimpleText:=' File : '+pe_file;
  end
  else
  begin
  UnmapViewOfFile(Fp);
  CloseHandle(Fm);
  CloseHandle(Fh);
  m.SelAttributes.Color:=cllime;
  m.Lines.Add('');
  m.Lines.Add(extractfilename(pe_file)+' : is Not a Win32 File (Not a PE file ...)');
  m.SelAttributes.Color:=$00F5DCD8;
  end;
except
oo.Free;
m.Lines.Add('File : '+pe_file);
m.Lines.Add('');
m.SelAttributes.Color:=clred;
m.Lines.Add('');
m.Lines.Add(' Error !');
m.SelAttributes.Color:=$00F5DCD8;
m.Lines.Add('');
m.Lines.Add(' Case error of');
m.Lines.Add('');
m.Lines.Add('   0:Unkown File Format   := File is not (PE).');
m.Lines.Add('   1:Unkown Exception     := File May Be Packed.');
m.Lines.Add('   2:Bug While Extracting := Contact Author. At : Chagdali@free.fr.');
m.Lines.Add('');
m.Lines.Add(' End;');
m.Lines.Add('');
st.SimpleText:=' Error ! ';
end;
end;

//------------------------header----Directories---------------------------------

procedure TF_Main.Go_header;
var
i:byte;
begin
oo.add('*=========================================================================*');
oo.add(' File Header');
oo.add('*=========================================================================*');
oo.add('Signature           '+#9+#9+inttohex(P_nt.Signature,8));
oo.add('Machine             '+#9+#9+inttohex(P_nt.F_Header.Machine,4));
oo.add('NumberOfSections    '+#9+#9+inttohex(P_nt.F_Header.NumberOfSections,4));
oo.add('TimeDateStamp       '+#9+#9+inttohex(P_nt.F_Header.TimeDateStamp,8));
oo.add('PointerToSymbolTable'+#9+#9+inttohex(P_nt.F_Header.PointerToSymbolTable,8));
oo.add('NumberOfSymbols     '+#9+#9+inttohex(P_nt.F_Header.NumberOfSymbols,8));
oo.add('SizeOfOptionalHeader'+#9+#9+inttohex(P_nt.F_Header.SizeOfOptionalHeader,4));
oo.add('Characteristics     '+#9+#9+inttohex(P_nt.F_Header.Characteristics,4));
oo.add('');
oo.Add('');
oo.add('*=========================================================================*');
oo.add(' Optional Header');
oo.add('*=========================================================================*');
oo.add('Magic                   '+#9+inttohex(P_nt.Op_Header.Magic,4));
oo.add('Linker Version          '+#9+inttostr(P_nt.Op_Header.MajorLinkerVersion)+'.'
                                +inttostr(P_nt.Op_Header.MinorLinkerVersion));
oo.add('Size Of Code            '+#9+inttohex(P_nt.Op_Header.SizeOfCode,8));
oo.add('SizeOfInitializedData   '+#9+inttohex(P_nt.Op_Header.SizeOfInitializedData,8));
oo.add('SizeOfUninitializedData '+#9+inttohex(P_nt.Op_Header.SizeOfUninitializedData,8));
oo.add('AddressOfEntryPoint     '+#9+inttohex(P_nt.Op_Header.AddressOfEntryPoint,8));
oo.add('Base Of Code            '+#9+inttohex(P_nt.Op_Header.BaseOfCode,8));
oo.add('Base Of Data            '+#9+inttohex(P_nt.Op_Header.BaseOfData,8));
oo.add('Image Base              '+#9+inttohex(P_nt.Op_Header.ImageBase,8));
oo.add('Section Alignmen        '+#9+inttohex(P_nt.Op_Header.SectionAlignment,8));
oo.add('File Alignment          '+#9+inttohex(P_nt.Op_Header.FileAlignment,8));
oo.add('Os Version              '+#9+inttostr(P_nt.Op_Header.MajorOperatingSystemVersion)+'.'
                                +inttostr(P_nt.Op_Header.MinorOperatingSystemVersion));
oo.add('Image Version           '+#9+inttostr(P_nt.Op_Header.MajorImageVersion)+'.'
                                 +inttostr(P_nt.Op_Header.MinorImageVersion));
oo.add('Subsystem Version       '+#9+inttostr(P_nt.Op_Header.MajorSubsystemVersion)+'.'
                                 +inttostr(P_nt.Op_Header.MinorSubsystemVersion));
oo.add('Reserved                '+#9+inttohex(P_nt.Op_Header.Reserved,8));
oo.add('Size Of Image           '+#9+inttohex(P_nt.Op_Header.SizeOfImage,8));
oo.add('Size Of Headers         '+#9+inttohex(P_nt.Op_Header.SizeOfHeaders,8));
oo.add('CheckSum                '+#9+inttohex(P_nt.Op_Header.CheckSum,8));
oo.add('Subsystem               '+#9+inttohex(P_nt.Op_Header.Subsystem,4));
oo.add('DllCharacteristics      '+#9+inttohex(P_nt.Op_Header.DllCharacteristics,4));
oo.add('SizeOfStackReserve      '+#9+inttohex(P_nt.Op_Header.SizeOfStackReserve,8));
oo.add('SizeOfStackCommit       '+#9+inttohex(P_nt.Op_Header.SizeOfStackCommit,8));
oo.add('SizeOfHeapReserve       '+#9+inttohex(P_nt.Op_Header.SizeOfHeapReserve,8));
oo.add('SizeOfHeapCommit        '+#9+inttohex(P_nt.Op_Header.SizeOfHeapCommit,8));
oo.add('LoaderFlags             '+#9+inttohex(P_nt.Op_Header.LoaderFlags,8));
oo.add('Number of directories   '+#9+inttohex(P_nt.Op_Header.Numberofdirectories,8));
oo.Add('');
oo.add('');
oo.add('*=========================================================================*');
oo.add(' Directories');
oo.add('*=========================================================================*');
oo.add('Directory Name    V-Address   V-Size');
oo.add('--------------    ---------   ---------');

     for i:= 0 to P_nt.Op_Header.Numberofdirectories -1 do
     begin
     oo.add(format('%-18s%-12.8x%.8x',[dr[i],
                  p_nt.Op_Header.data_directory[i].VirtualAddress,
                  p_nt.Op_Header.data_directory[i].Size]));
     end;

exp_ofs:=p_nt.Op_Header.data_directory[0].VirtualAddress;
imp_ofs:=p_nt.Op_Header.data_directory[1].VirtualAddress;
res_ofs:=p_nt.Op_Header.data_directory[2].VirtualAddress;

exp_ok:=exp_ofs<>0;
imp_ok:=imp_ofs<>0;
res_ok:=res_ofs<>0;

oo.Add('');
oo.Add('');
oo.Add('');
end;

//----------------------------Sections------------------------------------------

procedure TF_Main.go_sections;
var
i:integer;
begin
oo.add('*=========================================================================*');
oo.add(' Sections');
oo.add('*=========================================================================*');
p_sec:=P_SECTo_HEADER(p_nt);
Inc(P_NT_HEADER(p_sec));
ns:=p_nt.F_Header.NumberOfSections ;
oo.add('--------------------------------------------------------------------------');
oo.add(' # | Name     | V_Size   | V_Address | Data_Size | Data_Offset | Flags ');
oo.add('--------------------------------------------------------------------------');
  for i := 1 to  ns do
  begin
  oo.add(format('%.2d | %-9.8s| %-9.8x| %-10.8x| %-10.8x| %-12.8x| %.8x',
            [i,p_sec.Name,p_sec.misc.VirtualSize,p_sec.VirtualAddress,
            p_sec.SizeOfRawData,p_sec.PointerToRawData,p_sec.Characteristics]));
  Inc(p_sec);
  end;
oo.add('--------------------------------------------------------------------------');
oo.add('');
oo.add('');
oo.Add('');
end;
//---------------------------------export---------------------------------------

procedure TF_Main.go_export;
var
i:integer;
begin
if exp_ok then
begin
oo.add('*=========================================================================*');
oo.add(' Export Table');
oo.add('*=========================================================================*');
oo.add('');
P_exp:=P_export(Cardinal(P_Dos)+get_rva(exp_ofs));
s:=sol_C(p_exp.Name);

oo.Add(s+#9+': Exports ('+inttostr(p_exp.NumberOfFunctions)
+') Functions  ('+inttostr(p_exp.NumberOfNames)+' Named)');
oo.add('-----------   --------------------------------------');
oo.add('');

    P_fs:=P_funcs(Cardinal(P_Dos)+get_rva(p_exp.AddressOfNames));

    for i:=1 to p_exp.NumberOfNames do   // dump names only ...
    begin
    oo.Add(format('%-16s%s',['',sol_c(P_fs^)]));
    inc(P_funcs(p_fs));
    end;
   
oo.Add('');
oo.Add('');
oo.Add('');
end
else
begin
oo.add('*=========================================================================*');
oo.add(' Export Table is Missing in : '+extractfilename(pe_file));
oo.add('*=========================================================================*');
oo.add('');
oo.add('');
oo.Add('');
end;

end;

//-----------------------------------import-------------------------------------

procedure TF_Main.go_import;
begin

if imp_ok then
begin
oo.add('*=========================================================================*');
oo.add(' Import Table');
oo.add('*=========================================================================*');
P_imp:=P_import(Cardinal(P_Dos)+get_rva(imp_ofs));
repeat
 s:=sol_C(Cardinal(p_imp.Name));

        if p_imp.OriginalFirstThunk=0 then
        Thunk:=p_imp.FirstThunk
        else
        Thunk:=p_imp.OriginalFirstThunk;

          P_fs:=P_funcs(Cardinal(P_Dos)+get_rva(Thunk));
          oo.Add('');
          oo.Add(format( '%-14s: Hint     Function Name',[s]));
          oo.Add(format('%-16s----     ----------------------------------',['']));
          repeat
          if (p_fs^ and $80000000)=0 then
          oo.Add(format('%-16s%-7.4x  %s',['',sol_Hint(p_fs^),sol_C(p_fs^+2)]))
          else
          oo.Add(format('%-16sOrd      %s',['',inttostr(p_fs^ and $7FFFFFFF)]));
          inc(P_funcs(p_fs));
          until  p_fs^=$00;

Inc(P_import(P_imp));
until p_imp.Name=$00;

oo.Add('');
oo.Add('');
oo.Add('');
end
else
begin
oo.add('*=========================================================================*');
oo.add(' Import Table is Missing in : '+extractfilename(pe_file));
oo.add('*=========================================================================*');
oo.add('');
oo.add('');
oo.Add('');
end; end;
    
//--------------------------------resources-------------------------------------

procedure TF_Main.Go_Resour;
var
i,j,k:integer;
begin

if res_ok then
begin
res_ofs:=get_rva(res_ofs);
P_res_d :=P_RES_DIRECTORY(Cardinal(P_Dos)+res_ofs);      // root
nr:=P_res_d.NumberOfIdEntries+p_res_d.NumberOfNamedEntries;
oo.add('*=========================================================================*');
oo.Add(' Resources Section   : '+inttostr(nr)+' entries');
oo.add('*=========================================================================*');
P_Entry:=P_RES_DIR_ENTRY(p_res_d);     // level 1
Inc(P_RES_DIRECTORY(p_entry));

for i:=1 to nr do                       // 1 to number of resources
begin
oo.Add('');
oo.Add('');
s:=sol_A(Cardinal(p_entry.Name));
P_res_d :=P_RES_DIRECTORY(Cardinal(P_Dos)+res_ofs+(p_entry.OffsetToData and $7FFFFFFF));
nx:=P_res_d.NumberOfIdEntries+p_res_d.NumberOfNamedEntries;
oo.Add(#9+format('#:%d %-34s %-3d Entries',[i,'('+s+')',nx]));
oo.Add(#9+'--------------------------------------------------');
P_ee:=P_RES_DIR_ENTRY(p_res_d);         // level 2
Inc(P_RES_DIRECTORY(p_ee));

      for j:=1 to nx do
      begin
      s:=sol_B(p_ee.Name);
      P_res_d :=P_RES_DIRECTORY(Cardinal(P_Dos)+res_ofs+(p_ee.OffsetToData and $7FFFFFFF));
      nc:=P_res_d.NumberOfIdEntries+p_res_d.NumberOfNamedEntries;
      P_ii:=P_RES_DIR_ENTRY(p_res_d);    // level 3
      Inc(P_RES_DIRECTORY(P_ii));

                if nc>1 then    //   languages if any   !!!
                begin
                oo.Add('');
                oo.Add(#9+'('+s+')');
                  for k:=1 to nc do
                  begin
                  P_data:=P_RES_DATA(Cardinal(P_Dos)+res_ofs+p_ii.OffsetToData);
                  oo.Add(format('%-15s%-11s  At(%.8x). Size(%.8x)',['',sol_B(p_ii.Name),get_rva(p_data.OffsetToData),p_data.Size]));
                  Inc(P_RES_DIR_ENTRY(p_ii));
                  end;
                end
                else
                begin
                P_data:=P_RES_DATA(Cardinal(P_Dos)+res_ofs+p_ii.OffsetToData);
                oo.Add(#9+format('%-20s  At(%.8x). Size(%.8x)',[s,get_rva(p_data.OffsetToData),p_data.Size]));
                end;

      Inc(P_RES_DIR_ENTRY(p_ee));
      end;

Inc(P_RES_DIR_ENTRY(p_entry));
end;

end
else
begin
oo.add('*=========================================================================*');
oo.Add(' Resource Table is Missing in : '+extractfilename(pe_file));
oo.add('*=========================================================================*');
oo.add('');
end;

end;

//-----------------------------------on Create----------------------------------

procedure TF_Main.FormCreate(Sender: TObject);
begin
  if paramcount>0 then
  begin
  pe_file:=paramstr(1);
  go_load;
  end;
end;

//---------------------------------------save-----------------------------------

procedure TF_Main.SavClick(Sender: TObject);
begin
if not sv.Execute then exit;

  if pos('.',sv.FileName)>0 then
  m.Lines.SaveToFile(sv.FileName)
  else
  m.Lines.SaveToFile(sv.FileName+'.Txt');

 
end;

//------------------------------------------------------------------------------

procedure TF_Main.Exit1Click(Sender: TObject);
begin
close;
end;

//------------------------------------------------------------------------------

procedure TF_Main.About1Click(Sender: TObject);
begin
f2.show;
end;

//------------------------------------------------------------------------------

procedure TF_Main.Copy1Click(Sender: TObject);
begin
m.CopyToClipboard
end;

//------------------------------------------------------------------------------

procedure TF_Main.selectAll1Click(Sender: TObject);
begin
m.SelectAll;
end;

//------------------------------------------------------------------------------


end.





../delphi71code/tchag-pe-portable-executable-structure-extractor/unit1-pas..