<Win32> using hooks to intercept messages with Spy + +

Source: Internet
Author: User

1. Hooks

The hooks are the back door that Windows left us. Filtering messages, such as shortcut keys, programs to monitor the keyboard, to get keyboard action, and then to judge.

Detailed Travel: http://blog.csdn.net/sunears/article/details/1861568


2. Hook usage

Add Hook: SetWindowsHookEx

Hhook WINAPI SetWindowsHookEx (  _in_  int idhook,  _in_ HOOKPROC  lpfn,  _in_  hinstance Hmod,  _in_  DWORD dwThreadID);

Idhook: hook type, the monitoring message here is Wh_callwndproc (SendMessage send), Wh_getmessage (PostMessage send), and gets the return value Wh_callwndprocret.

LPFN: A thread that monitors another process needs to define a hook callback function in the DLL

Hmod:dll handle

dwThreadID: The thread ID of the monitored process


Uninstall Hook: UnhookWindowsHookEx

BOOL WINAPI UnhookWindowsHookEx (  _in_  hhook hhk);

Hhk:setwindowshookex returned by Hhook


3. Spy + + Get the message

Log Messages for monitoring:

Finder: Find the window handle;

Message: Defines the type of receive message;

Output: Defines the output additional information for the message, where we add "original message parameter", "Original return value";

The example diagram is as follows:


Before the handle to receive the message, P/S/R is defined as follows, needless to say.

Spy + + Help:

Code meaning
P Use the PostMessage function to send messages to the queue. There is no information available about the final disposition of the message.
S Use the SendMessage function to send a message. This means that the sender does not regain control until the receiver processes and returns the message. Therefore, the receiver can transfer a return value back to the sender.
S The message was sent, but security prevented access to the return value.
R Each "S" row has a corresponding "R" (return) row that lists the return value of the message. Sometimes a message call is nested, which means that one message handler sends another message.

Spy + + uses hooks to intercept messages as well.

According to: http://www.yourdelphi.com/topic_372749_d537.htm

The WIN32 program does not handle different types of message, and for post messages (sent via PostMessage), it is handled by GetMessage, for send over message (Sent via SendMessage ), is handled by Callwndproc and executes callwndretproc after processing is completed, so it is necessary to hook and distinguish between the two types of message that need to handle three hook:wh_getmessage, Wh_callwndproc, and Wh_ simultaneously Callwndprocret.
So:
1, ' P ': The message sent by PostMessage can be obtained by wh_getmessage
2, ' S ': can get SendMessage send message via Wh_callwndproc
3, ' R ': Through Wh_callwndprocret you can get SendMessage results, which is what you want Iresult

So the idea of imitating Spy + + has come out.

Set 3 thread hooks, order monitor Wh_callwndproc, Wh_callwndprocret, Wh_getmessage.


4. Concrete implementation

MyCsdn.exe: main caller, user input exe to be monitored

Shared.dll: Functions shared by all DLLs

CallWndProcHook.dll:WH_CALLWNDPROC Monitoring

CallWndProcRetHook.dll:WH_CALLWNDPROCRET Monitoring

GetMessageHook.dll:WH_GETMESSAGE Monitoring

For boost, pay attention to adding boost libraries.


MyCsdn.exe: Get EXE process ID, get thread ID, load DLL, start hook

