程序作用:
在Explorer.exe的窗口接到任何一个鼠标消息时在Explorer.exe进程注入一个线程,该线程显示一个窗体.
程序的问题,如果程序在Explorer.exe还没有接收到有效的鼠标消息之前被关闭,则进程注入不会成功.
启动程序:
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
启动程序的窗口单元.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
function EnableMouseHook:Boolean; stdcall; external 'HookDLL.dll' name 'EnableMouseHook';
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
//启动钩子.
EnableMouseHook;
end;
end.
钩子和线程注入DLL:
library hookDLL;
uses
SysUtils,
Classes,
Hookunit in 'Hookunit.pas',
Unit2 in 'Unit2.pas' {Form2};
{$R *.RES}
//导出函数.
exports EnableMouseHook,DisableMouseHook,CreateImmitThread;
begin
end.
//钩子和线程注入实现单元.
unit Hookunit;
interface
uses Windows,Messages,Controls,Sysutils,Dialogs;
Type
TCreateImmitThread=Procedure;stdcall;
var hHk: HHOOK;//钩子的句柄值。
function MouseHookProc(nCode: Integer;WParam: WPARAM;LParam: LPARAM): LRESULT;stdcall;
//鼠标钩子的回调函数,即用它来处理得到消息后要干什么。
//nCode参数是Hook的标志,一般只关心小于0时。看下面的详细说明
//WParam参数表示鼠标消息的类型
//LParam参数是一个指向 TMOUSEHOOKSTRUCT 结构的指针。结构包含了鼠标消息的状态,我只用了hwnd一个
//即鼠标消息要传递给的窗口句柄。
//返回值如果不是0的话Windows就把这个消息丢掉,其它的程序就不会再收到这个消息了。
//两个函数都是Boolean类型,成功都是返回True
function EnableMouseHook:Boolean; stdcall; export;
function DisableMouseHook:Boolean; stdcall; export;
//创建注入线程.
Procedure CreateImmitThread; stdcall; export;
implementation
uses Classes , Unit2;
procedure HandleEvent(HLib:THandle); stdcall;
var
Msg: TMsg;
MutexHandle:THandle;
begin
//再检查一次全局原子,如果该原是存在,则退出本函数,线程中止.
MutexHandle := windows.GlobalFindAtom('abhjjhsdhjdshjds111');
if MutexHandle <> 0 then
Exit;
MutexHandle:=Windows.GlobalAddAtom('abhjjhsdhjdshjds111');
//添加一个全局原子.
try
//创建一个Form.
Form2:=TForm2.Create(nil);
try
Form2.Show;
//显示Form.
//消息循环.
while True do
begin
//如果Form已经被关闭.
//注意这是和Form.OnClose事件和Form.OnDestroy事件配合使用的.
if Form2=nil then
Break;
//检查消息队列.
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
//如果得到WM_QUIT消息,则中止循环.
if Msg.Message = WM_QUIT then
Break;
//分发消息.
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
finally
//如果Form2还没有被释放.
if Form2<>nil then
Form2.Free;
end;
finally
//释放全局原子对象.
Windows.GlobalDeleteAtom(MutexHandle);
end;
end;
Procedure CreateImmitThread; stdcall;
var
ThreadID:DWORD;
begin
//该函唯一的功能就是创建并启动一个线程.
CreateThread(nil, 0, @HandleEvent, nil, 0, ThreadID);
end;
function MouseHookProc(nCode: Integer;WParam: WPARAM;LParam:LPARAM): LRESULT;stdcall;
var a:Array[0..255] of char;
s:String;
H:THandle;
P:Pointer;
MutexHandle:THandle;
begin
Result:=0;//最好首先给它一个返回值,不然会有警告的!记住这可不是C语言。
//当nCode小于0时表示还有其它的Hook必须把参数传给它。
//此时就要用Api函数CallNextHookEx让它调用下一个Hook!!!当然不用好像也可以。
if nCode < 0 then
Result:=CallNextHookEx(hHk,nCode,wParam,lParam)//参数是现成的,直接用就可以了。
else
begin
GetModuleFileName(0,a,255);
s:=UpperCase(StrPas(a));
if Pos('EXPLORER.EXE',s)>0 then//如果是资源管理器Explorer.EXE.
begin
MutexHandle := windows.GlobalFindAtom('abhjjhsdhjdshjds111');//检查是不存在全局原子
if MutexHandle <> 0 then//如果存在,则表示该窗口已经显示出来了.
exit;
H:=LoadLibrary('HookDLL.dll');//装载需要注入的DLL,其实就是本DLL.
if H<>INVALID_HANDLE_VALUE then
begin
P:=GetProcAddress(H,'CreateImmitThread');//得到注入的函数地址.
if P<>nil then
TCreateImmitThread(P);//执行函数,该函数仅启动一个线程.
end;
end;
end;
end;
function EnableMouseHook:Boolean; stdcall; export;
begin
if hHk = 0 then //为了安全,必须判断一下再设置钩子。
Begin
//第三个参数的Hinstance 在Delphi中有定义,用就可以了。第四个参数必须为0
hHk := SetWindowsHookEx(WH_MOUSE,@MouseHookProc,Hinstance,0);
Result := True;
end
else
Result := False;
end;
function DisableMouseHook:Boolean; stdcall; export;
begin
if hHk <> 0 then //如果有钩子就卸掉它。
begin
UnHookWindowsHookEx(hHk);
hHk := 0;
Result := True;
end
else
Result := False;
end;
end.
注入后线程启动的窗体:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
Close;
end;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//窗口关闭时释放自身.
Action:=caFree;
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
//窗口释放时置Form2为nil
Form2:=nil;
end;
end.