钩子是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