#include <iostream> #include <fstream> #include <Windows.h> #include <Shlobj.h> #include < boost/tokenizer.hpp> #include <process.h> #include <TlHelp32.h> #include <tchar.h> #include < Math.h>using namespace std;//get program main thread Iddword getthreadidbyprocessid (DWORD dwprocessid) {HANDLE Hthreadsnap =:: CreateToolhelp32Snapshot (Th32cs_snapthread, Dwprocessid); if (Hthreadsnap = = Invalid_handle_value) {return-1;} THREADENTRY32 te32 = {sizeof (TE32)};if (:: Thread32first (Hthreadsnap, &te32)) {do{if (Te32.th32ownerprocessid = = DWPROCESSID) {:: CloseHandle (HTHREADSNAP); return te32.th32threadid;}} while (:: Thread32next (Hthreadsnap, &te32));}::closehandle (hthreadsnap); return-1;} Get process Iddword getprocessidbyname (lpcwstr processName) {HANDLE hsnapshot = CreateToolhelp32Snapshot (Th32cs_ snapprocess,0);          PROCESSENTRY32 PE; pe.dwsize = sizeof (PROCESSENTRY32); if (!    Process32First (Hsnapshot,&pe)) {return NULL; } BOOL clearprocess = FALse;while (Process32Next (hsnapshot,&pe)) {if (!_tcsicmp (ProcessName, Pe.szexefile)) {:: Clo Sehandle (hsnapshot); return pe.th32processid;} }:: CloseHandle (hSnapShot); return-1;} BOOL g_bthreadrunning = true;void dllwinthread (lpvoid lP) {g_bthreadrunning = true;wchar_t wstrexe[256] = {0};cout <&lt ; "The program to Hook:"; wcin >> Wstrexe;dword dwprocessid = Getprocessidbyname (Wstrexe); if (Dwprocessid = =-1) {g_bth readrunning = False;system ("pause"); return;} DWORD dwThreadID = Getthreadidbyprocessid (DWPROCESSID); typedef void (*starthook) (int); HINSTANCE hinst = LoadLibrary (TEXT ("CallWndProcHook.dll")); HInstance Hinst2 = LoadLibrary (TEXT ("GetMessageHook.dll")); HInstance Hinst3 = LoadLibrary (TEXT ("CallWndProcRetHook.dll")); Starthook cwpst = (starthook) GetProcAddress (hinst, "Startcallwndhook"); Starthook gmst = (starthook) GetProcAddress (Hinst2, "Startgetmessagehook"); Starthook Cwprst = (starthook) GetProcAddress (Hinst3, "Startcallwndrethook"); Cwpst (DwthreADID); Cwprst (dwThreadID); Gmst (dwthreadid); int ntimeout = 500;while (ntimeout--) {Sleep (100);} FreeLibrary (hinst); FreeLibrary (HINST3); FreeLibrary (hinst2); g_bthreadrunning = false;} int main (int argc, char **argv) {HANDLE hthread = CreateThread (null, 0, (lpthread_start_routine) dllwinthread,//thread function NULL, function parameter 0, NULL), while (g_bthreadrunning) {Sleep (50);} CloseHandle (Hthread); System ("pause"); return 0;}


Shared.dll: Using export symbols, for other DLLs common functions, write files, message translation, use to boost (my blog: Boost installation)

Shared.h

#ifdef shared_exports#define Shared_api __declspec (dllexport) #else # define SHARED_API __declspec (dllimport) #endif # Include <map> #include <string>using std::map;using std::string; Shared_api void Appenddebug (char *pfilename, LPVOID pBuf, int length); Shared_api void Showdebug (LPTSTR lpstrformat, ...); Shared_api void Initsymbolicmsg (Map<uint, string>&); Shared_api const char * GETSYMBOLICMSG (UINT message, Map<uint, string>&m);

Shared.cpp:

#include "stdafx.h" #include "Shared.h" #include <fstream> #include <tchar.h> #include <boost/ Tokenizer.hpp> using Std::ifstream; Shared_api void Appenddebug (char *pfilename, LPVOID pBuf, int length) {FILE *pfile;if (pfilename = = NULL) {fopen_s (&AMP;PFI Le, "C:\\Test.txt", "AB");} Else{fopen_s (&pfile, Pfilename, "AB");} if (pFile! = NULL) {fwrite (PBuf, sizeof (char), length, pFile); fclose (PFile);}} Shared_api void Showdebug (LPTSTR lpstrformat, ...)//display in VS Output {Va_list Valist;va_start (valist, Lpstrformat); TCHAR Szbuf[max_path * 2] = {0};_vstprintf_s (szbuf, MAX_PATH, Lpstrformat, valist); OutputDebugString (SZBUF);} The hexadecimal string is converted to decimal int hextodec (string strhex) {int nret = 0;if (strhex.at (1) = = ' x ') {strhex = Strhex.substr (2);} int nlen = Strhex.size (); int nbase = 1;int para = 0;char ch = 0;for (int i = nLen-1, bi = 0; I >= 0; I--, bi++) {ch = St rhex.at (i); if (ch >= ' 0 ' && ch <= ' 9 ') {para = ch-' 0 ';} else if (Ch >= ' a ' && ch <= ' F ') {para = ch-' a ' + 10;} ELSE if (CH >= ' a ' && ch <= ' F ') {para = ch-' a ' + 10;} else//illegal character {return-1;} Nret + = para * nbase;nbase *= 16;} return nret;} Shared_api void Initsymbolicmsg (Map<uint, string> &mapsymbolicmsgs) {ifstream Ifs;ifs.open ("C:\\ SymbolicMessages.h ", std::ios::in); Mapsymbolicmsgs.clear (); if (!ifs.is_open ()) {return;} Boost::char_separator<char> Custcs ("");//Specify char line[256] = {0};string Strline;while (!ifs.eof ()) { Ifs.getline (line, 255); strLine = line;//use "" Space to Split if (Strline.find ("#define")! = String::npos) && (strline.fi nd ("wm_") = String::npos)) {boost::tokenizer<boost::char_separator<char> > Tok (StrLine, Custcs); Boost:: tokenizer<boost::char_separator<char> >::iterator cit = Tok.begin (); cit++;if (cit = = tok.end ()) {continue;} String msg (*cit); cit++;if (cit = = tok.end ()) {continue;} String Val (*cit); UINT nval = Hextodec (val); if (nval = =-1) {continue;} Mapsymbolicmsgs.insert (Std::make_pair<uint, string> (Nval, msg));} memset (Line,0, 256);} Ifs.close ();} Shared_api const char * GETSYMBOLICMSG (UINT message, Map<uint, string> &mapsymbolicmsgs)//message converted to string {map< UINT, string>::const_iterator cit = Mapsymbolicmsgs.begin (); for (; CIT! = mapsymbolicmsgs.end (); cit++) {if (cit-> First = = message) {return (Cit->second). C_STR ();}} Return ("User_define");}


