📄 unitwjshook.bak
字号:
unit UnitWJSHook;
interface
uses classes,Windows,messages;
type
PPointer = ^Pointer;
TImportCode = packed record
JumpInstruction: Word; // should be $25FF 即 FF 25
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);
//if IsBadReadPtr(NT,SizeOf(TImageNtHeaders)) then exit;
//找出这个模块调用了其它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 + -