钩子是Windows留给我们的后门。对消息进行过滤,比方快捷键,程序监控键盘,获取键盘动作,再进行判断。
详细的前往:http://blog.csdn.net/sunears/article/details/1861568
添加钩子:SetWindowsHookEx
HHOOK WINAPI SetWindowsHookEx( _In_ int idHook, _In_ HOOKPROC lpfn, _In_ HINSTANCE hMod, _In_ DWORD dwThreadId );
idHook: 钩子类型,监控消息这里用到的是WH_CALLWNDPROC(SendMessage发送), WH_GETMESSAGE(PostMessage发送), 并且获取返回值WH_CALLWNDPROCRET.
lpfn: 监控另外的进程的线程,需要定义在DLL中的钩子回调函数
hMod: DLL句柄
dwThreadId: 监控的进程的线程ID
卸载钩子:UnhookWIndowsHookex
BOOL WINAPI UnhookWindowsHookEx( _In_ HHOOK hhk );
hhk: SetWindowsHookEx返回的HHOOK
监视->日志消息:
查找程序:找到窗口句柄;
消息:定义接收消息类型;
输出:定义消息的输出附加信息,这里我们加上“原始消息参数”,“原始返回值”;
示例图如下:
前面为接收消息的句柄, P/S/R定义如下, 之后的不用说。
Spy++帮助:
| 代码 | 意义 | 
|---|---|
| P | 使用 PostMessage 函数将消息发送到队列。没有可用的关于消息的最终处置的信息。 | 
| S | 使用 SendMessage 函数发送消息。这意味着,发送方在接收方处理和返回该消息之前不会重新获取控制。因此,接收方可以将一个返回值传送回发送方。 | 
| s | 消息已发送,但安全性阻止对返回值的访问。 | 
| R | 每个“S”行都具有一个对应的列出消息返回值的“R”(返回)行。有时消息调用被嵌套,这意味着一个消息处理程序发送了另一个消息。 | 
Spy++使用的也是钩子的方式截获的消息。
根据:http://www.yourdelphi.com/topic_372749_d537.htm
Win32程序对不同类型Message的处理过程不一样,对于Post过来的Message(通过PostMessage发送),会由GetMessage来处理,对于Send过来的Message(通过SendMessage发送),则由CallWndProc来处理,并在处理完成后执行CallWndRetProc,所以要HOOK并区分这两种Message需要同时处理三个HOOK:WH_GETMESSAGE、WH_CALLWNDPROC和WH_CALLWNDPROCRET。 
所以: 
1、‘P‘: 通过WH_GETMESSAGE可以得到PostMessage发送的Message 
2、‘S‘: 通过WH_CALLWNDPROC可以得到SendMessage发送的Message 
3、‘R‘: 通过WH_CALLWNDPROCRET则可以得到SendMessage的结果,也就是你要的IResult
所以仿照Spy++的思路已经出来了。
设置3个线程钩子,顺序监控WH_CALLWNDPROC, WH_CALLWNDPROCRET, WH_GETMESSAGE。
MyCsdn.exe: 主调用程序,用户输入需要监控的exe
Shared.dll: 所有DLL共享的函数
CallWndProcHook.dll: WH_CALLWNDPROC监控
CallWndProcRetHook.dll: WH_CALLWNDPROCRET监控
GetMessageHook.dll: WH_GETMESSAGE监控
涉及到boost,注意添加boost库。
MyCsdn.exe: 获取EXE进程ID,进而获取线程ID,加载DLL,启动钩子
#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;
// 获取程序主线程ID
DWORD 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;
}
// 获取进程ID
DWORD 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))    
		{  
			::CloseHandle(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 << "The program to hook: ";
	wcin >> wstrExe;
	DWORD dwProcessId = GetProcessIdByName(wstrExe);
	if (dwProcessId == -1)
	{
		g_bThreadRunning = 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,	// 线程函数
		NULL,			// 函数参数
		0, NULL);
	while (g_bThreadRunning)
	{
		Sleep(50);
	}
	CloseHandle(hThread);
 	system("pause");
	return 0;
}
Shared.dll: 使用导出符号的方式,用于其他DLL共用的函数,写入文件,消息翻译,使用到boost(我的博文:boost安装)
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(&pFile, "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, ...) // 显示在VS的输出中
{
	va_list VAList;
	va_start(VAList, lpstrFormat);
	TCHAR szBuf[MAX_PATH * 2] = {0};
	_vstprintf_s(szBuf, MAX_PATH, lpstrFormat, VAList);
	OutputDebugString(szBuf);
}
// 十六进制字符串转为十进制
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 = strHex.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	// 非法字符
		{
			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(" ");	// 自己指定
	char line[256] = {0};
	string strLine;
	while (!ifs.eof())
	{
		ifs.getline(line, 255);
		strLine = line;
		// 使用" "空格进行分割
		if ( (strLine.find("#define") != string::npos) && (strLine.find("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) // 消息转换为字符串
{
	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: 监控WH_CALLWNDPROC
dllmain.cpp:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#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");  // 静态链接,动态链接LoadLibrary
		break;
	case DLL_THREAD_ATTACH:
		printf("<CallWndProc>thread attach\n");  // 线程中加载
		break;
	case DLL_THREAD_DETACH:
		printf("<CallWndProc>thread detach\n");  // 线程中卸载
		break;
	case DLL_PROCESS_DETACH:
		printf("<CallWndProc>process detach\n");   // 静态链接结束,动态链接FreeLibrary,程序退出
		StopCallWndHook();  // 卸载钩子
		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;   // 不能共享DLL的全局变量
	if (code == HC_ACTION) 
	{
		PCWPSTRUCT pMsg = (PCWPSTRUCT)lParam;		// WH_CALLWNDPROC
		char buffer[200] = {0};
		if (mapSymbolicMsgs.size() == 0)
		{
			InitSymbolicMsg(mapSymbolicMsgs);
		}
		sprintf_s(buffer, "%08X S Msg: %s(%04X), wParam: %08X, lParam: %08X\n", pMsg->hwnd, 
			GetSymbolicMsg(pMsg->message, mapSymbolicMsgs), 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: 输出函数, 用于主程序调用
LIBRARY EXPORTS StartCallWndHook @1
CallWndProcRetHook.dll, GetMessageHook.dll同理,不再赘述。
获取而得的文件片段:
00000000 P Msg: WM_TIMER(0113), wParam: 00006CFA, lParam: 76C718B2 00000000 P Msg: WM_TIMER(0113), wParam: 00006CFA, lParam: 76C718B2 000A0956 S Msg: User_Define(036A), wParam: 00000000, lParam: 00000000 000A0956 R Msg: User_Define(036A), lResult: 00000000 00060938 P Msg: WM_TIMER(0113), wParam: 00000001, lParam: 00000000 000A0956 S Msg: User_Define(036A), wParam: 00000000, lParam: 00000000 000A0956 R Msg: User_Define(036A), lResult: 00000000 00060938 S Msg: WM_WINDOWPOSCHANGING(0046), wParam: 00000000, lParam: 004BF6B4 00060938 R Msg: WM_WINDOWPOSCHANGING(0046), lResult: 00000000 000C0944 S Msg: WM_WINDOWPOSCHANGING(0046), wParam: 00000000, lParam: 004BF6B4
详见:工程下载地址
原文地址:http://blog.csdn.net/meta_cpp/article/details/42966489