思路:其实比较简单,还是利用DLL,首写跟据API函数OpenProcess与TerminateProcess的结构自已编写两个与这两个API一样的函数,再利用GetProcAddress获取系统的那两个API函数入口地址,最后用WriteProcessMemory将你写的函数的地址替换掉原来系统的函数地址。这样所有调用这两系统API都将先执行你的函数。
如果只Hook其中一个函数比如只hook OpenProcess的话那么任务管理器将不能获取到你的进程信息那么会出错。如果只hook TerminateProcess那样也不行,因为一个进程的句柄在本进程与别的进程中是不一样的,所以如果你不知道自已进程在别人进程中的句柄那么是没办法hook TerminateProcess的。
本例中首先利用OpenProcess获取自已在别的进程中的句柄,然后hook TerminateProcess进程监控,如果发现有程序调用TerminateProcess并且所结束的对象正是自已,那么就给出提示窗口。
------------------------------------------------调用部分
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
procedure StartHook(pid: DWORD); stdcall; external 'hookdll.dll';
procedure EndHook; stdcall; external 'hookdll.dll';
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
StartHook(GetCurrentProcessId);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
EndHook;
end;
end.
-----------------------------------------------------------------------------------------
DLL文件,全部实现都在这里
--------------------- Hookdll.dpr
library Hookdll;
uses
SysUtils,
Classes,
Windows,Dialogs,
unitHook in 'unitHook.pas';
const
HOOK_MEM_FILENAME = 'tmp.hkt';
var
hhk: HHOOK;
Hook: array[0..2] of TNtHookClass;
//内存映射
MemFile: THandle;
startPid: PDWORD; //保存PID
fhProcess: THandle; //保存本进程在远程进程中的句柄
//拦截 OpenProcess
function NewOpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall;
type
TNewOpenProcess = function (dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall;
begin
if startPid^ = dwProcessId then begin
Hook[1].UnHook;
Result := TNewOpenProcess(Hook[1].BaseAddr)(dwDesiredAccess, bInheritHandle, dwProcessId);
fhProcess:=Result;
Hook[1].Hook;
exit;
end;
Hook[1].UnHook;
Result := TNewOpenProcess(Hook[1].BaseAddr)(dwDesiredAccess, bInheritHandle, dwProcessId);
Hook[1].Hook;
end;
function NewTerminateProcess(hProcess: THandle;uExitCode: UINT): BOOL; Stdcall;
type
TNewTerminateProcess = function (hProcess: THandle;uExitCode: UINT): BOOL; Stdcall;
begin
if fhProcess = hProcess then begin
showmessage('不准关闭我!');
result := true;
exit;
end;
Hook[2].UnHook;
Result := TNewTerminateProcess(Hook[2].BaseAddr)(hProcess, uExitCode );
Hook[2].Hook;
end;
procedure InitHook; //安装 Hook
begin
Hook[1] := TNtHookClass.Create('kernel32.dll', 'OpenProcess', @NewOpenProcess);
hook[2] := TNtHookClass.Create('kernel32.dll', 'TerminateProcess', @NewTerminateProcess);
end;
procedure UninitHook; //删除 Hook
var
I: Integer;
begin
for I := 0 to High(Hook) do
begin
FreeAndNil(Hook[I]);
end;
end;
procedure MemShared();
begin
MemFile:=OpenFileMapping(FILE_MAP_ALL_ACCESS,False, HOOK_MEM_FILENAME); //打开内存映射文件
if MemFile = 0 then begin
MemFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
4, HOOK_MEM_FILENAME);
end;
if MemFile <> 0 then
//映射文件到变量
startPid := MapViewOfFile(MemFile,FILE_MAP_ALL_ACCESS,0,0,0);
end;
//传递消息
function HookProc(nCode, wParam, lParam: Integer): Integer; stdcall;
begin
Result := CallNextHookEx(hhk, nCode, wParam, lParam);
end;
//开始HOOK
procedure StartHook(pid: DWORD); stdcall;
begin
startPid^ := pid;
hhk := SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hInstance, 0);
end;
//结束HOOK
procedure EndHook; stdcall;
begin
if hhk <> 0 then
UnhookWindowsHookEx(hhk);
end;
//环境处理
procedure DllEntry(dwResaon: DWORD);
begin
case dwResaon of
DLL_PROCESS_ATTACH: InitHook; //DLL载入
DLL_PROCESS_DETACH: UninitHook; //DLL删除
end;
end;
exports
StartHook, EndHook;
begin
MemShared;
{ 分配DLL程序到 DllProc 变量 }
DllProc := @DllEntry;
{ 调用DLL加载处理 }
DllEntry(DLL_PROCESS_ATTACH);
end.
--------------------------- 单元unitHook.pas
unit unitHook;
interface
uses
Windows, Messages, Classes, SysUtils;
type
//NtHook类相关类型
TNtJmpCode=packed record //8字节
MovEax:Byte;
Addr:DWORD;
JmpCode:Word;
dwReserved:Byte;
end;
TNtHookClass=class(TObject)
private
hProcess:THandle;
NewAddr:TNtJmpCode;
OldAddr:array[0..7] of Byte;
ReadOK:Boolean;
public
BaseAddr:Pointer;
constructor Create(DllName,FuncName:string;NewFunc:Pointer);
destructor Destroy; override;
procedure Hook;
procedure UnHook;
end;
implementation
//==================================================
//NtHOOK 类开始
//==================================================
constructor TNtHookClass.Create(DllName: string; FuncName: string;NewFunc:Pointer);
var
DllModule:HMODULE;
dwReserved:DWORD;
begin
//获取模块句柄
DllModule:=GetModuleHandle(PChar(DllName));
//如果得不到说明未被加载
if DllModule=0 then DllModule:=LoadLibrary(PChar(DllName));
//得到模块入口地址(基址)
BaseAddr:=Pointer(GetProcAddress(DllModule,PChar(FuncName)));
//获取当前进程句柄
hProcess:=GetCurrentProcess;
//指向新地址的指针
NewAddr.MovEax:=$B8;
NewAddr.Addr:=DWORD(NewFunc);
NewAddr.JmpCode:=$E0FF;
//保存原始地址
ReadOK:=ReadProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved);
//开始拦截
Hook;
end;
//释放对象
destructor TNtHookClass.Destroy;
begin
UnHook;
CloseHandle(hProcess);
inherited;
end;
//开始拦截
procedure TNtHookClass.Hook;
var
dwReserved:DWORD;
begin
if (ReadOK=False) then Exit;
//写入新的地址
WriteProcessMemory(hProcess,BaseAddr,@NewAddr,8,dwReserved);
end;
//恢复拦截
procedure TNtHookClass.UnHook;
var
dwReserved:DWORD;
begin
if (ReadOK=False) then Exit;
//恢复地址
WriteProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved);
end;
end.