封装delphi Hook Api

本文介绍了一种在Windows环境下实现API Hook的技术方案,通过修改内存中的指令指针来替换原有的API函数,从而达到拦截和替换调用的效果。该技术利用了虚拟内存保护机制,并通过临界区确保线程安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

直接看代码

unit uApiHook;

interface

uses
  SysUtils, Windows, TlHelp32;

type
  PJmpCode = ^TJmpCode;
  TJmpCode = packed record
    JmpCode: BYTE;
    Address: Pointer;
    MovEAX: Array [0..2] of BYTE;
  end;

type
  TApiHookInfo = class
  private
    FCS:TRTLCriticalSection;
    FJmpCode: PJmpCode;
    FOldProc: PJmpCode;
    FLoadLib: Boolean;
    FDllHandle: THandle;
    FHookFun: Pointer;
    m_hProc: DWORD;
    FOldPoint: Cardinal;
    FbHook: Boolean;
    procedure SetPageWrite;
    procedure SetPageReadOnly;
  public
    FAddr: Pointer;
    constructor Create;
    destructor Destroy; override;
    function init(ADllName, AFunName: string; ANewFunPointer: Pointer):Boolean;
    procedure Lock;
    procedure UnLock;
    procedure Hook;
    procedure UnHook;
  end;

implementation

{ TApiHookInfo }

procedure TApiHookInfo.SetPageWrite;
begin
  if Win32PlatForm = VER_PLATFORM_WIN32_NT  then //判断是不是NT.
    VirtualProtect(FAddr, $F, PAGE_EXECUTE_READWRITE, FOldPoint);
end;

procedure TApiHookInfo.SetPageReadOnly;
begin
  if Win32PlatForm = VER_PLATFORM_WIN32_NT  then //判断是不是NT.
    VirtualProtect(FAddr, $F, FOldPoint, FOldPoint);
end;

constructor TApiHookInfo.Create;
begin
  InitializeCriticalSection(FCS);
  New(FJmpCode);
  New(FOldProc);
  FLoadLib := False;
  FDllHandle := 0;
  FHookFun := nil;
  FbHook := False;
end;

destructor TApiHookInfo.Destroy;
begin
  if FbHook then
    UnHook;
  if FLoadLib then
    FreeLibrary(FDllHandle);
  Dispose(FJmpCode);
  Dispose(FOldProc);
  DeleteCriticalSection(FCS);
  inherited;
end;

procedure TApiHookInfo.Hook;
var
  dwSize: Cardinal;
begin
  SetPageWrite;
  WriteProcessMemory(m_hProc, FAddr, FJmpCode, 8, dwSize);
  FbHook := True;
  SetPageReadOnly;
end;

function TApiHookInfo.init(ADllName, AFunName: string;
  ANewFunPointer: Pointer):Boolean;
var
  dwSize: DWORD;
begin
        FDllHandle := GetModuleHandle(PChar(ADllName));
        if FDllHandle = 0 then
  begin
    FDllHandle := LoadLibrary(PChar(ADllName));
    if FDllHandle = 0 then
    begin
                        Result := False;
      Exit;
    end
    else
            FLoadLib := True;
  end;
  //函数地址
        FAddr := GetProcAddress(FDllHandle, PChar(AFunName));
        if (FAddr = nil) then
  begin
    Result := False;
    Exit;
  end;
  //当前进程
        m_hProc := GetCurrentProcess();

        if (m_hProc = 0) then
  begin
    Result := False;
    Exit;
  end;
  //读当前进程中函数地址
  SetPageWrite;
  FJmpCode^.JmpCode := $B8;
  FJmpCode^.MovEAX[0] := $FF;
  FJmpCode^.MovEAX[1] := $E0;
  FJmpCode^.MovEAX[2] := 0;
  ReadProcessMemory(m_hProc, FAddr, FOldProc, 8, dwSize);
  FJmpCode^.Address := ANewFunPointer;
  WriteProcessMemory(m_hProc, FAddr, FJmpCode, 8, dwSize);
  SetPageReadOnly;
  Result := True;
end;

procedure TApiHookInfo.Lock;
begin
  EnterCriticalSection(FCS);
end;

procedure TApiHookInfo.UnHook;
var
  dwSize: DWORD;
begin
  SetPageWrite;
  WriteProcessMemory(m_hProc, FAddr, FOldProc, 8, dwSize);
  FbHook := False;
  SetPageReadOnly;
end;

procedure TApiHookInfo.UnLock;
begin
  LeaveCriticalSection(FCS);
end;

end.


使用方法:
var
  g_OpenProcess: TApiHookInfo;

function MyOpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall;
begin
  g_OpenProcess.Lock;
  try
    g_OpenProcess.UnHook;
    try
      //你自己的一些代码
      Result := OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
      //你自己的一些代码
    finally
      g_OpenProcess.Hook;
    end;
  finally
    g_OpenProcess.UnLock;
  end;
end;

procedure HookApi;
begin
  g_OpenProcess.init('kernel32.dll', 'OpenProcess', @MyOpenProcess);
end;

procedure UnHookAPI;
begin
  g_OpenProcess.Free;
end;
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值