Introduction to Windows Hooks

Source: Internet
Author: User

In recent times because of friends urged to try to write a monitoring system, mainly used to manage the children use the computer, to help children use the computer properly. On the Internet to find the relevant content found there is no such information, so only to try to use the hook to monitor the Windows application, that is, as long as the application to run the automatic inspection process, whether or not comply with the rules. Now some of the hooks are stored here, convenient for later use!

The Windows system is built on the event-driven mechanism, which is to put it bluntly that the entire system is implemented through message delivery. The hook is a very important system interface in Windows system, it can intercept and process the message to other applications, to accomplish the function that ordinary application is difficult to implement. Hooks can monitor various event messages in the system or process, intercept messages destined for the target window, and process them. In this way, we can install custom hooks in the system, monitor the occurrence of specific events in the system, and accomplish certain functions, such as intercepting the keyboard, mouse input, screen fetching words, log monitoring and so on. It can be seen that many special and useful functions are realized by using hooks. Therefore, it is necessary for the advanced programmer to master the programming method of hooks.

Types of Hooks
A By event category, like the following several common types
(1) Keyboard hooks and low-level keyboard hooks can monitor various keyboard messages.
(2) Mouse hooks and low-level mouse hooks can monitor various mouse messages.
(3) Shell hooks can monitor various shell event messages. such as starting and closing applications.
(4) Log hooks can record various event messages taken out of the system message queue.
(5) The window procedure hook monitors all messages sent from the system message queue to the target window.
In addition, there are some specific event hooks available for us to use, not listed.
The following describes commonly used hook types:
1, Wh_callwndproc and Wh_callwndprocret Hooks
Wh_callwndproc and Wh_callwndprocret hooks enable you to monitor messages sent to a window procedure. The system calls the Wh_callwndproc hook thread before the message is sent to the receive window procedure, and calls Wh_callwndpro after the window procedure finishes processing the message.
Cret Hook. The Wh_callwndprocret hook passes the pointer to the CWPRETSTRUCT structure, which is then passed to the hook path. The CWPRETSTRUCT structure contains the return value of the window procedure from which the message was processed, and also includes the message parameters associated with the message.
2, WH_CBT Hook
The system calls the WH_CBT hook thread before the following events, which include:
1. Activate, build, destroy, minimize, maximize, move, change the size of the window events;
2. Complete the system instructions;
3. Mobile mouse, keyboard events from the system message queue;
4. Set input focus events;
5. Synchronize system Message Queuing events.
The return value of the hook determines whether the system allows or prevents one of these operations.
3, Wh_debug Hook
The system calls the Wh_debug hook before the hook thread that is associated with the other hooks in the system call system. You can use this hook to decide whether to allow the system to invoke a hook that is associated with another hook.
4, Wh_foregroundidle Hook
When the foreground thread of an application is idle, a low-priority task can be performed using the Wh_foregroundidle hook. When the foreground thread of the application is about to become idle, the system calls the Wh_foregroundidle hook thread.
5, Wh_getmessage Hook
The application uses wh_getmessage hooks to monitor the messages returned from the GETMESSAGE or PeekMessage function. You can use the Wh_getmessage hook to monitor mouse and keyboard input, as well as other messages sent to the message queue.
6, Wh_journalplayback Hook
Wh_journalplayback hooks enable applications to insert messages into the system message queue. You can use this hook to replay successive mouse and keyboard events recorded by using the Wh_journalrecord hook. As long as the Wh_journalplayback hook has been installed, normal mouse and keyboard events are invalid. The Wh_journalplayback Hook is a global hook that cannot be used as a thread-specific hook. Wh_journalplayback Hook returns the timeout value, which tells the system how long (in milliseconds) to wait before processing the current message from the playback hook. This allows the hook to control the playback of real-time events. Wh_journalplayback are system-wide local hooks and they will not be injected into any of the travel address spaces. (It is estimated that the key wizard is made with this hook)
7, Wh_journalrecord Hook
Wh_journalrecord hooks are used to monitor and record input events. Typically, this hook can be used to record successive mouse and keyboard events, and then back and forth by using the Wh_journalplayback hook. The Wh_journalrecord Hook is a global hook that cannot be used as a thread-specific hook. Wh_journalrecord are system-wide local hooks and they will not be injected into any of the travel address spaces.
8, Wh_keyboard Hook
In the application, Wh_keyboard hooks are used to monitor wm_keydown and WM_KEYUP messages, which are returned by GetMessage or PeekMessage function. You can use this hook to monitor keyboard messages entered into the message queue.
9, Wh_keyboard_ll Hook
The Wh_keyboard_ll hook monitors the keyboard messages entered into the thread message queue.
10, Wh_mouse Hook
Wh_mouse Hooks monitor Mouse messages returned from the GetMessage or PeekMessage functions. Use this hook to monitor mouse messages entered into the message queue.
11, Wh_mouse_ll Hook
WH_MOUSE_LL Hooks monitor Mouse messages that are entered into the thread message queue.
12, Wh_msgfilter and Wh_sysmsgfilter Hooks
Wh_msgfilter and Wh_sysmsgfilter hooks enable us to monitor menus, scroll bars, message boxes, dialog messages and discover that users use ALT + TAB or ALT+ESC key combinations to switch windows. Wh_msgfilter hooks can only monitor messages that are passed to a menu, scroll bar, message box, and messages that are passed to a dialog box created by an application that has a hook thread installed. Wh_sysmsgfilter Hooks monitor all application messages. Wh_msgfilter and Wh_sysmsgfilter hooks allow us to filter messages during the pattern cycle, which is equivalent to filtering messages in the main message loop. The Wh_msgfilter Hook can be called directly by calling Callmsgfilter function. By using this function, the application can use the same code to filter the message during the pattern loop, as in the main message loop.
13, Wh_shell Hook
The shell application can use the Wh_shell hook to receive important notifications. When the shell application is active and the When top layer window is created or destroyed, the system calls the Wh_shell hook thread.
Wh_shell a total of 5:
1. As long as a top-level, unowned window is produced, acted on, or destroyed;
2. When taskbar need to redraw a button;
3. When the system needs to display a minimal form of a program about taskbar;
4. When the current keyboard layout status changes;
5. When the user presses CTRL+ESC to execute task Manager (or the same level of program).
As a rule, shell applications do not receive Wh_shell messages. Therefore, before an application can receive Wh_shell messages, the application must call SystemParametersInfo function to register itself.
These are the 13 types of hooks that are commonly used!
Two The main thread hooks and system hooks are categorized by use range
(1) Thread hooks monitor event messages for the specified thread.
(2) System hooks Monitor event messages for all threads in the system. Because the system hooks affect all applications in the system, the hook function must be placed in a separate dynamic-link library (DLL)
In This is a big difference between the system hooks and the thread hooks.
Here are a few things to note:
(1) If both the thread hook and the system hook are installed for the same event (such as a mouse message), the system will call the thread hook first and then the system hook.
(2) Multiple hook processes can be installed on the same event message, and these hook processes form a chain of hooks. The hook information should be passed to the next hook function at the end of the current hook processing. And recently installed hooks are placed at the beginning of the chain, and the first installed hooks are placed at the end, that is, the first to gain control after adding.
(3) Hooks, especially system hooks, consume message processing time and reduce system performance. Only when necessary to install the hook, after the use of the time to uninstall.
Write a hook program
The procedure for writing hooks is divided into three steps: defining hook functions, installing hooks, and unloading hooks.
1. Defining hook functions
The hook function is a special callback function. After the specific event that the hook is monitored, the system calls the hook function for processing. The form of the hook function for different events is not the same. The following is an example of a hook function using the mouse hook function:
LRESULT CALLBACK HookProc (int nCode, WPARAM wparam,lparam LPARAM)
Parameters wparam and lparam contain information about the hooked message, such as the mouse position, status, keyboard keys, and so on. Ncode contains information about the message itself, such as whether to move out of the message queue.
We first implement the custom function in the hook function, and then call the function CallNextHookEx. Pass the hook information to the next hook function in the hook chain. The prototype of CallNextHookEx is as follows:
LRESULT CallNextHookEx (hhook hhk, int nCode, WPARAM WPARAM, LPARAM LPARAM)
The parameter hhk is a hook handle. NCode, wparam, and lparam are hook functions.
It is also possible to discard the message by directly returning true to prevent the message from being passed.
2. Mounting hooks
At the time of program initialization, call function SetWindowsHookEx install hooks. Its function prototypes are:
Hhook SetWindowsHookEx (int idhook,hookproc lpfn, INSTANCE hmod,dword dwthreadid)
The parameter Idhook represents the hook type, which corresponds to the hook function type one by one. For example, Wh_keyboard indicates that a keyboard hook is installed, Wh_mouse is a mouse hook, and so on.
LPFN is the address of the hook function.
Hmod is the handle to the instance where the hook function resides. For thread hooks, this parameter is NULL, and for system hooks, this parameter is the DLL handle where the hook function resides.
DWTHREADID Specifies the thread number of the thread that the hook is monitoring. For global hooks, this parameter is null.
SetWindowsHookEx returns the installed hook handle.
3. Uninstalling Hooks
When you no longer use hooks, you must uninstall them in a timely manner. Simply call the function BOOL UnhookWindowsHookEx (Hhook hhk) to be able.

It is important to note that the position of the hook function of the thread hook and the system hook is very different. Thread hooks are generally in the current thread or in a thread that derives from the threads, and the system hooks must be placed in a separate dynamic link library, which is a bit cumbersome to implement.

Programming examples of thread hooks:
Follow the method described above to implement a thread-level mouse hook. The hook tracks the position change information of the mouse movement in the current window. and output to the window.
(1) using MFC in vc++6.0
APPWizard (EXE) generates a single document application Mousehook that does not use the document/view structure. Open the Childview.cpp file and join the global variable:
Hhook hhook;//Mouse Hook handle
CPoint point;//Mouse location information
CChildView *pview;
The output window pointer used by the mouse hook function

Add the following code to Cchildview::onpaint ():
CPAINTDC DC (this);
Char str[256];
sprintf (str, "x=%d,y=%d", POINT.X,POINT.Y);
Construct a string
dc. TextOut (0,0,STR); Display string

(2) The global mouse hook function is defined in the Childview.cpp file.
LRESULT CALLBACK Mouseproc
(int nCode, WPARAM WPARAM, LPARAM LPARAM)
{//IS mouse move message
if (wparam==wm_mousemove| | WParam
==wm_ncmousemove)
{
Point= ((MouseHookStruct *) lParam)->pt;
Take Mouse information
Pview->invalidate (); window re-painting
}
return CallNextHookEx (Hhook,ncode,wparam,lparam);
Passing Hook information
}
(3) Install hooks in the constructor of the CChildView class.
Cchildview::cchildview ()
{
pview=this;//Get Output Window pointer
Hhook=setwindowshookex (Wh_mouse,mouseproc,0,getcurrentthreadid ());
}
(4) Unload hooks in the destructor of the CChildView class.
Cchildview::~cchildview ()
{
if (hhook)
UnhookWindowsHookEx (Hhook);
}

