📄 复件 unitwjshook.pas
字号:
unit UnitWJSHook;
interface
uses classes,Windows,messages;
type
PPointer = ^Pointer;
TImportCode = packed record
JumpInstruction: Word;
AddressOfPointerToFunction: PPointer;
end;
PImportCode = ^TImportCode;
PImage_Import_Entry = ^Image_Import_Entry;
Image_Import_Entry = record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
Name: DWORD;
LookupTable: DWORD;
end;
HookStruct = record
OldFunction,NewFunction:Pointer;
end;
function FinalFunctionAddress(Code: Pointer): Pointer;
procedure HookAPIFunction(hook:HookStruct);
procedure UnHookAPIFunction(hook:HookStruct);
implementation
function FinalFunctionAddress(Code: Pointer): Pointer;
{取函数的实际地址
如果函数的第一个指令是Jmp指令,则取出它的跳转地址(实际地址)}
Var
func: PImportCode;
begin
Result:=Code;
if Code=nil then exit;
try
func:=code;
if (func.JumpInstruction=$25FF) then begin
{指令二进制码FF 25 汇编指令jmp [...]}
Result:=func.AddressOfPointerToFunction^;
end;
except
Result:=nil;
end;
end;
function PatchAddressInModule(BeenDone:Tlist;hModule: THandle; OldFunc,NewFunc: Pointer):integer;
Var
Dos: PImageDosHeader;
NT: PImageNTHeaders;
ImportDesc: PImage_Import_Entry;
rva: DWORD;
Func: PPointer;
DLL: String;
f: Pointer;
written: DWORD;
begin
Result:=0;
if hModule=0 then exit;
Dos:=Pointer(hModule);
{如果这个模块已经处理过,就退出。BeenDone包含已处理的模块。}
if BeenDone.IndexOf(Dos)>=0 then exit;
BeenDone.Add(Dos);{把模块名加入BeenDone}
OldFunc:=FinalFunctionAddress(OldFunc);{取函数的实际地址}
{如果对这个模块没有读的权限,则退出。}
if IsBadReadPtr(Dos,SizeOf(TImageDosHeader)) then exit;
{如果这个模块不是以'MZ'开头,表明不是EXE、DLL,则退出。}
if Dos.e_magic<>IMAGE_DOS_SIGNATURE then exit;{IMAGE_DOS_SIGNATURE='MZ'}
{windows的PE文件(EXE、DLL)分为DOS、Windows两个部分。
._lfanew是PE文件中Windows部分的起始地址。}
NT :=Pointer(Integer(Dos) + dos._lfanew);
{找出这个模块调用了其它DLL的哪些函数}
RVA:=NT^.OptionalHeader. {模块windows部分的第三小部分OptionalHeader}
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].{中的函数引用表}
VirtualAddress;{的入口地址}
if RVA=0 then exit;{如果没有调用,则退出。}
ImportDesc := pointer(DWORD(Dos)+RVA);{求函数引用表的绝对地址,RVA只是相对地址}
While (ImportDesc^.Name<>0) do{历遍所有被引用的DLL模块}
begin
DLL:=PChar(DWORD(Dos)+ImportDesc^.Name);{被当前模块引用的DLL模块名字}
{嵌套调用本函数,历遍DLL相互交差引用函数的网状结构}
{把这个被引用的DLL当作当前模块,重复以上过程}
PatchAddressInModule(BeenDone,GetModuleHandle(PChar(DLL)),OldFunc,NewFunc);
{找出被引用的DLL模块的每一个功能函数}
Func:=Pointer(DWORD(DOS)+ImportDesc.LookupTable);
While Func^<>nil do {历遍被引用的DLL模块的所有功能函数}
begin
f:=FinalFunctionAddress(Func^);{取实际地址}
if f=OldFunc then {如果函数实际地址就是所要找的地址}
WriteProcessMemory(GetCurrentProcess,Func,@NewFunc,4,written);{把新函数地址覆盖它}
If Written>0 then Inc(Result);
Inc(Func);{下一个功能函数}
end;
Inc(ImportDesc);{下一个DLL模块}
end;
end;
procedure HookAPIFunction(hook:HookStruct);
Var
BeenDone: TList;
begin
if (hook.NewFunction=nil)or(hook.NewFunction=nil)then exit;
BeenDone:=TList.Create; {用于存放所有模块的名字}
try
PatchAddressInModule(BeenDone,GetModuleHandle(nil),hook.OldFunction,hook.NewFunction);
finally
BeenDone.Free;
end;
end;
procedure UnHookAPIFunction(hook:HookStruct);
Var
BeenDone: TList;
begin
if (hook.NewFunction=nil)or(hook.NewFunction=nil)then exit;
BeenDone:=TList.Create;{用于存放所有模块的名字}
try
PatchAddressInModule(BeenDone,GetModuleHandle(nil),hook.NewFunction,hook.OldFunction);
finally
BeenDone.Free;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -