windows HOOK在delphi开发环境下的使用方法
2010-04-06 14:17
597 查看
要拦截的API如下:
MessageBoxA、MessageBoxW、MessageBeep和OpenProcess。
首先,大家都知道要在整个系统范围中拦截,需要使用Dll来完成。现在我们打开Delphi2007,新建一个Dll工程:hookDll。需要说明的是,Delphi是完全面向对象的编程语言,所以我们不要浪费,这个Dll打算用类的方式完成。于是,在新建的DLL工程中在添加一个UnitPas,命名为unitHook,用来写拦截类的处理。unitHook.pas中的代码如下:
这样,我们用来hookAPI的Dll就完工了。在Dll中,我们还使用到了内存映射,用来实现在拦截全局时的内存共享,如这个例子中需要保存调用此hook的进程句柄,以防止通过任务管理器关闭示例程序。
编译生成hookdll.dll文件,就可以使用了。现在我们再来建立一个测试用的程序。
如附图所示,画3个按钮,分别为"Hook"、"UnHook"、"MessageBox",前两个用来安装和删除钩子,第三个用来显示一个消息框,你将会看到被Hook后的情况。测试工程的代码如下:[/code]
.............
//环境处理
procedureDllEntry(dwResaon:DWORD);
begin
casedwResaonof
DLL_PROCESS_ATTACH:InitHook;//DLL载入
DLL_PROCESS_DETACH:UninitHook;//DLL删除
end;
end;
............
begin
MemShared;
{分配DLL程序到DllProc变量}
DllProc:=@DllEntry;
{调用DLL加载处理}
DllEntry(DLL_PROCESS_ATTACH);
end.
[/code]
[/code]
MessageBoxA、MessageBoxW、MessageBeep和OpenProcess。
首先,大家都知道要在整个系统范围中拦截,需要使用Dll来完成。现在我们打开Delphi2007,新建一个Dll工程:hookDll。需要说明的是,Delphi是完全面向对象的编程语言,所以我们不要浪费,这个Dll打算用类的方式完成。于是,在新建的DLL工程中在添加一个UnitPas,命名为unitHook,用来写拦截类的处理。unitHook.pas中的代码如下:
unitunitHook; interface uses Windows,Messages,Classes,SysUtils; type //NtHook类相关类型 TNtJmpCode=packedrecord//8字节 MovEax:Byte; Addr:DWORD; JmpCode:Word; dwReserved:Byte; end; TNtHookClass=class(TObject) private hProcess:THandle; NewAddr:TNtJmpCode; OldAddr:array[0..7]ofByte; ReadOK:Boolean; public BaseAddr:Pointer; constructorCreate(DllName,FuncName:string;NewFunc:Pointer); destructorDestroy;override; procedureHook; procedureUnHook; end; implementation //================================================== //NtHOOK类开始 //================================================== constructorTNtHookClass.Create(DllName:string;FuncName:string;NewFunc:Pointer); var DllModule:HMODULE; dwReserved:DWORD; begin //获取模块句柄 DllModule:=GetModuleHandle(PChar(DllName)); //如果得不到说明未被加载 ifDllModule=0thenDllModule:=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; //释放对象 destructorTNtHookClass.Destroy; begin UnHook; CloseHandle(hProcess); inherited; end; //开始拦截 procedureTNtHookClass.Hook; var dwReserved:DWORD; begin if(ReadOK=False)thenExit; //写入新的地址 WriteProcessMemory(hProcess,BaseAddr,@NewAddr,8,dwReserved); end; //恢复拦截 procedureTNtHookClass.UnHook; var dwReserved:DWORD; begin if(ReadOK=False)thenExit; //恢复地址 WriteProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved); end; end.
至此,unitHook.pas的代码OK了,其中加了详细的注释,在此就不再多做解释。现在切换到Dll的代码页,写入以下代码:
libraryhookdll;
uses
SysUtils,Windows,
Classes,
unitHookin'unitHook.pas';
{$R*.res}
const
HOOK_MEM_FILENAME='tmp.hkt';
var
hhk:HHOOK;
Hook:array[0..3]ofTNtHookClass;
//内存映射
MemFile:THandle;
startPid:PDWORD;//保存PID
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}
//拦截MessageBoxA
functionNewMessageBoxA(_hWnd:HWND;lpText,lpCaption:PAnsiChar;uType:UINT):Integer;stdcall;
type
TNewMessageBoxA=function(_hWnd:HWND;lpText,lpCaption:PAnsiChar;uType:UINT):Integer;stdcall;
begin
lpText:=PAnsiChar('已经被拦截MessageBoxA');
Hook[0].UnHook;
Result:=TNewMessageBoxA(Hook[0].BaseAddr)(_hWnd,lpText,lpCaption,uType);
Hook[0].Hook;
end;
//拦截MessageBoxW
functionNewMessageBoxW(_hWnd:HWND;lpText,lpCaption:PWideChar;uType:UINT):Integer;stdcall;
type
TNewMessageBoxW=function(_hWnd:HWND;lpText,lpCaption:PWideChar;uType:UINT):Integer;stdcall;
begin
lpText:='已经被拦截MessageBoxW';
Hook[2].UnHook;
Result:=TNewMessageBoxW(Hook[2].BaseAddr)(_hWnd,lpText,lpCaption,uType);
Hook[2].Hook;
end;
//拦截MessageBeep
functionNewMessageBeep(uType:UINT):BOOL;stdcall;
type
TNewMessageBeep=function(uType:UINT):BOOL;stdcall;
begin
Result:=True;
end;
//拦截OpenProcess,防止关闭
functionNewOpenProcess(dwDesiredAccess:DWORD;bInheritHandle:BOOL;dwProcessId:DWORD):THandle;stdcall;
type
TNewOpenProcess=function(dwDesiredAccess:DWORD;bInheritHandle:BOOL;dwProcessId:DWORD):THandle;stdcall;
begin
ifstartPid^=dwProcessIdthenbegin
result:=0;
Exit;
end;
Hook[3].UnHook;
Result:=TNewOpenProcess(Hook[3].BaseAddr)(dwDesiredAccess,bInheritHandle,dwProcessId);
Hook[3].Hook;
end;
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}
//安装APIHook
procedureInitHook;
begin
Hook[0]:=TNtHookClass.Create('user32.dll','MessageBoxA',@NewMessageBoxA);
Hook[1]:=TNtHookClass.Create('user32.dll','MessageBeep',@NewMessageBeep);
Hook[2]:=TNtHookClass.Create('user32.dll','MessageBoxW',@NewMessageBoxW);
Hook[3]:=TNtHookClass.Create('kernel32.dll','OpenProcess',@NewOpenProcess);
end;
//删除APIHook
procedureUninitHook;
var
I:Integer;
begin
forI:=0toHigh(Hook)do
begin
FreeAndNil(Hook[I]);
end;
end;
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}
//内存映射共想
procedureMemShared();
begin
MemFile:=OpenFileMapping(FILE_MAP_ALL_ACCESS,False,HOOK_MEM_FILENAME);//打开内存映射文件
ifMemFile=0thenbegin//打开失败则衉c2建内存映射文件
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
4,HOOK_MEM_FILENAME);
end;
ifMemFile<>0then
//映射文件到变量
startPid:=MapViewOfFile(MemFile,FILE_MAP_ALL_ACCESS,0,0,0);
end;
//传递消息
functionHookProc(nCode,wParam,lParam:Integer):Integer;stdcall;
begin
Result:=CallNextHookEx(hhk,nCode,wParam,lParam);
end;
//开始HOOK
procedureStartHook(pid:DWORD);stdcall;
begin
startPid^:=pid;
hhk:=SetWindowsHookEx(WH_CALLWNDPROC,HookProc,hInstance,0);
end;
//结束HOOK
procedureEndHook;stdcall;
begin
ifhhk<>0then
UnhookWindowsHookEx(hhk);
end;
//环境处理
procedureDllEntry(dwResaon:DWORD);
begin
casedwResaonof
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.
这样,我们用来hookAPI的Dll就完工了。在Dll中,我们还使用到了内存映射,用来实现在拦截全局时的内存共享,如这个例子中需要保存调用此hook的进程句柄,以防止通过任务管理器关闭示例程序。
编译生成hookdll.dll文件,就可以使用了。现在我们再来建立一个测试用的程序。
如附图所示,画3个按钮,分别为"Hook"、"UnHook"、"MessageBox",前两个用来安装和删除钩子,第三个用来显示一个消息框,你将会看到被Hook后的情况。测试工程的代码如下:[/code]
unitFMain;
interface
uses
Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs,StdCtrls;
type
TfrmMain=class(TForm)
btnHook:TButton;
btnUnhook:TButton;
Button1:TButton;
procedurebtnHookClick(Sender:TObject);
procedurebtnUnhookClick(Sender:TObject);
procedureButton1Click(Sender:TObject);
procedureFormCreate(Sender:TObject);
private
{Privatedeclarations}
public
{Publicdeclarations}
end;
var
frmMain:TfrmMain;
procedureStartHook(pid:DWORD);stdcall;external'hookdll.dll';
procedureEndHook;stdcall;external'hookdll.dll';
implementation
{$R*.dfm}
procedureTfrmMain.btnHookClick(Sender:TObject);
begin
StartHook(GetCurrentProcessId);
end;
procedureTfrmMain.btnUnhookClick(Sender:TObject);
begin
EndHook;
end;
procedureTfrmMain.Button1Click(Sender:TObject);
begin
MessageBox(0,'abdfadfasdf',nil,0);
end;
procedureTfrmMain.FormCreate(Sender:TObject);
begin
end;
end.
完成后运行,先不点击"hook"按钮,直接点击MessageBox,你会发现现在已经被拦截了。为什么我们还没有安装钩子就被拦截了呢?程序出错了吗?呵呵。当然没有出错。反过来看看DLL中的一处代码:
//环境处理
procedureDllEntry(dwResaon:DWORD);
begin
casedwResaonof
DLL_PROCESS_ATTACH:InitHook;//DLL载入
DLL_PROCESS_DETACH:UninitHook;//DLL删除
end;
end;
............
begin
MemShared;
{分配DLL程序到DllProc变量}
DllProc:=@DllEntry;
{调用DLL加载处理}
DllEntry(DLL_PROCESS_ATTACH);
end.
个人觉得这篇文章极其经典,我一看跟着走了一遍,钩子马上就给会了,其实也很简单。。。。。。
[/code]
[/code]
相关文章推荐
- Delphi、MS SQL Server开发环境下存储过程的使用
- android开发环境 国内镜像 及Android SDK manager使用国内服务器方法
- C#脱离Halcon编程开发环境使用方法
- Linux开发环境搭建与使用——ubuntu物理机安装方法:U盘安装
- (附) Hyperledger Fabric在CentOS 7.2 64位系统开发环境搭建——docker无法使用 解决方法
- 使用HTML界面的Delphi开发环境建立
- STM32串口通信中使用printf发送数据配置方法 开发环境 Keil
- Java web开发使用eclipse环境时需要安装的插件Database explorer 以及servers 的方法
- STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK)
- Linux开发环境搭建与使用——ubuntu物理机安装方法:wubi
- 从头搭建imx6ull开发环境(uboot、内核编译及烧入、mfgtools详细使用方法)
- C#脱离Halcon编程开发环境使用方法
- 在windows开发环境中,java代码中使用linux格式路径的方法需要注意的问题
- Linux开发环境搭建与使用——ubuntu物理机安装方法-wubi
- GSL安装使用方法MinGW 、 VC、Borland C++ Builder、Windows开发环境下的使用
- 【imx6ul】从头搭建imx6ul开发环境(uboot、内核编译及烧入、mfgtools详细使用方法)
- 从头搭建imx6ul开发环境(uboot、内核编译及烧入、mfgtools详细使用方法)
- NEC开发环境的使用方法
- JSP开发:Session对象使用环境及主要方法
- STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK)