⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unitpefile.pas

📁 灰鸽子VIP1.2经典源代码
💻 PAS
📖 第 1 页 / 共 4 页
字号:
unit unitPEFile;

interface

uses Windows, Classes, SysUtils, ConTnrs, unitResourceDetails, ImageHlp;

type

TPEModule = class;

//----------------------------------------------------------------------
// TImageSection class

TImageSection = class
private
  fParent: TPEModule;
  fSectionHeader : TImageSectionHeader;
  fRawData : TMemoryStream;
  fUninitializedDataSize : Integer;

  function GetSectionName: string;
public
  constructor Create (AParent : TPEModule; const AHeader : TImageSectionHeader; rawData : pointer);
  destructor destroy; override;
  property Parent : TPEModule read fParent;

  property SectionName : string read GetSectionName;
  property SectionHeader : TImageSectionHeader read fSectionHeader;
  property RawData : TMemoryStream read fRawData;
end;

//----------------------------------------------------------------------
// TPEModule class

TPEModule = class (TResourceModule)
private
  fDOSHeader : TImageDosHeader;
  fCOFFHeader : TImageFileHeader;
  fOptionalHeader : PImageOptionalHeader;
  fSectionList : TObjectList;                   // List of TImageSection objects
  fDOSStub : TMemoryStream;
  fCommentBlock : PChar;
  fCommentSize : Integer;
  fEndComment : PChar;
  fEndCommentSize : Integer;

  function GetOptionalHeader: TImageOptionalHeader;
  function GetImageSection(index: Integer): TImageSection;
  function GetImageSectionCount: Integer;
  function GetDataDictionary(index: Integer): PImageDataDirectory;
  function GetDataDictionaryCount: Integer;
  function GetDOSHeader: TImageDosHeader;
  function GetCOFFHeader: TImageFileHeader;

protected
  procedure Decode (memory : pointer; exeSize : Integer); virtual;
  procedure Encode; virtual;
  property OptionalHeaderPtr : PImageOptionalHeader read fOptionalHeader;
  function FindDictionaryEntrySection (entryNo : Integer): Integer;

public
  constructor Create;
  destructor Destroy; override;

  property DOSHeader : TImageDosHeader read GetDOSHeader;
  property COFFHeader : TImageFileHeader read GetCOFFHeader;
  property OptionalHeader : TImageOptionalHeader read GetOptionalHeader;

  property ImageSectionCount : Integer read GetImageSectionCount;
  property ImageSection [index : Integer] : TImageSection read GetImageSection;

  property DataDictionaryCount : Integer read GetDataDictionaryCount;
  property DataDictionary [index : Integer] : PImageDataDirectory read GetDataDictionary;

  procedure LoadFromStream (s : TStream); override;
  procedure LoadFromFile (const name : string); override;

  procedure SaveToStream (s : TStream); override;
  procedure SaveToFile (const name : string); override;
end;

//----------------------------------------------------------------------
// TResourceDirectoryTable record

TResourceDirectoryTable = packed record
  characteristics : DWORD; // Resource flags, reserved for future use; currently set to zero.
  timeDateStamp : DWORD;   // Time the resource data was created by the resource compiler.
  versionMajor : WORD;     // Major version number, set by the user.
  versionMinor : WORD;     // Minor version number.
  cNameEntries : WORD;     // Number of directory entries, immediately following the table, that use strings to identify Type, Name, or Language (depending on the level of the table).
  cIDEntries : WORD;       // Number of directory entries, immediately following the Name entries, that use numeric identifiers for Type, Name, or Language.
end;
PResourceDirectoryTable = ^TResourceDirectoryTable;

//----------------------------------------------------------------------
// TPEModule record

TResourceDirectoryEntry = packed record
  name : DWORD;         // RVA Address of integer or string that gives the Type, Name, or Language identifier, depending on level of table.
  RVA : DWORD;          // RVA High bit 0. Address of a Resource Data Entry (a leaf).
                        // RVA High bit 1. Lower 31 bits are the address of another Resource Directory Table (the next level down).
end;
PResourceDirectoryEntry = ^TResourceDirectoryEntry;

//----------------------------------------------------------------------
// TResourceDirectoryEntry record

