小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

淺議VisualBasic.NET中HOOK的應用...

 ShangShujie 2007-05-29
作者: CQFZ
出處: 天極BLOG
本文不是講解Hook原理的文章,僅是討論一下在vb.net如何調(diào)用Hook功能,以及vb.net中API使用的變化問題。

  由于Hook種類較多,本文中以最常用的鍵盤Hook為例進行分析。

  一、先來看一下在vb中是如何實現(xiàn)的

  截的是空格鍵。表現(xiàn)的目標是:一個form,上面有一個textbox,不管焦點是否落在textbox里,按空格鍵,不會在textbox中輸入一個空格,而是變成在textbox中寫入一句話:“HOOK成功!”

  1.在一個Module中寫入下列代碼:

  調(diào)用的API的申明:

Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long

  函數(shù)說明:本函數(shù)是用于啟動Hook設置。

  idHook是Hook的類型,即處理的消息類型。

  Lpfn是Hook子程(函數(shù)或過程)的地址指針。如果dwThreadId參數(shù)為0或是一個由別的進程創(chuàng)建的線程的標識,lpfn必須指向DLL中的Hook子程。除此以外,lpfn可以指向當前進程的一段Hook子程代碼(我們利用的就是這個性質(zhì))。

  hMod是應用程序?qū)嵗木浔?,標識包含lpfn所指的子程的DLL。如果dwThreadId 標識當前進程創(chuàng)建的一個線程,而且子程代碼位于當前進程,hMod必須為NULL。

  dwThreadId是與安裝Hook子程相關聯(lián)的線程的標識符,如果為0,Hook子程與所有的線程關聯(lián)。 返回值:函數(shù)成功則返回Hook子程的句柄,失敗返回NULL。

Declare Function UnHookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long

  函數(shù)說明: 本函數(shù)是解除Hook之用。hHook是Hook函數(shù)的句柄。

Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long

  函數(shù)說明:本函數(shù)的作用是將當前Hook鏈中的Hook信息傳遞給下一個Hook。

  hHook是當前Hook的句柄,一個應用程序接收這個句柄,作為先前調(diào)用SetWindowsHookEx函數(shù)的結(jié)果。

  nCode指的是傳遞到當前Hook過程的Hook代碼,下一個Hook過程使用這段代碼去決定如何處理Hook信息。

  wParam指傳遞給當前Hook過程的wParam值,它的具體含義是由當前Hook鏈中的相關Hook的類型決定的。

  lParam指傳遞給當前Hook過程的lParam值,它的具體含義是由當前Hook鏈中的相關Hook的類型決定的。

  2. 定義的常量是:

Public hnextHookproc As Long

Public Const WH_KEYBOARD = 2 ‘這個是表明Hook的種類是鍵盤Hook

Public Const PM_KEY_SPACE = &H20 ‘空格鍵

  3.代碼段

Public Sub UnHookKBD()  ‘解鍵盤HOOK函數(shù)
 If hnextHookproc <> 0 Then
  UnHookWindowsHookEx hnextHookproc
  hnextHookproc = 0
 End If
End Sub


Public Function EnableKBDHook() ‘設置鍵盤HOOK
 If hnextHookproc <> 0 Then
  Exit Function
 End If

 hnextHookproc = SetWindowsHookEx(WH_KEYBOARD, AddressOf MyKBHFunc, App.hInstance, 0)

 If hnextHookproc <> 0 Then
  EnableKBDHook = hnextHookproc
 End If
End Function


Public Function MyKBHFunc(ByVal iCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

 MyKBHFunc = 0
 If iCode < 0 Then
  MyKBHFunc = CallNextHookEx(hnextHookproc, iCode, wParam, lParam)
  Exit Function
 End If

 If wParam = PM_KEY_SPACE Then ‘‘偵測 有沒有按到空格鍵
  MyKBHFunc = 1
 ‘加入自己的代碼,用于表明響應
  form1.text1.text=”Hook成功!”
 End If
End Function

  4.在Form中的代碼很簡單:

Private Sub Form_Load()
 Call EnableKBDHook
End Sub

Private Sub Form_Unload(Cancel As Integer)
 Call UnHookKBD
End Sub
現(xiàn)在在form窗體狀態(tài)下,敲空格鍵,就會響應你在MyKBHFunc函數(shù)中寫的代碼了。

  1. 新建一個module,先寫一下API的聲明:

Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As HookType, ByVal lpfn As HOOKPROC, ByVal hmod As Integer, ByVal dwThreadId As Integer) As Integer

Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Integer) As Integer

Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Integer, ByVal ncode As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

  和上面VB6里的聲明比一下,你發(fā)現(xiàn)了什么?是不是數(shù)據(jù)類型發(fā)生了變 化?integer代替了long。這個好理解,因為vb.net中integer定義為32位(4字節(jié))的整數(shù),值的范圍是-231到231(首位是符 號位),這與vb6中l(wèi)ong的定義是一致的,因此,我們必須做一下這樣的轉(zhuǎn)換。

  等等,還有一個變化,就是SetWindowsHookEx的參數(shù)lpfn的類型變成了HOOKPROC,那……那是什么意思。噢,wait,我再補一句聲明先:

Public Delegate Function HOOKPROC(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

  看出來什么了嗎?HOOKPROC其實就是一個函數(shù)聲明,但是前面有一個Delegate(委托)是什么意思?為什么在vb.net中不能用integer表示lpfn的類型了呢?我們回頭看一下vb6中調(diào)用API的句子:

hnextHookproc = SetWindowsHookEx(WH_KEYBOARD, AddressOf MyKBHFunc, App.hInstance, 0)

  Lpfn在這里被表示為AddressOf MyKBHFunc,即說明Hook發(fā)生作用時,調(diào)用的子程是MyKBHFunc。也就是說lpfn表示的是函數(shù)或過程的地址。在vb6中用long類型就可以記錄下函數(shù)或過程的地址。

在vb.net中,有了一點小變化嘍,AddressOf 運算符創(chuàng)建的是一個指向指定的子程的子程委托。當指定的子程是一個實例方法時,子程委托同時引用實例和方法,以便當調(diào)用該子程委托時,調(diào)用指定實例的指定 方法。AddressOf 運算符可以用作委托構造函數(shù)的操作數(shù),或可以用在編譯器能夠確定委托類型的上下文中。

  所以,正是由于Addressof創(chuàng)建的不再只是簡單的函數(shù)指針了,而是子程委托!打住先,什么是委托?(^?^)

解釋一下:事件是對象發(fā)送的消息,以發(fā)信號通知操作的發(fā)生。操作可能是由用戶交互(例如鼠標單擊)引起的,也可能是由某些其他的程序邏輯觸發(fā)的。引發(fā) (觸發(fā))事件的對象叫做事件發(fā)送方。捕獲事件并對其作出響應的對象叫做事件接收方。在事件通訊中,事件發(fā)送方類不知道哪個對象或方法將接收到(處理)它引 發(fā)的事件。所需要的是在源和接收方之間存在一個媒介(或類似指針的機制)。.NET 框架定義了一個特殊的類型(Delegate),該類型提供函數(shù)指針的功能???,這里提到了.net框架,所以C#等vs.net中的語言都可以有這個類 型嘍。

  委托就是可用于調(diào)用其他對象方法的對象。與其他的類不同,委托類具有一個簽名,并且它只能對與其簽名匹配的方法進行引用。這 樣,委托就等效于一個類型安全函數(shù)指針或一個回調(diào)。因為它們與其他編程語言中所使用的函數(shù)指針相似。但不同于函數(shù)指針,Visual Basic.NET 委托是基于 System.Delegate 類的引用類型,它可以引用共享方法—無需特定即可調(diào)用的方法—和實例方法。(具體內(nèi)容請自已去查閱一下MSDN或等我的后續(xù)文章再說明)

回過頭來總結(jié)一下,也就是說,Addressof創(chuàng)建的是DelegateType(委托類型)。而不是簡單的子程指針了,所以它的表示法就不是地址類 型的long了,而是與調(diào)用的子程相一致的委托類型表示形式。因此,我定義了一個與MyKBHFunc聲明同形的委托函數(shù)HOOKPROC來表示lpfn 的類型。

  繼續(xù),我又接著聲明了一個API:

Declare Function GetCurrentThreadId Lib "kernel32" Alias "GetCurrentThreadId" () As Integer

  函數(shù)說明:本函數(shù)是用于獲取當前線程一個唯一的線程標識符。返回值:當前的線程標識符。這個有什么用,一會再說,反正是個簡單的問題,不如賣個關子,哈哈……(不要砸我)

  2. 定義的常量是:

Public hnextHookproc As Long
Public Const WH_KEYBOARD = 2 ‘這個是表明Hook的種類是鍵盤Hook
Public Const PM_KEY_SPACE = &H20 ‘空格鍵

  或者,實際上也是,我在程序中對上面的第二句寫法改變了一下,也沒什么了,就是多交待一點東西給朋友們嘛:

Public Enum HookType
 WH_KEYBOARD = 2
End Enum

  定義成了一個枚舉。其實Hook的種類真的很多,比如有:WH_CALLWNDPROC、WH_CALLWNDPROCRET、WH_CBT 、WH_DEBUG、WH_GETMESSAGE等等。所以你不妨寫一個枚舉,以達到一勞永逸的目的。

  3. 代碼段

Module Module1

Public frm1 As New Form1() ‘這個的作用,最后再說

 Declare Function GetCurrentThreadId Lib "kernel32" Alias "GetCurrentThreadId" () As Integer
 Declare Function SetWindowsHookEx Lib "user32" Alias _
"SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn As HOOKPROC, _
ByVal hmod As Integer, ByVal dwThreadId As Integer) As Integer

 Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Integer) As Integer

 Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Integer, _
