unit HookFuncLib;
interface
uses Windows,SysUtils,Classes;
const
CHookJump_LEN = 5; //要修改的函数的跳转5字节,一个Jmp指令,一个函数地址
type
TFuncHookList = class;
TFuncHook = class
private
OldProtection: DWORD;//内存区域原读写权限
FOldFunc: Pointer;
OldCode: array[0..4] of Byte;//要修改的原函数5字节
NewCode: array[0..4] of Byte;
function GetHasInstalled: Boolean;//要替换成的5字节
public
constructor Create(OldFunc: Pointer);
destructor Destroy;override;
property HasHooked: Boolean read GetHasInstalled;
function HookFunc(NewFunc: Pointer): Boolean;
procedure UnHookFunc;
procedure SwapOld;
procedure SwapNew;
end;
TFuncHookList = class
private
HookList: TStringList;
function Getitem(index: Integer): TFuncHook;
function GetFuncCount: Integer;
public
constructor Create;
destructor Destroy;override;
function AddHookFunc(HookName: string;OldFunc: Pointer;NewFunc: Pointer): Boolean;
function FindHookedFunc(Func: Pointer): Integer;
procedure UnHookFunc(HookName: string);overload;
procedure UnHookFunc(Func: Pointer);overload;
procedure SwapToOldFunc(HookName: string);overload;
procedure SwapToOldFunc(Func: Pointer);overload;
procedure SwapToNewFunc(HookName: string);overload;
procedure SwapToNewFunc(Func: Pointer);overload;
procedure SwapToOldFuncs;
procedure SwapToNewFuncs;
procedure UnHookFuncs;
property item[index: Integer]: TFuncHook read Getitem;
property FuncCount: Integer read GetFuncCount;
end;
implementation
{ TFuncHook }
constructor TFuncHook.Create(OldFunc: Pointer);
begin
OldProtection := 0;
FOldFunc := OldFunc;
NewCode[0] := 0;
end;
destructor TFuncHook.Destroy;
begin
if HasHooked then
UnHookFunc;
inherited;
end;
function TFuncHook.GetHasInstalled: Boolean;
begin
Result := NewCode[0] <> 0;
end;
function TFuncHook.HookFunc(NewFunc: Pointer): Boolean;
var
OffsetAddr: DWORD; //偏移地址
begin
Result := False;
if (NewFunc <> nil) and (not HasHooked) then
begin
if VirtualProtect(FOldFunc,8,PAGE_EXECUTE_READWRITE,@OldProtection) then //解内存保护成功
begin
NewCode[0] := $e9;//Jmp指令机器码
OffsetAddr := Integer(NewFunc) - Integer(FOldFunc) - SizeOf(NewCode);
CopyMemory(@NewCode[1],@OffsetAddr,SizeOf(OffsetAddr));//将偏移地址写入NewCode的Jmp指令后
CopyMemory(@OldCode[0],FOldFunc,SizeOf(OldCode));//保存原函数5字节
CopyMemory(FOldFunc,@NewCode[0],SizeOf(NewCode));//替换5字节
Result := True;
end;
end;
end;
procedure TFuncHook.SwapNew;
begin
if HasHooked then
CopyMemory(FOldFunc,@NewCode[0],SizeOf(NewCode));//恢复到新函数执行
end;
procedure TFuncHook.SwapOld;
begin
if FOldFunc <> nil then
CopyMemory(FOldFunc,@OldCode[0],SizeOf(OldCode));//恢复到原函数
end;
procedure TFuncHook.UnHookFunc;
var
temp: DWORD;
begin
if (FOldFunc <> nil) and HasHooked then
begin
try
CopyMemory(FOldFunc,@OldCode[0],SizeOf(OldCode));//恢复原函数
VirtualProtect(FOldFunc,8,OldProtection,@temp);//恢复原读写保护
NewCode[0] := 0;
except
end;
end;
end;
{ TFuncHookList }
function TFuncHookList.AddHookFunc(HookName: string;OldFunc, NewFunc: Pointer): Boolean;
var
FuncHook: TFuncHook;
index: integer;
begin
if HookList.IndexOf(HookName) = -1 then
begin
index := FindHookedFunc(OldFunc);
if index <> -1 then
begin
FuncHook := TFuncHook(HookList.Objects[index]);
Result := FuncHook.HookFunc(NewFunc);
HookList[index] := HookName;
end
else
begin
FuncHook := TFuncHook.Create(OldFunc);
Result := FuncHook.HookFunc(NewFunc);
HookList.AddObject(HookName,FuncHook);
end;
end else
raise Exception.Create('HookName '+HookName+' 已经存在!');
end;
constructor TFuncHookList.Create;
begin
HookList := TStringList.Create;
end;
destructor TFuncHookList.Destroy;
begin
UnHookFuncs;
HookList.Free;
inherited;
end;
function TFuncHookList.FindHookedFunc(Func: Pointer): Integer;
var
i: Integer;
label 1;
begin
Result := -1;
for i := 0 to HookList.Count - 1 do
begin
if TFuncHook(HookList.Objects[i]).FOldFunc = Func then
begin
Result := i;
goto 1;
end;
end;
1:
end;
procedure TFuncHookList.UnHookFunc(HookName: string);
var
index: Integer;
begin
index := HookList.IndexOf(HookName);
if index <> -1 then
begin
TFuncHook(HookList.Objects[index]).Free;
//HookList.Delete(index);
end;
end;
procedure TFuncHookList.UnHookFunc(Func: Pointer);
var
index: Integer;
begin
index := FindHookedFunc(Func);
if index <> -1 then
begin
TFuncHook(HookList.Objects[index]).Free;
HookList.Delete(index);
end;
end;
procedure TFuncHookList.SwapToOldFuncs;
var
i: Integer;
begin
for i := 0 to HookList.Count - 1 do
TFuncHook(HookList.Objects[i]).SwapOld;
end;
procedure TFuncHookList.SwapToNewFuncs;
var
i: integer;
begin
for i := 0 to HookList.Count - 1 do
TFuncHook(HookList.Objects[i]).SwapNew;
end;
procedure TFuncHookList.UnHookFuncs;
begin
while HookList.Count > 0 do
begin
TFuncHook(HookList.Objects[HookList.Count - 1]).Free;
HookList.Delete(HookList.Count - 1);
end;
end;
procedure TFuncHookList.SwapToOldFunc(HookName: string);
var
index: Integer;
begin
index := HookList.IndexOf(HookName);
if index <> -1 then
TFuncHook(HookList.Objects[index]).SwapOld;
end;
procedure TFuncHookList.SwapToOldFunc(Func: Pointer);
var
index: Integer;
begin
index := FindHookedFunc(Func);
if index <> -1 then
TFuncHook(HookList.Objects[index]).SwapOld
end;
procedure TFuncHookList.SwapToNewFunc(HookName: string);
var
index: Integer;
begin
index := HookList.IndexOf(HookName);
if index <> -1 then
TFuncHook(HookList.Objects[index]).SwapNew;
end;
procedure TFuncHookList.SwapToNewFunc(Func: Pointer);
var
index: Integer;
begin
index := FindHookedFunc(Func);
if index <> -1 then
TFuncHook(HookList.Objects[index]).SwapNew;
end;
function TFuncHookList.Getitem(index: Integer): TFuncHook;
begin
if (index < 0) or (index > HookList.Count - 1) then
raise Exception.Create('超过边界');
Result := TFuncHook(HookList.Objects[index]);
end;
function TFuncHookList.GetFuncCount: Integer;
begin
Result := HookList.Count;
end;
end.