TResourceDataEntry = packed record
  OffsetToData : DWORD;
  Size : DWORD;
  CodePage : DWORD;
  Reserved : DWORD
end;
PResourceDataEntry = ^TResourceDataEntry;

//----------------------------------------------------------------------
// TPEResourceModule class

TPEResourceModule = class (TPEModule)
private
  fDetailList : TObjectList;             // List of TResourceDetails objects

  function GetResourceSection : TImageSection;
protected
  procedure Decode (memory : pointer; exeSize : Integer); override;
  procedure Encode; override;
  function GetResourceCount: Integer;  override;
  function GetResourceDetails(idx: Integer): TResourceDetails; override;
public
  constructor Create;
  destructor Destroy; override;


  property ResourceCount : Integer read GetResourceCount;
  property ResourceDetails [idx : Integer] : TResourceDetails read GetResourceDetails;
  procedure DeleteResource (resourceNo : Integer); override;
  procedure InsertResource (idx : Integer; details : TResourceDetails); override;
  function AddResource (details : TResourceDetails) : Integer; override;
  function IndexOfResource (details : TResourceDetails) : Integer; override;
  procedure SortResources; override;
end;


EPEException = class (Exception);

implementation

{ TPEModule }
resourcestring
  rstInvalidDOSSignature   = 'Invalid DOS signature';
  rstInvalidCOFFSignature  = 'Invalid COFF signature';
  rstInvalidOptionalHeader = 'Invalid Windows Image';
  rstBadDictionaryIndex    = 'Index exceeds data dictionary count';
  rstBadLangID             = 'Unsupported non-integer language ID in resource';
  rstEncode                = 'Error encoding module';

type
  TResourceNode = class
    count : Integer;
    nodes : array of record
      id : string;
      intID : boolean;
      case leaf : boolean of
        false : (next : TResourceNode);
        true : (data : TMemoryStream; CodePage : DWORD)
      end;

    constructor Create (const AType, AName : string; ALang : Integer; aData : TMemoryStream; CodePage : DWORD);
    constructor CreateNameNode (const AName : string; ALang : Integer; aData : TMemoryStream; CodePage : DWORD);
    constructor CreateLangNode (ALang : Integer; aData : TMemoryStream; CodePage : DWORD);
    procedure Add (const AType, AName : string; ALang : Integer; aData : TMemoryStream; CodePage : DWORD);
    procedure AddName (const AName : string; ALang : Integer; aData : TMemoryStream; CodePage : DWORD);
    procedure AddLang (ALang : Integer; aData : TMemoryStream; CodePage : DWORD);
    function IsID (idx : Integer): boolean;
    destructor Destroy; override;
  end;

(*----------------------------------------------------------------------*
 | constructor PEModule.Create                                          |
 |                                                                      |
 | Constructor for TPEModule instance.  Create empty section list       |
 *----------------------------------------------------------------------*)
constructor TPEModule.Create;
begin
  inherited Create;
  fSectionList := TObjectList.Create;
  fDOSStub := TMemoryStream.Create;
end;

(*----------------------------------------------------------------------*
 | procedure PEModule.Decode                                            |
 |                                                                      |
 | Decode the PE file.  Load the DOS header, the COFF header and the    |
 | 'optional' header, then load each section into fSectionList          |
 *----------------------------------------------------------------------*)
procedure TPEModule.Decode (Memory : pointer; exeSize : Integer);
var
  offset : LongInt;
  i : Integer;
  sectionHeader : PImageSectionHeader;
  commentOffset : Integer;