ByVal ncode As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

Public Delegate Function HOOKPROC(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

 Public hnexthookproc As Integer
 Public Const PM_KEY_SPACE = &H20
 Public Enum HookType
 WH_KEYBOARD = 2
End Enum


Public Sub UnHook()  ‘解Hook
 If hnexthookproc <> 0 Then
  UnhookWindowsHookEx(hnexthookproc)
  hnexthookproc = 0
 End If
End Sub

Public Function SetHook() ‘設置Hook
 If hnexthookproc <> 0 Then
  Exit Function
End If

hnexthookproc = SetWindowsHookEx(HookType.WH_KEYBOARD, AddressOf MyKeyboardProc, 0, GetCurrentThreadId())

  我把第三個參數(shù)設為0(即NULL),表示的是此Hook的代碼在此進程中。第四個參數(shù)用了一個API去取安裝Hook子程相關聯(lián)的線程的標識符。(參見前面的API聲明)

End Function

Public Function MyKeyboardProc(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

MyKeyboardProc = 0

If nCode < 0 Then
 MyKeyboardProc = CallNextHookEx(hnexthookproc, nCode, wParam, lParam)
 Exit Function
End If

If wParam = PM_KEY_SPACE Then
 MyKeyboardProc = 1
 ‘寫入你自己的代碼
 frm1.textbox1.text=”HOOK成功!”
End If

End Function

Sub main()
 Application.Run(frm1)
End Sub
End Module

  同時請在:

  解決方案管理器-〉windowsapplication1.sln -〉右點鼠標 -〉屬性 -〉通用屬性->常規(guī)->啟動對象 -〉改為Module1

  4.在Form1中的代碼:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Call SetHook()

End Sub

‘vb.net中沒有form_unload事件了,而是用closing

Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

Call UnHook()

End Sub

最后簡單說明一下,為什么我在module1里用了Public frm1 As New Form1()這句話,及啟動對象 -〉改為Module1的作法。這是由于vb.net已經(jīng)是OO的了,如果你是yesky上vb.net版的???,你就會很熟悉這個問題,我們已經(jīng)討論過 N次了。

  結(jié)束語:關于API的調(diào)用,本文只涉及了冰山之一角,關于具體的調(diào)用變化,我會根據(jù)vb.net版上的具體情況再寫相關的文章來說明的。

  對了,補充一點,vb.net不再認any類型了,因此,在聲明時要具體聲明成你想要用的類型即可。
Add by : Huobazi (2005-8-17:09:59) 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多