Programming examples of system hooks:
Because the system hook to use DLL, so first introduced the following Win32 DLL features:
The Win32 DLL differs greatly from the Win16 DLL, which is mainly determined by the design of the operating system. On the one hand, the program entry point function and exit point function (LibMain and WEP) are implemented separately in the Win16 DLL, whereas in the Win32 DLL it is implemented by the same function DllMain. Whenever a process or thread loads and unloads a DLL, the function is called, and its prototype is bool WINAPI DllMain
(HInstance Hinstdll,dword Fdwreason, LPVOID lpvreserved); where the first parameter represents the instance handle of the DLL; The third parameter system is reserved; Here's a second parameter, which has four possible values: Dll_ Process_attach (process loading), Dll_thread_attach (thread loading), Dll_thread_detach (thread offload), Dll_process_detach (process offload), In the DllMain function, the value of this parameter passed in can be judged, and the DLL is initialized or cleaned up according to different parameter values. For example, when a process loads a DLL, the second parameter that the system assigns to the DLL is Dll_process_attach, and you can initialize the specific data based on this parameter. On the other hand, in the WIN16 environment, all applications are in the same address space, while in the WIN32 environment, all applications have their own private space, each process space is independent of each other, which reduces the interaction between applications, but also increases the difficulty of programming. As you know, in the WIN16 environment, the DLL's global data is the same for each process that loads it, while in the WIN32 environment, the situation changes, and when the process loads the DLL, the system automatically maps the DLL address to the private space of the process. It also replicates a copy of the DLL's global data to the process space, meaning that the value of the global data for the same DLL owned by each process is not necessarily the same. Therefore, in a Win32 environment, if you want to share data across multiple processes, you must make the necessary settings. That is, separating the data that needs to be shared, placing it in a separate data segment, and setting the attribute of that segment to shared.
There are three forms of MFC DLLs in VC6 (which can be used and inherited from existing MFC classes), i.e. regular statically linked to MFC DLLs (standard statically linked MFC DLLs) and regular using the Shared MFC DLLs (Standard dynamic-link MFC DLLs) and extension MFC DLLs (extended MFC DLLs). The first DLL is characterized by the use of MFC code at compile time to add to the DLL, so in the use of the program does not require the existence of other MFC dynamic Link class library, but the disk space is larger; the second DLL is characterized by dynamically linking to the MFC class library at run time, thus reducing the footprint of space. However, it relies on the MFC dynamic Link class library at runtime, both of which can be used by MFC programs or WIN32 programs. The third kind of DLL features similar to the second, as an extension of the MFC class Library, can only be used by MFC programs.
Let's talk about the implementation of globally shared data in VC6
In the main file, create a new data segment with #pragma data_seg and define the shared data in the following format:
#pragma data_seg ("Shareddata")
HWND sharedwnd=null;//Shared data
#pragma data_seg ()
Defining only one segment of data does not achieve the purpose of sharing data, but also tells the compiler the properties of that segment, there are two ways to do that (the effect is the same), and one way is to do so. def file, add the following statement:
Setctions shareddata READ WRITE SHARED
Another way is to include the following statement in the Project Settings link option:
/section:shareddata,rws
Well, the preparation of knowledge has been learned, let's start to write a global hook program it!



Since the global hook function must be included in the dynamic link library, this example is implemented by two program bodies.
1. Build Hook Mousehook.DLL
(1) Select MFC AppWizard (DLL) to create the project Mousehook;
(2) Select MFC Extension DLL (Shared MFC copy) type;
(3) Since VC5 does not have a ready-made hook class, create a Mousehook.h file in the project directory where the hook class is built:
Class Afx_ext_class Cmousehook:public CObject
{
Public
Cmousehook ();
The constructor of the hook class
~cmousehook ();
A destructor for a hook class
BOOL Starthook (HWND hwnd);
Install hook function
BOOL Stophook ();
Unload hook function
};
(4) Add # include "Mousehook.h" statement at the top of the Mousehook.app file;
(5) Adding global shared data variables:
#pragma data_seg ("MyData")
HWND Glhprevtarwnd=null;
The window handle that was last pointed to by the mouse
HWND Glhdisplaywnd=null;
Displays the handle of the title edit box for the target window
Hhook Glhhook=null;
Installed mouse hook handle
HINSTANCE Glhinstance=null;
DLL instance handle
#pragma data_seg ()
(6) Define the segment properties in the Def file:
SECTIONS
MyData READ WRITE SHARED
(7) Add the statement that holds the DLL instance handle in the DllMain function of the main file Mousehook.cpp:
DllMain (hinstance hinstance, DWORD dwreason, LPVOID lpreserved)
{
If you use the lpreserved parameter, delete the following line
Unreferenced_parameter (lpreserved);
if (Dwreason = = Dll_process_attach)
{
TRACE0 ("Mousehook. DLL initializing!\n ");
Extension DLLs are initialized only once
if (! AfxInitExtensionModule (Mousehookdll, hinstance))
return 0;
New CDynLinkLibrary (Mousehookdll);
Adding DLLs to the dynamic MFC class Library
Glhinstance=hinstance;
Insert Save DLL Instance handle
}
else if (Dwreason = = Dll_process_detach)
{
TRACE0 ("Mousehook. DLL terminating!\n ");
Call it before terminating this link library
AfxTermExtensionModule (Mousehookdll);
}
return 1;
}
(8) The concrete implementation of the member function of class Cmousehook:
Cmousehook::cmousehook ()
Class constructors
{
}
Cmousehook::~cmousehook ()
Class destructor
{
Stophook ();
}
BOOL Cmousehook::starthook (HWND hwnd)
Install the hook and set the Receive display window handle
{
BOOL Bresult=false;
Glhhook=setwindowshookex (wh_mouse,mouseproc,glhinstance,0);
if (glhhook!=null)
Bresult=true;
Glhdisplaywnd=hwnd;
Set the handle of the Display Target window title edit box
return bresult;
}
BOOL Cmousehook::stophook ()
Uninstalling Hooks
{
BOOL Bresult=false;
if (Glhhook)
{
bresult= UnhookWindowsHookEx (Glhhook);
if (bresult)
{
Glhprevtarwnd=null;
glhdisplaywnd=null;//Clear Variable
Glhhook=null;
}
}
return bresult;
}
(9) The implementation of the hook function:
LRESULT WINAPI mouseproc (int ncode,wparam wparam,lparam LPARAM)
{
Lpmousehookstruct pmousehook= (mousehookstruct FAR *) lparam;
if (ncode>=0)
{
HWND glhtargetwnd=pmousehook->hwnd;
Take the target window handle
HWND Parentwnd=glhtargetwnd;
while (Parentwnd!=null)
{
Glhtargetwnd=parentwnd;
Parentwnd=getparent (Glhtargetwnd);
Take the application main window handle
}
if (Glhtargetwnd!=glhprevtarwnd)
{
Char szcaption[100];
GetWindowText (glhtargetwnd,szcaption,100);
Take the target window title
if (IsWindow (Glhdisplaywnd))
SendMessage (glhdisplaywnd,wm_settext,0, (LPARAM) (LPCTSTR) szcaption);
Glhprevtarwnd=glhtargetwnd;
Save Target window
}
}
return CallNextHookEx (Glhhook,ncode,wparam,lparam);
Continue to deliver messages
}
(10) Compile the project to generate Mousehook.dll.
2. Create hooks to execute programs
(1) using MFC AppWizard (EXE) to create the project mouse;
(2) Select "Based on the Dialogue app" and press "Finish" key;
(3) Edit the dialog box, delete its original two buttons, add static text box and edit box, right-click on the static text box, in the pop-up menu select "Properties", set its title "Mouse window title";

(4) Add the Include statement to Mousehook.h # include "in Mouse.h. \mousehook\mousehook.h ";
(5) Add a private data member to the Cmousedlg class definition in CMouseDlg.h:
Cmousehook m_hook;//joins the Hook class as a data member
(6) Modify the Cmousedlg::oninitdialog () function:
BOOL Cmousedlg::oninitdialog ()
{
CDialog::OnInitDialog ();
ASSERT ((Idm_aboutbox & 0xfff0) = = Idm_aboutbox);
ASSERT (Idm_aboutbox <0xf000);
cmenu* Psysmenu = GetSystemMenu (FALSE);
if (psysmenu! = NULL)
{
CString Straboutmenu;
Straboutmenu.loadstring (Ids_aboutbox);
if (!straboutmenu.isempty ())
{
Psysmenu->appendmenu (Mf_separator);
Psysmenu->appendmenu (mf_string, Idm_aboutbox, Straboutmenu);
}
}
SetIcon (M_hicon, TRUE);//set big icon
SetIcon (M_hicon, FALSE);//set small icon
Todo:add Extra initialization here
CWnd * Pwnd=getdlgitem (IDC_EDIT1);
Gets the class pointer of the edit box
M_hook.starthook (Pwnd->getsafehwnd ());
Get the window handle of the edit box and install the hook
return TRUE;
Return TRUE unless you set the focus to a control
}
(7) Link DLL library, that is, put the. \mousehook\debug\mousehook.lib added to the Project Settings Link tab;
(8) Compile the project to generate executable files;
(9) Copy the Mousehook.DLL to. The \mouse\debug directory;
(10) Run several executable programs first, then run the Mouse.exe program, move the mouse in different windows, in the Mouse.exe program window in the edit box will show the main window of the application of the mouse title

Introduction to Windows Hooks

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.