CallWndProc.dll: Monitoring Wh_callwndproc

Dllmain.cpp:

Dllmain.cpp: Defines the entry point for the DLL application. #include "stdafx.h" #include <stdio.h>void showdebug (LPTSTR lpstrformat, ...); void Stopcallwndhook (); extern hinstance G_hcwinst; BOOL apientry DllMain (hmodule hmodule,                       DWORD  ul_reason_for_call,                       lpvoid lpreserved) {switch (ul_reason_ For_call) {Case dll_process_attach:g_hcwinst = hmodule;printf ("<callwndproc>process attach\n");  Static link, dynamic link loadlibrarybreak;case dll_thread_attach:printf ("<callwndproc>thread attach\n");  Thread loading Break;case dll_thread_detach:printf ("<callwndproc>thread detach\n");  Thread Uninstall Break;case dll_process_detach:printf ("<callwndproc>process detach\n");   Static link end, dynamic link FreeLibrary, program exit Stopcallwndhook ();  Unload hook break;} return TRUE;}

CallWndProc.cpp:

#include "stdafx.h" #include <tchar.h> #include <string> #include <Windows.h> #include <stdio.h > #include ". /shared/shared.h "#pragma comment (lib,"). /debug/shared.lib ") hinstance G_hcwinst; Hhook G_hookcallwndproc;   LRESULT CALLBACK callwndhookproc (int code,wparam wparam,lparam LPARAM) {static map<uint, string> mapsymbolicmsgs; Cannot share global variables for DLL if (code = = hc_action) {pcwpstruct PMSG = (pcwpstruct) lparam;//Wh_callwndprocchar buffer[200] = {0};if (ma Psymbolicmsgs.size () = = 0) {initsymbolicmsg (MAPSYMBOLICMSGS);} sprintf_s (buffer, "%08x s MSG:%s (%04x), WParam:%08x, LParam:%08x\n", Pmsg->hwnd, Getsymbolicmsg (Pmsg->message, M APSYMBOLICMSGS), pmsg->message, (int) pmsg->wparam, (int) pmsg->lparam); Appenddebug (NULL, buffer, strlen (buffer));} Return CallNextHookEx (NULL, Code, WParam, LParam);} void Startcallwndhook (int threadId) {G_hookcallwndproc = SetWindowsHookEx (Wh_callwndproc, Callwndhookproc, G_hCwInst, THREADID);} void Stopcallwndhook () {UnhookWindowsHookEx(G_hookcallwndproc);} 

Callwndproc.def: Output function for the main program call

Libraryexportsstartcallwndhook @1


CallWndProcRetHook.dll, GetMessageHook.dll the same, no longer repeat.

Get the file fragment:

00000000 P Msg:wm_timer (0113), WPARAM:00006CFA, lparam:76c718b200000000 P Msg:wm_timer (0113), WPARAM:00006CFA, LParam  : 76c718b2000a0956 S Msg:user_define (036A), wparam:00000000, lparam:00000000000a0956 R msg:user_define (036A), LResult: 0000000000060938 P Msg:wm_timer (0113), wparam:00000001, lparam:00000000000a0956 S msg:user_define (036A), wparam:0000 0000, lparam:00000000000a0956 R msg:user_define (036A), lresult:0000000000060938 S msg:wm_windowposchanging (0046), WPa ram:00000000, lparam:004bf6b400060938 R msg:wm_windowposchanging (0046), lresult:00000000000c0944 S Msg:wm_windowposc Hanging (0046), wparam:00000000, LPARAM:004BF6B4


See: Engineering


<Win32> using hooks to intercept messages with Spy + +

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.