unit CompareFiles;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ImgList, Menus;

function GetInfo_2(sFile_2:string):boolean;

type
  TfrmCompare = class(TForm)
    lsInfo: TListView;
    ImageList1: TImageList;
    PopMain: TPopupMenu;
    SaveReport1: TMenuItem;
    procedure lsInfoAdvancedCustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
      var DefaultDraw: Boolean);
    procedure SaveReport1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmCompare: TfrmCompare;
  IDH_2:    TImageDosHeader;
  INH_2:    TImageNtHeaders;
  ISH_2:    TImageSectionHeader;

implementation

uses Main;

{$R *.dfm}

function CompareVars(Var1:DWORD; Var2:DWORD):integer;
begin
  if Var1 = Var2 then
    Result := 0
  else
    Result := 1;
end;

function CompareString(Var1:string; Var2:string):integer;
begin
  if Var1 = Var2 then
    Result := 0
  else
    Result := 1
end;

function GetInfo_2(sFile_2:string):boolean;
var
hFile:  THandle;
dRead:  DWORD;
SecName_2 : array [0..7] of char;
i:      integer;
begin
  hFile := CreateFile(PChar(sFile_2), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if hFile <> INVALID_HANDLE_VALUE then
  begin
    frmCompare.lsInfo.Clear;
    SetFilePointer(hFile, 0, nil, FILE_BEGIN);
    ReadFile(hFile, IDH_2, SizeOf(IDH_2), dRead, nil); // Read first 64 bytes into IMAGE_DOS_HEADER struct
    if IDH_2.e_magic <> 23117 then // Check for valid MZ header
    begin
      MessageBox(Application.Handle, PChar('Invalid PE File'), PChar('Error'), MB_ICONEXCLAMATION);
      Exit;
    end;
    SetFilePointer(hFile, IDH_2._lfanew, nil, FILE_BEGIN); // Setting file pointer to the beginning IMAGE_NT_HEADERS struct
    ReadFile(hFile, INH_2, SizeOf(INH_2), dRead, nil); // Read 248 bytes into IMAGE_NT_HEADERS struct

    ///

    with frmCompare.lsInfo.Items.Add do // IMAGE_DOS_HEADER
    begin
      Caption := 'DosHeader';
      ImageIndex := 2;
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'Magic';
      SubItems.Add(IntToHex(IDH_2.e_magic, 4));
      SubItems.Add(IntToHex(IDH.e_magic, 4));
      ImageIndex := CompareVars(IDH_2.e_magic, IDH.e_magic);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := '_lfanew';
      SubItems.Add(IntToHex(IDH_2._lfanew, 8));
      SubItems.Add(IntToHex(IDH._lfanew, 8));
      ImageIndex := CompareVars(IDH_2._lfanew, IDH._lfanew);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin  // IMAGE_FILE_HEADER
      Caption := 'FileHeader';
      ImageIndex := 2;
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'Machine';
      SubItems.Add(IntToHex(INH_2.FileHeader.Machine, 4));
      SubItems.Add(IntToHex(INH.FileHeader.Machine, 4));
      ImageIndex := CompareVars(INH_2.FileHeader.Machine, INH.FileHeader.Machine);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'NumberOfSections';
      SubItems.Add(IntToHex(INH_2.FileHeader.NumberOfSections, 4));
      SubItems.Add(IntToHex(INH.FileHeader.NumberOfSections, 4));
      ImageIndex := CompareVars(INH_2.FileHeader.NumberOfSections, INH.FileHeader.NumberOfSections);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'TimeDateStamp';
      SubItems.Add(IntToHex(INH_2.FileHeader.TimeDateStamp, 8));
      SubItems.Add(IntToHex(INH.FileHeader.TimeDateStamp, 8));
      ImageIndex := CompareVars(INH_2.FileHeader.TimeDateStamp, INH.FileHeader.TimeDateStamp);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'PointerToSymbolTable';
      SubItems.Add(IntToHex(INH_2.FileHeader.PointerToSymbolTable, 8));
      SubItems.Add(IntToHex(INH.FileHeader.PointerToSymbolTable, 8));
      ImageIndex := CompareVars(INH_2.FileHeader.PointerToSymbolTable, INH.FileHeader.PointerToSymbolTable);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'NumberOfSymbols';
      SubItems.Add(IntToHex(INH_2.FileHeader.NumberOfSymbols, 8));
      SubItems.Add(IntToHex(INH.FileHeader.NumberOfSymbols, 8));
      ImageIndex := CompareVars(INH_2.FileHeader.NumberOfSymbols, INH.FileHeader.NumberOfSymbols);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'NumberOfSymbols';
      SubItems.Add(IntToHex(INH_2.FileHeader.NumberOfSymbols, 8));
      SubItems.Add(IntToHex(INH.FileHeader.NumberOfSymbols, 8));
      ImageIndex := CompareVars(INH_2.FileHeader.NumberOfSymbols, INH.FileHeader.NumberOfSymbols);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'SizeOfOptionalHeader';
      SubItems.Add(IntToHex(INH_2.FileHeader.SizeOfOptionalHeader, 8));
      SubItems.Add(IntToHex(INH.FileHeader.SizeOfOptionalHeader, 8));
      ImageIndex := CompareVars(INH_2.FileHeader.SizeOfOptionalHeader, INH.FileHeader.SizeOfOptionalHeader);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'Characteristics';
      SubItems.Add(IntToHex(INH_2.FileHeader.Characteristics, 4));
      SubItems.Add(IntToHex(INH.FileHeader.Characteristics, 4));
      ImageIndex := CompareVars(INH_2.FileHeader.Characteristics, INH.FileHeader.Characteristics);
    end;

    with frmCompare.lsInfo.Items.Add do  // IMAGE_OPTIONAL_HEADER
    begin
      Caption := 'OptionalHeader';
      ImageIndex := 2;
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'Entry Point';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.AddressOfEntryPoint, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.AddressOfEntryPoint, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.AddressOfEntryPoint, INH.OptionalHeader.AddressOfEntryPoint);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'ImageBase';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.ImageBase, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.ImageBase, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.ImageBase, INH.OptionalHeader.ImageBase);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'SizeOfImage';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.SizeOfImage, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.SizeOfImage, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.SizeOfImage, INH.OptionalHeader.SizeOfImage);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'BaseOfCode';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.BaseOfCode, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.BaseOfCode, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.BaseOfCode, INH.OptionalHeader.BaseOfCode);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'BaseOfData';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.BaseOfData, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.BaseOfData, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.BaseOfData, INH.OptionalHeader.BaseOfData);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'SectionAlignment';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.SectionAlignment, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.SectionAlignment, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.SectionAlignment, INH.OptionalHeader.SectionAlignment);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'FileAlignment';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.FileAlignment, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.FileAlignment, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.FileAlignment, INH.OptionalHeader.FileAlignment);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'Magic';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.Magic, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.Magic, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.Magic, INH.OptionalHeader.Magic);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'SizeOfHeaders';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.SizeOfHeaders, 8));
      SubItems.Add(IntToHex(INH.OptionalHeader.SizeOfHeaders, 8));
      ImageIndex := CompareVars(INH_2.OptionalHeader.SizeOfHeaders, INH.OptionalHeader.SizeOfHeaders);
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'Linker Version';
      SubItems.Add(IntToStr(INH_2.OptionalHeader.MajorLinkerVersion) + '.' + IntToStr(INH_2.OptionalHeader.MinorLinkerVersion));
      SubItems.Add(IntToStr(INH.OptionalHeader.MajorLinkerVersion) + '.' + IntToStr(INH.OptionalHeader.MinorLinkerVersion));
      ImageIndex := CompareString(IntToStr(INH_2.OptionalHeader.MajorLinkerVersion) + '.' + IntToStr(INH_2.OptionalHeader.MinorLinkerVersion), IntToStr(INH.OptionalHeader.MajorLinkerVersion) + '.' + IntToStr(INH.OptionalHeader.MinorLinkerVersion));
    end;

    with frmCompare.lsInfo.Items.Add do
    begin
      Caption := 'Subsystem';
      SubItems.Add(IntToHex(INH_2.OptionalHeader.Subsystem, 0));
      SubItems.Add(IntToHex(INH.OptionalHeader.Subsystem, 0));
      ImageIndex := CompareVars(INH_2.OptionalHeader.Subsystem, INH.OptionalHeader.Subsystem);
    end;
  end;
  CloseHandle(hFile);
