利用HOOK技术做自己的系统锁
文/图 Zorro
===================================
本文利用Delphi工具使用Hook技术来做一个自己的系统锁。我们要实现锁定系统的功能,主要是锁定键盘上的几个组合键,同时设置程序窗体最大化。这通过钩子(Hook)就能实现!钩子是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理窗口消息或特定事件。
钩子分为系统钩子和线程钩子,线程钩子用于监视指定线程的事件消息,如一些QQ木马,它们主要监视QQ进程。系统钩子监视系统中的所有线程的事件消息,如我们要实现系统锁功能就要监视整个系统消息并做出处理。因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库(DLL) 中。编写Hook.Dll
下面我们通过系统锁这个实例,来看一下键盘/鼠标钩子的安装与卸载。
单击Delphi菜单“File→New→Other”,选择DLL Wizard,新建一个DLL工程,其主要代码如下。
var
hHk,:HHOOK;
KB:PKBDLLHOOKSTRUCT;
// 结构体,记录按键信息
function keyHookProc(nCode: Integer;WParam: WPARAM;LParam: LPARAM): LRESULT;stdcall; //键盘钩子回调函数
var
k:integer;
begin
if nCode<0 then
Result:= CallNextHookEx(hHk,nCode,WParam,LParam)
else
begin
k:=0;
if (WParam=WM_KEYDOWN) or (WParam=WM_SYSKEYDOWN) then
//键盘按下
begin
KB:=PKBDLLHOOKSTRUCT(Lparam);
if ((KB^.vkCode=VK_F4) and (GetAsyncKeyState(VK_MENU)<0)) then
//屏蔽ALT+F4
k:=1;
if ((KB^.vkCode=VK_TAB) and (GetAsyncKeyState(VK_MENU)<0))
then //屏蔽ALT+TAB
k:=1;
if ((KB^.vkCode=VK_LWIN) or (KB^.vkCode=VK_RWIN)) then
k:=1; //屏蔽Win键
end;
if k=1 then
Result:=1 //吃掉消息
else
Result:= CallNextHookEx(hHk,nCode,WParam,LParam);
//向下传递消息
end;
end;function sethook:Boolean;stdcall;export;
//安装钩子
begin
hHk := SetWindowsHookEx(13,@keyHookProc,HInstance,0);
Result := True;
end;function endhook:Boolean; stdcall; export;
//卸载钩子
begin
UnHookWindowsHookEx(hHk);
hHk := 0;
Result := True;
end;exports //导出两个函数,供外部程序调用
sethook,
endhook;我们在一个DLL里安装两个不同类型的钩子,它们属于不同类型,不会引起冲突。导出的两个函数sethook和endhook供主程序调用。我们先看安装钩子使用的API函数SetWindowsHookEx,其原型如下。
HHOOK SetWindowsHookEx(
int idHook,
//钩子类型,我们这里使用了WH_MOUSE和WH_KEYBOARD
HOOKPROC lpfn,
//钩子子程的地址指针(指定类型的Hook监视的事件发生时,系统就调用与这个Hook关联的Hook链的开头的Hook子程,Hook子程负责处理这些消息
HINSTANCE hMod,
//应用程序实例的句柄
DWORD dwThreadId
//与安装的钩子子程相关联的线程的标识符,我们使用的是全局钩子,所以设置为0
);
钩子子程也就是回调函数原型,具体如下。LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)
其中参数wParam和lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode包含有关消息本身的信息,比如是否从消息队列中移出。
我们可以在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx把钩子信息传递给钩子链的下一个钩子函数。CallNextHookEx的原型如下。LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam )
我们也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。如我们在鼠标钩子回调函数中直接设置“RESULT:=1”吃掉消息,在键盘钩子回调函数中屏蔽“ALT+F4”等一些功能键。
需要特别指出的是,在WinNT操作系统下,屏蔽“ALT+CTRL+DEL”功能键的时候,需要DLL远程注入,实现有一定难度。不过我们可以在主程序中设置一个Timer,监视任务管理器,一旦启动就将其关闭,只需几行代码就可以实现,这也算是一种笨方法!系统锁主程序
系统锁主程序的界面如图1所示,主要组件有一个timer组件,一个Tedit和Tbuuton,tpannel以及一个Image。把Button1的default属性设置为true。主要代码如下。
图1
unit Unit1;
……………..
function sethook:BOOLEAN;external hook.dll;
//声明DLL导出函数
function endhook:BOOLEAN;external hook.dll;procedure TForm1.Button1Click(Sender: TObject);
var
pass:string;
begin
pass:=trim(edit1.Text);
if pass=zorro then
begin
endhook(); //卸载钩子
ShowWindow(TaskBarhd,SW_RESTORE); //显示任务栏
close;
end
else
begin
MessageDlgPos(密码错误,测试密码
"zorro",mtError,mbOKcancel,0 ,Panel1.Left,panel1.Top);
end;
end;procedure TForm1.FormActivate(Sender: TObject);
var
rel2:boolean;
begin
SetWindowPos(form1.Handle,HWND_TOPMOST,
form1.Left,form1.Top,form1.Width,form1.Height,0);
//窗体始终在前
form1.Width:=screen.Width;
//设置窗体全屏
form1.Height:=screen.Height;
Image1.Width:=form1.Width;
//设置Image1大小为窗体大小
Image1.Height:=form1.Height;
Panel1.Left:=(form1.Width - Panel1.Width) div 2;
//居中显示
Panel1.Top:=(form1.Height-Panel1.Width) div 2;TaskBarhd:=FindWindow(Shell_traywnd,);
EnableWindow(TaskBarhd,true);
//禁用任务管理器
ShowWindow(TaskBarhd,SW_HIDE);
//隐藏任务栏
rel2:=sethook(); //安装钩子
end;procedure TForm1.Timer1Timer(Sender: TObject);
var
rect:Trect;
hdman:Thandle;
begin
hdman:=FindWindow(NIL,Windows 任务管理器);
if hdman<>0 then
PostMessage(hdman, WM_CLOSE, 0, 0);
//关闭任务管理器
//将鼠标始终限制在Panel1坐标范围内
rect.Left:=Panel1.Left;
rect.Top:=Panel1.Top;
rect.Right:=Panel1.Left+Panel1.Width;
rect.Bottom:=Panel1.Top+Panel1.Height;
clipcursor(@rect);
end;需要注意使用clipcursor函数锁定鼠标时,如果“Ctrl+alt+delete”锁屏就会失效,所以要在Timer中实时设置。我们可以给程序加上自动启动功能和登录限制,超过限制次数就关机,呵呵,这样就变成了一个小小的恶作剧程序。
这个程序主要利用了HOOK实现锁屏功能,程序还不完善,应该有设置密码的功能,这个就交给大家来完成吧!最后,不知道这个系统锁能否破解,我是没能破解,大家可以试试
补充:综合编程 , 安全编程 ,