当前位置:首页 > Windows程序 > 正文

实现拦截API的钩子(Hook)

2021-03-22 Windows程序

道理不多讲,简单说就是将系统API的跳转地址,替换为我们自己写的API的地址,所以要求我们自定义的API函数要和被拦截的API有相同的参数。在用完后,记得恢复。

因为要挂全局的钩子,所以Hook的部分,做成DLL。   源码下载

Hook.DLL主工程文件代码

[delphi] view plaincopy

 

library Hook;  

  

uses  

  SysUtils,  

  Windows,  

  Classes,  

  ApiDefine in ‘ApiDefine.pas‘,  

  APIHook in ‘APIHook.pas‘;  

  

{$R *.res}  

var  

  HookHandle: HHook;  

  

function HookProc(code:Integer;wparam:WPARAM;lparam:LPARAM):LRESULT;stdcall;  

begin  

  Result := CallNextHookEx(HookHandle,code,wparam,lparam);  

end;  

  

procedure SetHook;stdcall;  

begin  

  HookHandle := SetWindowsHookEx(WH_GETMESSAGE,@HookProc,HInstance,0);  

end;  

  

procedure StopHook;stdcall;  

begin  

  UnhookWindowsHookEx(HookHandle);  

end;  

  

exports  

  SetHook name ‘SetHook‘,  

  StopHook name ‘StopHook‘;  

  

{已启动就挂上,修改API函数指向}  

begin  

  API_Hook;  

end.  

APIHook单元,这个单元实现对API地址的替换

[c-sharp] view plaincopy

 

unit APIHook;  

  

interface  

  

uses  

  Windows, SysUtils, Classes;  

  

type  

  //引入表入口数据结构  

  Image_Import_Entry = packed record  

    OriginalFirstThunk:DWORD;  

    TimeDateStamp:DWORD;  

    ForwarderChain:DWORD;  

    Name:DWORD;  

    FirstThunk:DWORD;  

  end;  

  PImage_Import_Entry = ^Image_Import_Entry;  

  TImportCode = packed record  

    JmpCode: Word;  

    AddressOfPFun: PPointer;  

  end;  

  PImportCode = ^TImportCode;  

  

  function GetFunTrueAddress(Code:Pointer):Pointer;  

  function ReplaceFunAddress(oldfun:Pointer;newfun:Pointer):Integer;  

  

implementation  

  

//获得实际地址  

function GetFunTrueAddress(Code: Pointer): Pointer;  

var  

   func: PImportCode;  

begin  

   Result := Code;  

   if Code = nil then exit;  

   try  

      func := code;  

      if (func.JmpCode = $25FF) then  

      begin  

         Result := func.AddressOfPFun^;  

      end;  

   except  

      Result := nil;  

   end;  

end;  

  

//替换地址  

function ReplaceFunAddress(oldfun:Pointer;newfun:Pointer): Integer;  

var  

   IsDone: TList;  

   function ReplaceAddressInModule(hModule: THandle; OldFunc, NewFunc: Pointer): Integer;  

   var  

      DosHeader: PImageDosHeader;  

      NTHeader: PImageNTHeaders;  

      ImportDesc: PImage_Import_Entry;  

      RVA: DWORD;  

      Func: ^Pointer;  

      DLL: string;  

      f: Pointer;  

      written: DWORD;  

   begin  

      Result := 0;  

      DosHeader := Pointer(hModule);  

      //已经找过,则退出  

      if IsDone.IndexOf(DosHeader) >= 0 then exit;  

      IsDone.Add(DosHeader);  

  

      oldfun := GetFunTrueAddress(OldFunc);  

  

      if IsBadReadPtr(DosHeader, SizeOf(TImageDosHeader)) then exit;  

      if DosHeader.e_magic <> IMAGE_DOS_SIGNATURE then exit;  

      NTHeader := Pointer(Integer(DosHeader) + DosHeader._lfanew);  

      //引入表的虚拟地址  

      RVA := NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;  

  

      if RVA = 0 then exit;  

      ImportDesc := pointer(integer(DosHeader) + RVA);  

      while (ImportDesc^.Name <> 0) do  

      begin  

        //引入文件名  

         DLL := PChar(Integer(DosHeader) + ImportDesc^.Name);  

         //获得该DLL的句柄,然后递归查找  

         ReplaceAddressInModule(GetModuleHandle(PChar(DLL)), oldfun, newfun);  

         //引入函数入口  

         Func := Pointer(Integer(DOSHeader) + ImportDesc.FirstThunk);  

         //如果函数指针不为空  

         while Func^ <> nil do  

         begin  

           //取得真是地址  

            f := GetFunTrueAddress(Func^);  

            //如果和我们要拦截的Api函数地址一样  

            if f = oldfun then  

            begin  

              //替换成我们自己的Api地址  

               WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written);  

               if Written > 0 then Inc(Result);  

            end;  

            //继续找  

            Inc(Func);  

         end;  

         Inc(ImportDesc);  

      end;  

   end;  

  

begin  

   IsDone := TList.Create;  

   try  

     //GetModuleHandle,参数nil,为获取自身的模块句柄  

      Result := ReplaceAddressInModule(GetModuleHandle(nil), oldfun, newfun);  

   finally  

      IsDone.Free;  

   end;  

end;  

end.  

ApiDefine单元,,这里实现我们自定义的API

[delphi] view plaincopy

 

unit ApiDefine;  

  

interface  

  

uses  

  Windows, SysUtils, Classes,Messages,APIHook,ShellAPI;  

  

  procedure API_Hook;  

  procedure API_UnHook;  

  

implementation  

  

//自定义Api的类型  

type  

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/65391.html