?? unitwjshook.pas
字號:
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.OldFunction=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.OldFunction=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 + -