📄 jclpeimage.pas
字号:
FIsPackage: Boolean;
FIsBorlandImage: Boolean;
FLibHandle: THandle;
FPackageInfo: TJclPePackageInfo;
FPackageCompilerVersion: Integer;
function GetFormCount: Integer;
function GetForms(Index: Integer): TJclPeBorForm;
function GetFormFromName(const FormClassName: string): TJclPeBorForm;
function GetLibHandle: THandle;
function GetPackageCompilerVersion: Integer;
function GetPackageInfo: TJclPePackageInfo;
protected
procedure AfterOpen; override;
procedure Clear; override;
procedure CreateFormsList;
public
constructor Create(ANoExceptions: Boolean = False); override;
destructor Destroy; override;
function DependedPackages(List: TStrings; FullPathName, Descriptions: Boolean): Boolean;
function FreeLibHandle: Boolean;
property Forms[Index: Integer]: TJclPeBorForm read GetForms;
property FormCount: Integer read GetFormCount;
property FormFromName[const FormClassName: string]: TJclPeBorForm read GetFormFromName;
property IsBorlandImage: Boolean read FIsBorlandImage;
property IsPackage: Boolean read FIsPackage;
property LibHandle: THandle read GetLibHandle;
property PackageCompilerVersion: Integer read GetPackageCompilerVersion;
property PackageInfo: TJclPePackageInfo read GetPackageInfo;
end;
// Threaded function search
TJclPeNameSearchOption = (seImports, seDelayImports, seBoundImports, seExports);
TJclPeNameSearchOptions = set of TJclPeNameSearchOption;
TJclPeNameSearchNotifyEvent = procedure (Sender: TObject; PeImage: TJclPeImage;
var Process: Boolean) of object;
TJclPeNameSearchFoundEvent = procedure (Sender: TObject; const FileName: TFileName;
const FunctionName: string; Option: TJclPeNameSearchOption) of object;
TJclPeNameSearch = class(TThread)
private
F_FileName: TFileName;
F_FunctionName: string;
F_Option: TJclPeNameSearchOption;
F_Process: Boolean;
FFunctionName: string;
FOptions: TJclPeNameSearchOptions;
FPath: string;
FPeImage: TJclPeImage;
FOnFound: TJclPeNameSearchFoundEvent;
FOnProcessFile: TJclPeNameSearchNotifyEvent;
protected
function CompareName(const FunctionName, ComparedName: string): Boolean; virtual;
procedure DoFound;
procedure DoProcessFile;
procedure Execute; override;
public
constructor Create(const FunctionName, Path: string; Options: TJclPeNameSearchOptions = [seImports, seExports]);
procedure Start;
property OnFound: TJclPeNameSearchFoundEvent read FOnFound write FOnFound;
property OnProcessFile: TJclPeNameSearchNotifyEvent read FOnProcessFile write FOnProcessFile;
end;
// PE Image miscellaneous functions
type
TJclRebaseImageInfo = record
OldImageSize: DWORD;
OldImageBase: DWORD;
NewImageSize: DWORD;
NewImageBase: DWORD;
end;
{ Image validity }
function IsValidPeFile(const FileName: TFileName): Boolean;
function PeGetNtHeaders(const FileName: TFileName; var NtHeaders: TImageNtHeaders): Boolean;
{ Image modifications }
function PeCreateNameHintTable(const FileName: TFileName): Boolean;
function PeRebaseImage(const ImageName: TFileName; NewBase: DWORD = 0; TimeStamp: DWORD = 0;
MaxNewSize: DWORD = 0): TJclRebaseImageInfo;
function PeUpdateLinkerTimeStamp(const FileName: string; const Time: TDateTime): Boolean;
function PeReadLinkerTimeStamp(const FileName: string): TDateTime;
function PeInsertSection(const FileName: TFileName; SectionStream: TStream; SectionName: string): Boolean;
{ Image Checksum }
function PeVerifyCheckSum(const FileName: TFileName): Boolean;
function PeClearCheckSum(const FileName: TFileName): Boolean;
function PeUpdateCheckSum(const FileName: TFileName): Boolean;
// Various simple PE Image searching and listing routines
{ Exports searching }
function PeDoesExportFunction(const FileName: TFileName; const FunctionName: string;
Options: TJclSmartCompOptions = []): Boolean;
function PeIsExportFunctionForwardedEx(const FileName: TFileName; const FunctionName: string;
var ForwardedName: string; Options: TJclSmartCompOptions = []): Boolean;
function PeIsExportFunctionForwarded(const FileName: TFileName; const FunctionName: string;
Options: TJclSmartCompOptions = []): Boolean;
{ Imports searching }
function PeDoesImportFunction(const FileName: TFileName; const FunctionName: string;
const LibraryName: string = ''; Options: TJclSmartCompOptions = []): Boolean;
function PeDoesImportLibrary(const FileName: TFileName; const LibraryName: string;
Recursive: Boolean = False): Boolean;
{ Imports listing }
function PeImportedLibraries(const FileName: TFileName; const LibrariesList: TStrings;
Recursive: Boolean = False; FullPathName: Boolean = False): Boolean;
function PeImportedFunctions(const FileName: TFileName; const FunctionsList: TStrings;
const LibraryName: string = ''; IncludeLibNames: Boolean = False): Boolean;
{ Exports listing }
function PeExportedFunctions(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
function PeExportedNames(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
function PeExportedVariables(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
{ Resources listing }
function PeResourceKindNames(const FileName: TFileName; ResourceType: TJclPeResourceKind;
const NamesList: TStrings): Boolean;
{ Borland packages specific }
function PeBorFormNames(const FileName: TFileName; const NamesList: TStrings): Boolean;
function PeBorDependedPackages(const FileName: TFileName; PackagesList: TStrings;
FullPathName, Descriptions: Boolean): Boolean;
// Missing imports checking routines
function PeFindMissingImports(const FileName: TFileName; MissingImportsList: TStrings): Boolean; overload;
function PeFindMissingImports(RequiredImportsList, MissingImportsList: TStrings): Boolean; overload;
function PeCreateRequiredImportList(const FileName: TFileName; RequiredImportsList: TStrings): Boolean;
// Mapped or loaded image related routines
function PeMapImgNtHeaders(const BaseAddress: Pointer): PImageNtHeaders;
function PeMapImgLibraryName(const BaseAddress: Pointer): string;
function PeMapImgSections(NtHeaders: PImageNtHeaders): PImageSectionHeader;
function PeMapImgFindSection(NtHeaders: PImageNtHeaders;
const SectionName: string): PImageSectionHeader;
function PeMapImgExportedVariables(const Module: HMODULE; const VariablesList: TStrings): Boolean;
function PeMapImgResolvePackageThunk(Address: Pointer): Pointer;
function PeMapFindResource(const Module: HMODULE; const ResourceType: PChar;
const ResourceName: string): Pointer;
type
TJclPeSectionStream = class(TCustomMemoryStream)
private
FInstance: HMODULE;
FSectionHeader: TImageSectionHeader;
procedure Initialize(Instance: HMODULE; const ASectionName: string);
public
constructor Create(Instance: HMODULE; const ASectionName: string);
function Write(const Buffer; Count: Longint): Longint; override;
property Instance: HMODULE read FInstance;
property SectionHeader: TImageSectionHeader read FSectionHeader;
end;
// API hooking classes
type
TJclPeMapImgHookItem = class(TObject)
private
FBaseAddress: Pointer;
FFunctionName: string;
FModuleName: string;
FNewAddress: Pointer;
FOriginalAddress: Pointer;
FList: TObjectList;
protected
function InternalUnhook: Boolean;
public
destructor Destroy; override;
function Unhook: Boolean;
property BaseAddress: Pointer read FBaseAddress;
property FunctionName: string read FFunctionName;
property ModuleName: string read FModuleName;
property NewAddress: Pointer read FNewAddress;
property OriginalAddress: Pointer read FOriginalAddress;
end;
TJclPeMapImgHooks = class(TObjectList)
private
function GetItems(Index: Integer): TJclPeMapImgHookItem;
function GetItemFromOriginalAddress(OriginalAddress: Pointer): TJclPeMapImgHookItem;
function GetItemFromNewAddress(NewAddress: Pointer): TJclPeMapImgHookItem;
public
function HookImport(Base: Pointer; const ModuleName, FunctionName: string;
NewAddress: Pointer; var OriginalAddress: Pointer): Boolean;
class function IsWin9xDebugThunk(P: Pointer): Boolean;
class function ReplaceImport(Base: Pointer; ModuleName: string; FromProc, ToProc: Pointer): Boolean;
class function SystemBase: Pointer;
procedure UnhookAll;
function UnhookByNewAddress(NewAddress: Pointer): Boolean;
property Items[Index: Integer]: TJclPeMapImgHookItem read GetItems; default;
property ItemFromOriginalAddress[OriginalAddress: Pointer]: TJclPeMapImgHookItem read GetItemFromOriginalAddress;
property ItemFromNewAddress[NewAddress: Pointer]: TJclPeMapImgHookItem read GetItemFromNewAddress;
end;
// Image access under a debbuger
function PeDbgImgNtHeaders(ProcessHandle: THandle; BaseAddress: Pointer;
var NtHeaders: TImageNtHeaders): Boolean;
function PeDbgImgLibraryName(ProcessHandle: THandle; BaseAddress: Pointer;
var Name: string): Boolean;
// Borland BPL packages name unmangling
type
TJclBorUmSymbolKind = (skData, skFunction, skConstructor, skDestructor, skRTTI, skVTable);
TJclBorUmSymbolModifier = (smQualified, smLinkProc);
TJclBorUmSymbolModifiers = set of TJclBorUmSymbolModifier;
TJclBorUmDescription = record
Kind: TJclBorUmSymbolKind;
Modifiers: TJclBorUmSymbolModifiers;
end;
TJclBorUmResult = (urOk, urNotMangled, urMicrosoft, urError);
TJclPeUmResult = (umNotMangled, umBorland, umMicrosoft);
function PeBorUnmangleName(const Name: string; var Unmangled: string;
var Description: TJclBorUmDescription; var BasePos: Integer): TJclBorUmResult; overload;
function PeBorUnmangleName(const Name: string; var Unmangled: string;
var Description: TJclBorUmDescription): TJclBorUmResult; overload;
function PeBorUnmangleName(const Name: string; var Unmangled: string): TJclBorUmResult; overload;
function PeBorUnmangleName(const Name: string): string; overload;
function PeIsNameMangled(const Name: string): TJclPeUmResult;
function PeUnmangleName(const Name: string; var Unmangled: string): TJclPeUmResult;
implementation
uses
JclLogic, JclResources, JclSysUtils;
const
BPLExtension = '.bpl';
DCPExtension = '.dcp';
MANIFESTExtension = '.manifest';
PackageInfoResName = 'PACKAGEINFO';
DescriptionResName = 'DESCRIPTION';
PackageOptionsResName = 'PACKAGEOPTIONS';
DVclAlResName = 'DVCLAL';
DebugSectionName = '.debug';
ReadOnlySectionName = '.rdata';
// Helper routines
function AddFlagTextRes(var Text: string; const FlagText: PResStringRec; const Value, Mask: Integer): Boolean;
begin
Result := (Value and Mask <> 0);
if Result then
begin
if Length(Text) > 0 then
Text := Text + ', ';
Text := Text + LoadResString(FlagText);
end;
end;
function CompareResourceName(T1, T2: PChar): Boolean;
begin
if (LongRec(T1).Hi = 0) or (LongRec(T2).Hi = 0) then
Result := Word(T1) = Word(T2)
else
Result := (StrIComp(T1, T2) = 0);
end;
function CreatePeImage(const FileName: TFileName): TJclPeImage;
begin
Result := TJclPeImage.Create(True);
Result.FileName := FileName;
end;
function InternalImportedLibraries(const FileName: TFileName;
Recursive, FullPathName: Boolean; ExternalCache: TJclPeImagesCache): TStringList;
var
Cache: TJclPeImagesCache;
procedure ProcessLibraries(const AFileName: TFileName);
var
I: Integer;
S: string;
ImportLib: TJclPeImportLibItem;
begin
with Cache[AFileName].ImportList do
for I := 0 to Count - 1 do
begin
ImportLib := Items[I];
if FullPathName then
S := ImportLib.FileName
else
S := ImportLib.Name;
if Result.IndexOf(S) = -1 then
begin
Result.Add(S);
if Recursive then
ProcessLibraries(ImportLib.FileName);
end;
end;
end;
begin
if ExternalCache = nil then
Cache := TJclPeImagesCache.Create
else
Cache := ExternalCache;
try
Result := TStringList.Create;
try
Result.Sorted := True;
Result.Duplicates := dupIgnore;
ProcessLibraries(FileName);
except
FreeAndNil(Result);
raise;
end;
finally
if ExternalCache = nil then
Cache.Free;
end;
end;
// Smart name compare function
function PeStripFunctionAW(const FunctionName: string): string;
var
L: Integer;
begin
Result := FunctionName;
L := Length(Result);
// (rom) possible bug. 'A'..'Z' missing from set (better use AnsiValidIdentifierLetters).
if (L > 1) and (Result[L] in ['A', 'W']) and
(Result[L - 1] in ['a'..'z', '_', '0'..'9']) then
Delete(Result, L, 1);
end;
function PeSmartFunctionNameSame(const ComparedName, FunctionName: string;
Options: TJclSmartCompOptions): Boolean;
var
S: string;
begin
if scIgnoreCase in Options then
Result := StrSame(FunctionName, ComparedName)
else
Result := (FunctionName = ComparedName);
if (not Result) and not (scSimpleCompare in Options) then
begin
if Length(FunctionName) > 0 then
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -