Windows applications are message-driven. Various applications respond to a variety of messages to achieve a variety of functions.
Windows hooks are a monitoring point for Windows message processing mechanisms that enable you to monitor the functionality of certain types of messages in a specified form by installing hooks. The so-called specified form is not limited to the form of the current process, but can also be a form for other processes. When a monitored message arrives at the specified form, the hook function intercepts the message before the specified form processes the message, and the hook function can either process the message or continue to pass the message without any processing. Using hooks is one of the ways to implement DLL injection. Other frequently used methods are: manual injection, remote thread injection.
A hook function is a program segment that processes messages. is to register the system when installing the hooks .
The following three points are clear about Windows hooks:
1: Hooks are used to intercept the flow of messages in the system. The use of hooks can handle messages of any kind that we are interested in, including, of course, other processes.
2: After intercepting the message, the program used to process the message is called the hook function. It is a function of its own definition that tells Windows the address of this function when the hook is installed.
3: The system may have more than one process installation hook at the same time, multiple hooks constitute the hook chain. So after intercepting the message and processing it, the message should continue to be passed so that the other hooks can handle the message.
Note: Using a hook can slow down the system because it adds the amount of system processing for each message. So install the hooks only when necessary. Do not need to be unloaded in time.
Mounting hooks:
1:
SetWindowsHookEx ( int Idhook, //type of hook to install. HOOKPROC The address of the LPFN,//hook function. hinstance Hmode, //The address of the DLL within the process where the hook function resides. DWORD Dwthread, //thread to install hooks. If 0, the hooks are installed for all threads. );
Idhook Specifies the type of hook to install, he can be the following value:
The hook function is called when the Wh_callwndproc//target thread calls SendMessage to send a message.
Wh_callwndprocret//When SendMessage returns, the hook function is called.
Wh_keyboard//When querying Wm_keyup or wm_keydown from the message queue.
Wh_getmessage//target thread when calling GETMESSAGE or PeekMessage
Wh_mouse//Queries the message queue for mouse event messages.
Wh_msgfilter//Please refer to MSDN below.
Wh_sysmsgfilter
Wh_jornalrecord
Whjornalplayback
Wh_shell
Wh_cbt
Wh_foregroundidle
Wh_debug
2:
LPFN is the address of the hook function. After the hook is installed, it is assumed that a corresponding message occurred, and Windows will call the function that this parameter points to. The General hook function is located in a DLL. When installing hooks for threads in other processes, assuming that the hook function is in the DLL, the system maps the DLL to that process so that he can be called within that process.
Note: The hook function is mostly called by threads in other processes, not necessarily the thread that installs the hooks.
the process by which the hook function is called :
When a thread of process a prepares to send a message to a form, the system checks to see if the thread is installed with a hook, assuming that the thread is installed with a hook and that the message is the same as the message type that the hook is intercepting, this message will be intercepted. The system checks if the DLL where the hook function is located is already mapped in process A's address space. Assuming it is not mapped, the system forces the DLL to be mapped to the address space of process a. Then get the hook function at the virtual address of process A and call the hook function. We are able to define our process of handling this message within the hook function.
Note: When the system maps the DLL containing the hook function to a process address space, the entire DLL is mapped, not just the hook function, which means that we can use all the exported functions in that DLL.
The 3:hmod parameter is the instance handle of the DLL where the hook function is located, and also the virtual address of the DLL within the process. Assuming that the hook function is in the current session, this parameter should be specified as null.
4:DWTHREADID Specifies the ID number of the thread to which the hook is to be installed. Assuming that it is set to 0, hooks are installed for all GUI threads within the system.
5: Hook function
After the hook is installed, it is assumed that a corresponding message occurs, and Windows calls the hook function. The following is a prototype of the hook function:
LRESULT CALLBACK HookProc (int ncode,wparam wparam,lparam LPARAM) { //The code that processes the message. return CallNextHookEx (Hhook,ncode,wparam,lparam); }
HookProc is the name of the hook function.
ncode Specifies whether the message must be processed. Assuming that it is hc_action, then the hook function must process the message. Assuming that it is less than 0, the hook function must pass the message to CallNextHookEx, the message is not processed correctly, and the return value of CallNextHookEx is returned.
The CallNextHookEx is used to pass the message to the next hook function in the hook chain.
wparam and the value of the lparam depends on the detailed hook type. Please refer to MSDN.
Uninstall the Hooks .
BOOL UnhookWindowsHookEx (Hhook hhk);
HHK is the handle of the hook to unload.
A sample is implemented below to enable monitoring of keyboard keys. Once a keyboard is pressed, a message is displayed in the main program form indicating which key is pressed.
Program Appearance:
To implement the DLL first:
There is no doubt that the hook function is implemented within the DLL. The functions of installing hooks and unloading hooks can be written in the main program, and can also be written in DLLs. It is only possible to install hooks within the main program when written in the main program. The implementation in the DLL allows the program to install hooks that load the DLL. For example, when a process loads the DLL, it can create a thread in DllMain and let him invoke the install hook function to implement the hook for the thread in this process. In order to extend the function of the program and implement code reuse, it is best to write the hook function inside the DLL. In addition, it is also possible to achieve modularity. Once the requirements change, you can simply change the code within the DLL without changing the main program.
When the hook function is called, that is, we are intercepted the message has been triggered, how to let the main program get this notification?
We are able to send messages to the main program's form within the hook function in other processes. But how to send it?
PostMessage is able to implement this function.
Look at the prototype:
BOOL WINAPI PostMessage (HWND hwnd,uint msg,wparam wparam,lparam LPARAM);
The HWND is the form handle to accept the message.
MSG is the message to be sent.
WPARAM and lparam are additional parameters for the message.
Although you can use PostMessage to implement a message to the main program's form, how do we get the form handle of the main program? We know that the hook function is implemented within the DLL, and the DLL is loaded into each process. It is a problem for other processes to want the form handle of the main program.
Talking about memory-mapped files in the Windows core programming series, we talked about the use of shared segments within a running file to enable multiple instances of the same executable file to share data within a shared segment. What about using shared segments in DLLs? Haha, you may have guessed it, because the DLL is mapped to each process, the data is placed in the shared segment of the DLL, it is possible to actually share the data within the DLL in the process.
Our solution is to create a shared segment within the DLL and place the main program's form handle in the shared segment. You can assign a form handle in a shared segment to the form handle of a master program when the main program calls the function that installs the hook. So as to achieve the purpose of sharing data within each process. Here, we learn a way to share data between processes, and one way is to take advantage of memory-mapped files.
Create and set up code for shared segments: be able to refer to the memory mapping file in Windows core programming.
#pragma data_seg ("shared") HWND hwnd=null; Hhook Hhook=null; #pragma data_seg () #pragma comment (linker, "/SECTION:SHARED,RWS")
How many more a hhook,hhook is the handle to the created hook. Because in the hook function, CallNextHookEx is called to pass the message to the next node of the hook chain. Both are called in other processes, so we must also set the handle of the hook to be shared.
Code for creating hooks inside a DLL:
KEYHOOKDLL_API BOOL Sethook (
The bool isinstall,//true indicates that the hook is installed and false indicates an unload hook.
HWND hwnd, //main program form handle, used to pass in settings within the main program.
int ThreadId)//The thread to install the hook on. {:: hwnd=hwnd;//assigns the current form handle to the form handle within the common segment of the DLL. if (Isinstall) {Hhook=setwindowshookex (wh_keyboard,keyhookproc,getmodulehandle
("Keyhookdll"), ThreadId); return true;} Else{unhookwindowshookex (hhook); return true;}}
created with a hook type of wh_keyboard, he was able to intercept Wm_keydown and the Wm_keyup message. Please refer to MSDN for details.
The ability to create a hook function is very easy, just install hooks and set data in shared segments. Thread is the threads to which the hooks are to be installed. The main program passes in 0 at the time of invocation, indicating that the hooks are installed for all threads.
Then look at the hook function:
LRESULT CALLBACK keyhookproc (int nCode, WPARAM wparam,lparam LPARAM) {if (ncode<0| | Ncode==hc_noremove) {return CallNextHookEx (Hhook,ncode,wparam,lparam);} if (lparam&0x40000000)//only responds to Wm_down. { PostMessage (hwnd,wm_keydown,wparam,lparam); }
return CallNextHookEx (Hhook,ncode,wparam,lparam);}
in the hook function first infer the value of ncode, when he is less than zero should call CallNextHookEx, in addition to it can also have the following values:
ACTION: Describes the information that wparam and lparam include the keystroke message, which can be handled.
Hc_noremove: Description wparam and lparam include information about the keystroke message, but the message was not removed from the message queue. That is, the program calls PeekMessage to query messages within the message queue.
(Differences and connections with GetMessage: They all query messages from within the message queue, send the message when there is a message, and getmessage wait until a message arrives without a message.) PeekMessage, however, returns immediately regardless of whether any messages are in the message queue. )
It is therefore necessary to call CallNextHookEx directly when the ncode is detected to be less than 0 or if the message cannot be processed for wh_noremove. The 30th bit of lparam is 1, indicating that the key is pressed and the key is bounced. This is inferred to send a message to the form only when the key is pressed. Prevents messages from being sent two times per keystroke.
when a message arrives, we send a message to the main program form to define the message for the user: Wm_key
He was defined as # define Wm_key wm_user+1
Within the main program we have to implement the message handler for this message ourselves.
The prototypes are:
afx_msg LRESULT OnKey (WPARAM wparam,lparam LPARAM);
Implementation :
Char Keyname[100];::getkeynametext (lparam,keyname,100);//Gets the key name of the key. CString A;a.format ("User key:%s\r\n", keyname); m_output+=a; UpdateData (FALSE);:: MessageBeep (MB_OK); CEdit *edit= (cedit*) GetDlgItem (idc_edit_output); Edit->linescroll (Edit->getlinecount ()); return 0;
so far, the main functions are all done, and all that remains is how to create the DLLs. No longer described here. The sample program was implemented on the afternoon of December 2, 2011.
Summary: The above program took nearly three hours to achieve, this program seems easy but once you start to achieve a variety of problems ensued. So in the future to often do some seemingly easy program, do not above his business. When I hit these words, the keyboard monitor was still working, showing each key I pressed. Obviously the computer feels slower than usual, and it seems that using hooks, especially system-wide hooks, can lead to very large overhead.
Several ways to inject DLLs are discussed in Windows core programming. It describes the use of Windows hooks, but the introduction of the very easy. The above content is from the fifth edition of Windows core programming, Part IV and the second edition of Windows programming, Wang Yanping. If there is any mistake, please correct me.
Windows core Programming series 18 Talk about Windows hooks