end;

procedure TfrmCompare.lsInfoAdvancedCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
  var DefaultDraw: Boolean);
begin

  if Item.Caption = 'DosHeader' then
  begin
    Sender.Canvas.Font.Style := Sender.Canvas.Font.Style + [fsBold];
    Sender.Canvas.Font.Color := clRed;
  end;

  if Item.Caption = 'FileHeader' then
  begin
    Sender.Canvas.Font.Style := Sender.Canvas.Font.Style + [fsBold];
    Sender.Canvas.Font.Color := clRed;
  end;

  if Item.Caption = 'OptionalHeader' then
  begin
    Sender.Canvas.Font.Style := Sender.Canvas.Font.Style + [fsBold];
    Sender.Canvas.Font.Color := clRed;
  end;
end;

procedure TfrmCompare.SaveReport1Click(Sender: TObject);
var
hFile:    THandle;
i:        integer;
dWritten: DWORD;
sBuff:    string;
begin
  hFile := CreateFile(PChar('HPE-Report-' + ExtractFileName(sFile) + '-' + ExtractFileName(lsInfo.Columns[2].Caption) + '.txt'), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 0, 0);
  if hFile <>  INVALID_HANDLE_VALUE then
  begin
    SetFilePointer(hFile, 0, nil, FILE_BEGIN);
    sBuff := ExtractFileName(sFile) + ' >> ' + ExtractFileName(lsInfo.Columns[2].Caption) + #13#10#13#10;
    WriteFile(hFile, sBuff[1], Length(sBuff), dWritten, nil);
    For i := 0 to lsInfo.Items.Count - 1 do
    begin
      if (lsInfo.Items[i].Caption <> 'DosHeader') and (lsInfo.Items[i].Caption <> 'FileHeader') and (lsInfo.Items[i].Caption <> 'OptionalHeader') then
      begin
        sBuff := lsInfo.Items[i].Caption + ':  ' + lsInfo.Items[i].SubItems[0] + ' >> ' + lsInfo.Items[i].SubItems[1] + #13#10;
        WriteFile(hFile, sBuff[1], Length(sBuff), dWritten, nil);
      end;
    end;
    sBuff := #13#10#13#10#13#10 + '// HoundPE';
    WriteFile(hFile, sBuff[1], Length(sBuff), dWritten, nil);
  end;
  CloseHandle(hFile);
end;

end.
