Results 1 to 14 of 14

Thread: Question about hooking....

  1. #1

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Question about hooking....

    Can someone provide me with some insight or code that will explain to me a little more about hooking a window?

    basically this is my goal.. i want to hook a window to a program that is not one of my applications and view all the windows messages that are sent to it... i would have the class name or window handle of the target window... how could this be accomplished?

  2. #2
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    There are two types of windows hook that will be of use:- WH_CALLWNDPROC which is triggered whenever a message is added to a window's message queue using Sendmessage and the WH_GETMESSAGE hook type which is triggered whenever a window takes a messager off the queue using GetMessage or PeekMessage.

    Unfortunately, these are very difficult to implement safely in VB.
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  3. #3

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373
    merrion, can you give an example of their use?

    and if possible can you explain their instability in VB?

  4. #4
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    Code hacked out of the EventVB.dll hook implementation...may be incomplete...

    VB Code:
    1. '\\ In a .Bas module:-
    2. Public Enum enHookTypes
    3.     WH_CALLWNDPROC = 4
    4.     WH_CBT = 5
    5.     WH_DEBUG = 9
    6.     WH_FOREGROUNDIDLE = 11
    7.     WH_GETMESSAGE = 3
    8.     WH_HARDWARE = 8
    9.     WH_JOURNALPLAYBACK = 1
    10.     WH_JOURNALRECORD = 0
    11.     WH_MOUSE = 7
    12.     WH_MSGFILTER = (-1)
    13.     WH_SHELL = 10
    14.     WH_SYSMSGFILTER = 6
    15.     WH_KEYBOARD_LL = 13
    16.     WH_MOUSE_LL = 14
    17.     WH_KEYBOARD = 2
    18. End Enum
    19.  
    20. Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As enHookTypes, ByVal lpfn As Long, ByVal hMod As Long, ByVal dwThreadId As Long) As Long
    21.  
    22. Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
    23.  
    24. Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
    25.  
    26. Private Type msg
    27.     hwnd As Long
    28.     Message As Long
    29.     wParam As Long
    30.     lParam As Long
    31.     time As Long
    32.     pt As Long 'MSG
    33. End Type
    34.  
    35. Private Declare Sub CopyMemoryMSG Lib "kernel32" Alias "RtlMoveMemory" (Destination As msg, ByVal Source As Long, ByVal Length As Long)
    36.  
    37.  
    38. '\\ [VB_HOOKGETMESSAGEPROC]------------------------------------------
    39. '\\ typedef LRESULT (CALLBACK* HOOKPROC)(int code, WPARAM wParam, LPARAM lParam);
    40. '\\ code - hook action,
    41. '\\ Wparam, Lparam - message specific
    42. '\\ --------------------------------------------------------------------------------
    43. '\\ (c) 2001 - Merrion Computing.  
    44. '\\ Please check [url]http://www.merrioncomputing.com[/url] for updates.
    45. '\\ -------------------------------------------------------------------------------
    46. Public Function VB_HOOKGETMESSAGEPROC(ByVal Code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    47.  
    48. On Local Error Resume Next
    49.  
    50.  
    51. '\\ Note: If the code passed in is less than zero, it must be passed direct to the next hook proc
    52. If Code < 0 Then
    53.     VB_HOOKGETMESSAGEPROC = CallNextHookEx(lHookId, Code, wParam, lParam)
    54.     Exit Function
    55. End If
    56.  
    57. '\\ Process the message here...
    58. Dim msgIn As MSG
    59. If CopyMemoryMSG(msgIn, lParam, len(msgIn)) Then
    60.    Debug.Print Hex(msgIn.Message) & " processed by window " & msgIn.hwnd
    61. End If
    62.  
    63. lret = CallNextHookEx(lHookId, Code, wParam, lParam)
    64.  
    65.  
    66. '\\ If the message isn't cancelled, return the next hook's message...
    67. If lMsgRet = 0 Then
    68.     '\\ Return value to calling code....
    69.     VB_HOOKGETMESSAGEPROC = lret
    70. Else
    71.     VB_HOOKGETMESSAGEPROC = lMsgRet
    72. End If
    73.  
    74. End Function

    ...more to follow...
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  5. #5
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    See this article on how to install global hooks...
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  6. #6

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373
    thanks.. unfortunatly this is for something i am working on at home.. so i will have to wait till after work to try it out!

  7. #7
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    I have been working on this for the EventVB.dll...
    So far I can get a thread-wide message hook thus:

    VB Code:
    1. Option Explicit
    2.  
    3. Dim WithEvents vbLink As EventVB.APIFunctions
    4. Dim WithEvents vbHook As EventVB.ApiSystemHook
    5.  
    6. Private Sub Form_Load()
    7.  
    8. Set vbLink = New APIFunctions
    9.  
    10. Set vbHook = vbLink.System.Hooks
    11. vbHook.StartHook WH_GETMESSAGE, HOOK_LOCAL_PROCESS
    12.  
    13.  
    14. End Sub
    15.  
    16. Private Sub vbHook_AnyWindowMessageHandled(ByVal TargetWnd As EventVB.ApiWindow, ByVal Removed As Boolean, msg As EventVB.WindowMessages, wParam As Long, lParam As Long)
    17.  
    18. Debug.Print TargetWnd.WindowText & " received message " & msg
    19.  
    20. End Sub

    But if I change HOOK_LOCAL_PROCESS to HOOK_GLOBAL it only receives one message, which it erroneously says is message #4110, then unhooks itself. I can only presume that the CopyMemory needs to be replaced with a call to ReadProcessmemory, but can't figure out what process the hook is being called from before getting the MSG structure.....
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  8. #8
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    Did you get anywhere with this?

    I'm thinking a small C++ dll for the global hook with a callback function for your VB app to use might be the best way forward.
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  9. #9

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373
    Originally posted by MerrionComputin
    Did you get anywhere with this?

    I'm thinking a small C++ dll for the global hook with a callback function for your VB app to use might be the best way forward.
    merrion.. unfortunatly i got tied up and couldn't work on it last night... but this is a high priority application that i want to make..

    i have little knowledge of programmming in C so I am hoping it can be done via VB...

    basically I am working on a plug in for AOL Instant Messanger.. and I need to know when an IM is receieved.. i have found code on PSC and such to manipulate AIM but they were really nothing more than a bunch of API calls to find the window, send text to it etc.. i want to hook the AIM window to find out when incoming messages are actually recieved.. and have not found any code to do this.. thats why i am trying it on my own... i figure a message has to be processed telling it to send a message to the window..

  10. #10
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    Originally posted by MerrionComputin
    Did you get anywhere with this?

    I'm thinking a small C++ dll for the global hook with a callback function for your VB app to use might be the best way forward.
    You cannot do this in VB, Can you ? I thought you need global hook which can only be installed inside a standard DLL. You cannot make standard Dll's in VB.

  11. #11
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    I thought you need global hook which can only be installed inside a standard DLL
    This is true but I'm not so sure a global hook is required. Instead you can (possibly) convince the third party application to load your VB dll in it's thread context and install a thread local hook (which you can write in VB no problem).
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  12. #12
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    Originally posted by MerrionComputin
    This is true but I'm not so sure a global hook is required. Instead you can (possibly) convince the third party application to load your VB dll in it's thread context and install a thread local hook (which you can write in VB no problem).
    Geez, I'd like to know how to do that, if you do not mind telling us.

  13. #13
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    DLL Injection method 1: Only works for Windows NT4 or above...

    First you need to open a handle to the remote process that has appropriate access rights to write to that processes' own virtual memory. You do this with the OpenProcess API call specifying PROCESS_VM_WRITE and PROCESS_CREATE_THREAD flags.

    VB Code:
    1. Public Enum ProcessAccessRights
    2.     PROCESS_TERMINATE = &H1
    3.     PROCESS_CREATE_THREAD = &H2
    4.     PROCESS_VM_OPERATION = &H8
    5.     PROCESS_VM_READ = &H10
    6.     PROCESS_VM_WRITE = &H20
    7.     PROCESS_DUP_HANDLE = &H40
    8.     PROCESS_CREATE_PROCESS = &H80
    9.     PROCESS_SET_QUOTA = &H100
    10.     PROCESS_SET_INFORMATION = &H200
    11.     PROCESS_QUERY_INFORMATION = &H400
    12. End Enum
    13.  
    14. Public Declare Function OpenProcess Lib "kernel32" ( _
    15.                                     ByVal dwDesiredAccess As  ProcessAccessRights, _
    16.                                     ByVal bInheritHandle As Long, _
    17.                                     ByVal Processid As Long) As Long
    18.                                      
    19. Public Declare Function CloseHandle Lib "kernel32" (ByVal HandleIn As Long) As Long

    Then you need to allocate a page in the memory of the target process which will hold the DLL by using the VirtualAllocEx API call:

    VB Code:
    1. Public Enum VirtualMemoryAllocationTypes
    2.     MEM_COMMIT = &H1000
    3.     MEM_RESERVE = &H2000
    4.     MEM_FREE = &H10000
    5.     MEM_PRIVATE = &H20000
    6.     MEM_MAPPED = &H40000
    7.     MEM_RESET = &H80000
    8.     MEM_TOP_DOWN = &H100000
    9.     MEM_4MB_PAGES = &H80000000
    10. End Enum
    11.  
    12. Public Enum MemoryPageProtectionFlags
    13.     PAGE_NOACCESS = &H1
    14.     PAGE_READONLY = &H2
    15.     PAGE_READWRITE = &H4
    16.     PAGE_WRITECOPY = &H8
    17.     PAGE_EXECUTE = &H10
    18.     PAGE_EXECUTE_READ = &H20
    19.     PAGE_EXECUTE_READWRITE = &H40
    20.     PAGE_EXECUTE_WRITECOPY = &H80
    21.     PAGE_GUARD = &H100
    22.     PAGE_NOCACHE = &H200
    23. End Enum
    24.  
    25. Public Declare Function VirtualAllocEx Lib "kernel32" ( _
    26.                                            ByVal hProcess As Long, _
    27.                                            ByVal lpAddress As Long, _
    28.                                            ByVal dwSize As Long, _
    29.                                            ByVal flAllocationType As VirtualMemoryAllocationTypes, _
    30.                                            ByVal flProtect As MemoryPageProtectionFlags) As Long

    And, of course, any memory so allocated must be freed again when you are done....
    VB Code:
    1. Public Enum VirtualMemoryFreeTypes
    2.     MEM_DECOMMIT = &H4000
    3.     MEM_RELEASE = &H8000
    4. End Enum
    5.  
    6. Public Declare Function VirtualFreeEx Lib "kernel32" ( _
    7.                                            ByVal hProcess As Long, _
    8.                                            ByVal lpAddress As Long, _
    9.                                            ByVal dwSize As Long, _
    10.                                            ByVal dwFreeType As VirtualMemoryFreeTypes) As Long

    Now you copy the memory that has the dll code in it in your process to the target process using the WriteProcessmemory API call:
    VB Code:
    1. Public Declare Function WriteProcessMemory Lib "kernel32" ( _
    2.                                            ByVal hProcess As Long, _
    3.                                            ByVal lpAddress As Long, _
    4.                                            ByVal lpSourceBuffer As Long, _
    5.                                            ByVal dwSize As Long, _
    6.                                            dwBytesWritten As Long) As Long

    ...continues....
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  14. #14
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    ...contiunued....

    And you need to allocate memory and copy this for the parameters for the thread to use using the same VirtualAllocEx, WriteProcessmemory combination.

    Then you make this block of memory into a thread using the CreateRemoteThread API call:

    VB Code:
    1. Public Declare Function CreateRemoteThread Lib "kernel32" ( _
    2.                                            ByVal hProcess As Long, _
    3.                                            ByVal lpSecurityAttributes As Long, _
    4.                                            ByVal dwStackSize As Long, _
    5.                                            ByVal lpThreadProc As Long, _
    6.                                            ByVal lpParameters As Long, _
    7.                                            ByVal dwCreateFlags As Long, _
    8.                                            lThreadId As Long) As Long
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width