begin
  fSectionList.Clear;

                                // Check it's really a PE file.
  if PWORD (Memory)^ <> IMAGE_DOS_SIGNATURE then
    raise EPEException.Create (rstInvalidDOSSignature);

                                // Load the DOS header
  fDOSHeader := PImageDosHeader (Memory)^;

  offset := fDOSHeader._lfanew;
  fDOSStub.Write ((PChar (Memory) + sizeof (fDOSHeader))^, fDOSHeader._lfanew - sizeof (fDOSHeader));

                                // Check the COFF signature
  if PDWORD (PChar (Memory) + offset)^ <> IMAGE_NT_SIGNATURE then
    raise EPEException.Create (rstInvalidCOFFSignature);

                                // Load the COFF header
  Inc (offset, sizeof (DWORD));       
  fCOFFHeader := PImageFileHEader (PChar (Memory) + offset)^;

  Inc (offset, sizeof (fCOFFHeader));

                                // Check the Optional Header signature.  nb
                                // the optional header is compulsory for
                                // 32 bit windows modules!
  if PWORD (PChar (Memory) + offset)^ <> IMAGE_NT_OPTIONAL_HDR_MAGIC then
    raise EPEException.Create (rstInvalidOptionalHeader);

                                // Save the 'optional' header
  ReallocMem (fOptionalHeader, fCOFFHeader.SizeOfOptionalHeader);
  Move ((PChar (Memory) + Offset)^, fOptionalHeader^, fCOFFHeader.SizeOfOptionalHeader);

  Inc (offset, fCOFFHeader.SizeOfOptionalHeader);

  sectionHeader := PImageSectionHeader (PChar (memory) + offset);
  commentOffset := offset + fCOFFHeader.NumberOfSections * sizeof (TImageSectionHeader);

// Save padding between the end of the section headers, and the start of the
// 1st section.  TDump reports this as 'comment', and it seems to be important
// to MS clock.exe...

  fCommentSize := Integer (sectionHeader^.PointerToRawData) - commentOffset;

  if fCommentSize > 0 then
  begin
    GetMem (fCommentBlock, fCommentSize);
    Move ((PChar (memory) + commentOffset)^, fCommentBlock^, fCommentSize)
  end;
                                // Now save each image section in the fSectionList
  for i := 0 to fCOFFHeader.NumberOfSections - 1 do
  begin
    sectionHeader := PImageSectionHeader (PChar (memory) + offset);
    fSectionList.Add (TImageSection.Create (self, sectionHeader^, PChar (memory) + sectionHeader^.PointertoRawData));
    Inc (offset, sizeof (TImageSectionHeader));
  end;

  i := sectionHeader^.PointerToRawData + sectionHeader^.SizeOfRawData;

// Save the padding between the last section and the end of the file.
// This appears to hold debug info and things ??

  fEndCommentSize := exeSize - i;
  if fEndCommentSize > 0 then
  begin
    GetMem (fEndComment, fEndCommentSize);
    Move ((PChar (memory) + i)^, fEndComment^, fEndCommentSize)
  end
end;

(*----------------------------------------------------------------------*
 | destructor PEModule.Destroy                                          |
 |                                                                      |
 | Destructor for TPEModule instance.                                   |
 *----------------------------------------------------------------------*)
destructor TPEModule.Destroy;
begin
  ReallocMem (fOptionalHeader, 0);
  fSectionList.Free;
  fDOSStub.Free;
  ReallocMem (fCommentBlock, 0);
  ReallocMem (fEndComment, 0);
  inherited;
end;

(*----------------------------------------------------------------------*
 | procedure PEModule.Encode                                            |
 |                                                                      |
 | Fix up the data prior to writing to stream.                          |
 |                                                                      |
 | Ensure that the headers match what we've got...                      |
 *----------------------------------------------------------------------*)
procedure TPEModule.Encode;
var
  offset : DWORD;
  i : Integer;
  section : TImageSection;
  align : Integer;
  addrAlign : Integer;
  address : Integer;
  alignedSize, AddrAlignedSize : Integer;
  codeSize, iDataSize, uDataSize, iSize : Integer;
begin
  codeSize := 0;
  iDataSize := 0;
  uDataSize := 0;
                                               // Use the DOS stub from their .EXE
  fDOSHeader._lfanew := sizeof (fDosHeader) + fDOSStub.Size;

                                               // Fixup sections count
  fCOFFHeader.NumberOfSections := fSectionList.Count;

  iSize :=  fDOSHeader._lfanew +               // File offset for start of sections
            SizeOf (DWORD) +                   // NT signature
            sizeof (fCoffHeader) +
            fCOFFHeader.SizeOfOptionalHeader +
            fSectionList.Count * sizeof (TImageSectionHeader);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -