⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 复件 unitwjshook.pas

📁 在delphi中实现windows核心编程.原书光盘代码核心编程.原书光盘代码
💻 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 + -