note : Call SetWindowsHookEx In DLL
来源:互联网 发布:软件管家360下载 编辑:程序博客网 时间:2024/06/06 04:23
在DLL 中调用SetWindowsHookEx, 要在DLL建立一个隐藏的窗体.
在消息循环有了之后, 才能调用SetWindowsHookEx.
调用DLL的代码
void CsrcExeToLoadDllDlg::OnBnClickedButtonHook(){ /// 加载dll, 由DllMain 去SetWindowsHookEx if (NULL == g_hDll) { g_hDll = LoadLibraryW(L"DllBeTest.dll"); DbgPrtW(L"LoadLibraryW(L\"DllBeTest.dll\") = 0x%p\r\n", g_hDll); }}void CsrcExeToLoadDllDlg::OnDestroy(){ if (NULL != g_hDll) { DbgPrtW(L"FreeLibrary(0x%p)\r\n", g_hDll); FreeLibrary(g_hDll); } CDialogEx::OnDestroy();}
DLL 代码
// dllmain.cpp : Defines the entry point for the DLL application.#include "stdafx.h"#include "resource.h"#include "DllBeTest.h"#define G_MY_WND_CLASS_NAME L"my wnd class name"#define G_MY_WND_TITLE_NAME L"my wnd title name"HWND g_hMsgWnd = NULL; ///< 自己建立的消息窗口句柄HHOOK g_hHookMouse = NULL;/// @fn DbgPrtW/// @brief 打印调试信息void DbgPrtW(wchar_t *fmt,...);/// @fn Thread_CreateMyWnd/// @brief 线程, 建立DLL自己的窗体, 为了使DLL拥有消息循环UINT Thread_CreateMyWnd(LPVOID lParam);/// @fn CreateMyWindow/// @brief 建立自己的窗体BOOL CreateMyWindow( HINSTANCE hInstance, int nCmdShow, wchar_t * lpcWndClass, wchar_t * lpcWndTitleName, HWND & hWndParent);ATOM MyRegisterClass(HINSTANCE hInstance, wchar_t * pcClassName);LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);void SetWndHook();void UnSetWndHook();void SetWndHook_Mouse();LRESULT CALLBACK cbProcMouse(int iCode, WPARAM wParam, LPARAM lParam);BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){ HANDLE hThread = INVALID_HANDLE_VALUE; DWORD nThreadId = 0; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { /// DLL被加载时, 就创建自己的窗口消息处理 /// 由窗口消息处理例程, 完成Hook的任务 DbgPrtW(L">> DllBeTest.dll DLL_PROCESS_ATTACH"); hThread = ::CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Thread_CreateMyWnd, 0, 0, &nThreadId); CloseHandle(hThread); } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: { /// 让窗口自然消失, 会调到UnHook if (NULL != g_hMsgWnd) SendMessage(g_hMsgWnd, WM_CLOSE, 0, 0); DbgPrtW(L">> DllBeTest.dll DLL_PROCESS_DETACH"); } break; } return TRUE;}DLLBETEST_API void __stdcall fnTest(){ /// 为了exe加载DLL用的, 空函数就行 /// 如果exe动态调用DLL, 这个函数不用调用 return;}void DbgPrtW(wchar_t *fmt,...){ va_list marker; wchar_t szBufW[4096]; ::ZeroMemory(szBufW, sizeof(szBufW)); va_start(marker, fmt); wvsprintfW(szBufW, fmt, marker); va_end(marker); OutputDebugStringW(szBufW);}UINT Thread_CreateMyWnd(LPVOID lParam){ BOOL bRc = FALSE; HWND hWndParent = NULL; HMODULE hModule = NULL; ATOM atom; MSG msg; HACCEL hAccelTable = NULL; HINSTANCE hInst = NULL; UNREFERENCED_PARAMETER(lParam); hWndParent = ::GetConsoleWindow(); hModule = ::GetModuleHandle(NULL); atom = MyRegisterClass(hModule, G_MY_WND_CLASS_NAME); if (0 == atom) { DbgPrtW(L"ERROR : MyRegisterClass\n"); } /// 窗口实例化过程一定要成功, 否则在这不停的尝试创建窗口 /// 窗口必须有资源ID(accelerator, icon, menu), 才能创建成功 do { bRc = CreateMyWindow( hModule, SW_HIDE, G_MY_WND_CLASS_NAME, G_MY_WND_TITLE_NAME, hWndParent); DbgPrtW(L"CreateMyWindow [%s]\n", bRc ? L"TRUE" : L"FALSE"); Sleep(1000); } while (!bRc); hAccelTable = LoadAccelerators( hModule, MAKEINTRESOURCE(IDR_ACCELERATOR_XX)); DbgPrtW(L">> message loop"); while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } DbgPrtW(L"<< Thread_CreateMyWnd, msg.wParam = 0x%x", msg.wParam); return (int) msg.wParam;}BOOL CreateMyWindow( HINSTANCE hInstance, int nCmdShow, wchar_t * pcWndClass, wchar_t * pcWndTitleName, HWND & hWndParent){ g_hMsgWnd = CreateWindowW( pcWndClass, pcWndTitleName, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, hWndParent, NULL, hInstance, NULL); if (NULL == g_hMsgWnd) { DbgPrtW(L"error : CreateWindowW\r\n"); return FALSE; } ShowWindow(g_hMsgWnd, nCmdShow); UpdateWindow(g_hMsgWnd); DbgPrtW(L"OK : CreateWindowW\r\n"); return TRUE;}ATOM MyRegisterClass(HINSTANCE hInstance, wchar_t * pcClassName){ WNDCLASSEXWwcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WindowProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON_XX)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_XX); wcex.lpszClassName = pcClassName; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON_XX)); return RegisterClassExW(&wcex);}LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: SetWndHook(); ///< 消息循环已经有了, 可以SetWindowsHookEx return DefWindowProc(hWnd, message, wParam, lParam); case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... EndPaint(hWnd, &ps); break; /// 窗口关闭时, WM_CLOSE >> WM_DESTROY case WM_CLOSE: DbgPrtW(L">> WM_CLOSE\r\n"); case WM_DESTROY: DbgPrtW(L">> WM_DESTROY\r\n"); UnSetWndHook();///< 这里UnHook, 在窗体被销毁之前 PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}void SetWndHook(){ if (NULL == g_hHookMouse) SetWndHook_Mouse(); /// Set Other Wnd Hook}void UnSetWndHook(){ if (NULL != g_hHookMouse) { DbgPrtW(L"UnhookWindowsHookEx(0x%p)\r\n", g_hHookMouse); UnhookWindowsHookEx(g_hHookMouse); g_hHookMouse = NULL; } else { DbgPrtW(L"NULL == g_hHookMouse, need not unHook\r\n"); } /// UnSet Other Wnd Hook}void SetWndHook_Mouse(){ DWORD dwTid = 0; DWORD dwID = 0; HWND hIEModule = NULL; hIEModule = (HWND)GetModuleHandle(NULL); DbgPrtW(L"[hIEModule] hIEModule is:0x%x \n",hIEModule); dwTid = GetWindowThreadProcessId(hIEModule,&dwID); g_hHookMouse = SetWindowsHookEx( WH_MOUSE, cbProcMouse, GetModuleHandle(NULL), dwTid); DbgPrtW(L"[g_hHookMouse] g_hHookMouse = 0x%p\r\n", g_hHookMouse);}LRESULT CALLBACK cbProcMouse(int iCode, WPARAM wParam, LPARAM lParam){ DbgPrtW(L">> callback cbProcMouse\r\n"); if (wParam == WM_LBUTTONDOWN) DbgPrtW(L"WM_LBUTTONDOWN hit~\r\n"); return CallNextHookEx(g_hHookMouse, iCode, wParam, lParam);}
<2015-0627>
maiamirehuo@csdner 发现 SetWindowsHookEx 失败, 我写了个Demo试了一下, 发现是 SetWindowsHookEx 参数给错了.
Demo下载点 : srcSetWindowsHookExOnDll_2015_0627_1510.rar
编译环境 : vs2010 vc++
参数传错的地方如下:
g_hHookMouse = SetWindowsHookEx( WH_MOUSE, (HOOKPROC)cbProcMouse, g_hModuleDll/*GetModuleHandle(NULL)*/, dwTid);另外, 为了减少对OS的影响, 放过了调试器进程(DebugView和VC2010)
运行后的效果(可以看到Hook已经生效了)
实验步骤:
* 运行 MainProgWin32.exe, 加载HookDll
* 运行 forHookTestDlg.exe, 在DebugView上可以看到捕获了鼠标按下,和空格键按下的效果.
代码预览:
HookDll
// dllmain.cpp : Defines the entry point for the DLL application.#include "stdafx.h"#include <string>#include "resource.h"#define G_MY_WND_CLASS_NAME L"my wnd class name"#define G_MY_WND_TITLE_NAME L"my wnd title name"HMODULE g_hModuleDll = NULL; ///< 本DLL被载入时的Handle, 这个Handel才是我自己的, 而不是宿主的handleHWND g_hMsgWnd = NULL; ///< 自己建立的消息窗口句柄HHOOK g_hHookMouse = NULL; ///< 当被注入的程序是console时,没有鼠标消息HHOOK g_hHookKeyboard = NULL;BOOL g_bNeedSkipHookProc = FALSE;/// @fn DbgPrtW/// @brief 打印调试信息void DbgPrtW(wchar_t *fmt,...);BOOL GetFilePathName_host(std::wstring & strPathName);BOOL IsNeedSkipHook();/// @fn Thread_CreateMyWnd/// @brief 线程, 建立DLL自己的窗体, 为了使DLL拥有消息循环UINT Thread_CreateMyWnd(LPVOID lParam);/// @fn CreateMyWindow/// @brief 建立自己的窗体BOOL CreateMyWindow( HINSTANCE hInstance, int nCmdShow, wchar_t * lpcWndClass, wchar_t * lpcWndTitleName, HWND & hWndParent);ATOM MyRegisterClass(HINSTANCE hInstance, wchar_t * pcClassName);LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);void SetWndHook();void UnSetWndHook();void SetWndHook_Mouse();LRESULT CALLBACK cbProcMouse(int iCode, WPARAM wParam, LPARAM lParam);void SetWndHook_Keyboard();LRESULT CALLBACK cbProcKeyboard(int iCode, WPARAM wParam, LPARAM lParam);BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ HANDLE hThread = INVALID_HANDLE_VALUE; DWORD nThreadId = 0; switch (ul_reason_for_call){case DLL_PROCESS_ATTACH: { g_hModuleDll = hModule; g_bNeedSkipHookProc = IsNeedSkipHook(); /// DLL被加载时, 就创建自己的窗口消息处理 /// 由窗口消息处理例程, 完成Hook的任务 DbgPrtW(L">> DllHook.dll DLL_PROCESS_ATTACH"); hThread = ::CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Thread_CreateMyWnd, 0, 0, &nThreadId); CloseHandle(hThread); } break;case DLL_THREAD_ATTACH: break;case DLL_THREAD_DETACH: break;case DLL_PROCESS_DETACH: { /// 让窗口自然消失, 会调到UnHook if (NULL != g_hMsgWnd) SendMessage(g_hMsgWnd, WM_CLOSE, 0, 0); DbgPrtW(L">> DllHook.dll DLL_PROCESS_DETACH"); }break; default: break;}return TRUE;}void DbgPrtW(wchar_t *fmt,...){ va_list marker; wchar_t szBufW[4096]; do { if (g_bNeedSkipHookProc) break; ::ZeroMemory(szBufW, sizeof(szBufW)); va_start(marker, fmt); wvsprintfW(szBufW, fmt, marker); va_end(marker); OutputDebugStringW(szBufW); } while (0);}UINT Thread_CreateMyWnd(LPVOID lParam){ BOOL bRc = FALSE; HWND hWndParent = NULL; HMODULE hModule = NULL; ATOM atom; MSG msg; HACCEL hAccelTable = NULL; HINSTANCE hInst = NULL; UNREFERENCED_PARAMETER(lParam); hWndParent = ::GetConsoleWindow(); hModule = ::GetModuleHandle(NULL); atom = MyRegisterClass(hModule, G_MY_WND_CLASS_NAME); if (0 == atom) { DbgPrtW(L"ERROR : MyRegisterClass\n"); } /// 窗口实例化过程一定要成功, 否则在这不停的尝试创建窗口 /// 窗口必须有资源ID(accelerator, icon, menu), 才能创建成功 do { bRc = CreateMyWindow( hModule, SW_HIDE, G_MY_WND_CLASS_NAME, G_MY_WND_TITLE_NAME, hWndParent); DbgPrtW(L"CreateMyWindow [%s]\n", bRc ? L"TRUE" : L"FALSE"); Sleep(1000); } while (!bRc); hAccelTable = LoadAccelerators( hModule, MAKEINTRESOURCE(IDR_ACCELERATOR_XX)); DbgPrtW(L">> message loop"); while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } DbgPrtW(L"<< Thread_CreateMyWnd, msg.wParam = 0x%x", msg.wParam); return (int) msg.wParam;}BOOL CreateMyWindow( HINSTANCE hInstance, int nCmdShow, wchar_t * pcWndClass, wchar_t * pcWndTitleName, HWND & hWndParent){ g_hMsgWnd = CreateWindowW( pcWndClass, pcWndTitleName, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, hWndParent, NULL, hInstance, NULL); if (NULL == g_hMsgWnd) { DbgPrtW(L"error : CreateWindowW\r\n"); return FALSE; } ShowWindow(g_hMsgWnd, nCmdShow); UpdateWindow(g_hMsgWnd); DbgPrtW(L"OK : CreateWindowW\r\n"); return TRUE;}ATOM MyRegisterClass(HINSTANCE hInstance, wchar_t * pcClassName){ WNDCLASSEXWwcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WindowProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON_XX)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_XX); wcex.lpszClassName = pcClassName; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON_XX)); return RegisterClassExW(&wcex);}LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: SetWndHook(); ///< 消息循环已经有了, 可以SetWindowsHookEx return DefWindowProc(hWnd, message, wParam, lParam); case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... EndPaint(hWnd, &ps); break; /// 窗口关闭时, WM_CLOSE >> WM_DESTROY case WM_CLOSE: DbgPrtW(L">> WM_CLOSE\r\n"); case WM_DESTROY: DbgPrtW(L">> WM_DESTROY\r\n"); UnSetWndHook();///< 这里UnHook, 在窗体被销毁之前 PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}void SetWndHook(){ std::wstring strPathName = L""; do { if (NULL == g_hHookMouse) SetWndHook_Mouse(); /// Set Other Wnd Hook if (NULL == g_hHookKeyboard) SetWndHook_Keyboard(); } while (0);}void UnSetWndHook(){ if (NULL != g_hHookMouse) { DbgPrtW(L"UnhookWindowsHookEx(0x%p)\r\n", g_hHookMouse); UnhookWindowsHookEx(g_hHookMouse); g_hHookMouse = NULL; } else { DbgPrtW(L"NULL == g_hHookMouse, need not unHook\r\n"); } /// UnSet Other Wnd Hook if (NULL != g_hHookKeyboard) { DbgPrtW(L"UnhookWindowsHookEx(0x%p)\r\n", g_hHookKeyboard); UnhookWindowsHookEx(g_hHookKeyboard); g_hHookKeyboard = NULL; } else { DbgPrtW(L"NULL == g_hHookKeyboard, need not unHook\r\n"); }}void SetWndHook_Mouse(){ DWORD dwTid = 0; DWORD dwID = 0; HWND hIEModule = NULL; DWORD dwErr = 0; hIEModule = (HWND)GetModuleHandle(NULL); DbgPrtW(L"[hIEModule] hIEModule is:0x%x \n",hIEModule); dwTid = GetWindowThreadProcessId(hIEModule,&dwID); if (NULL == g_hHookMouse) { /// SetWindowsHookEx 对窗口程序才有效的, 如果是控制台程序, 无效的 /// 会得到 ERROR_HOOK_NEEDS_HMOD 错误 g_hHookMouse = SetWindowsHookEx( WH_MOUSE, (HOOKPROC)cbProcMouse, g_hModuleDll/*GetModuleHandle(NULL)*/, dwTid); dwErr = GetLastError(); // WH_KEYBOARD DbgPrtW(L"[g_hHookMouse] g_hHookMouse = 0x%p\r\n", g_hHookMouse); if (NULL == g_hHookMouse) { // ERROR_HOOK_NEEDS_HMOD DbgPrtW(L"g_hHookMouse SetWindowsHookEx LastError = %d", dwErr); } }}void SetWndHook_Keyboard(){ DWORD dwTid = 0; DWORD dwID = 0; HWND hIEModule = NULL; DWORD dwErr = 0; hIEModule = (HWND)GetModuleHandle(NULL); DbgPrtW(L"[hIEModule] hIEModule is:0x%x \n",hIEModule); dwTid = GetWindowThreadProcessId(hIEModule,&dwID); if (NULL == g_hHookKeyboard) { /// SetWindowsHookEx 对窗口程序才有效的, 如果是控制台程序, 无效的 /// 会得到 ERROR_HOOK_NEEDS_HMOD 错误 g_hHookKeyboard = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)cbProcKeyboard, g_hModuleDll /*GetModuleHandle(NULL)*/, 0 /*dwTid*/); dwErr = GetLastError(); DbgPrtW(L"[g_hHookKeyboard] g_hHookKeyboard = 0x%p\r\n", g_hHookKeyboard); if (NULL == g_hHookKeyboard) { // ERROR_HOOK_NEEDS_HMOD DbgPrtW(L"g_hHookKeyboard SetWindowsHookEx LastError = %d", dwErr); } }}LRESULT CALLBACK cbProcMouse(int iCode, WPARAM wParam, LPARAM lParam){ do { if (g_bNeedSkipHookProc) break; if (wParam == WM_LBUTTONDOWN) DbgPrtW(L"WM_LBUTTONDOWN hit~\r\n"); } while (0); return CallNextHookEx(g_hHookMouse, iCode, wParam, lParam);}LRESULT CALLBACK cbProcKeyboard(int iCode, WPARAM wParam, LPARAM lParam){ do { if (g_bNeedSkipHookProc) break; if (HC_ACTION == iCode) { if (wParam == VK_SPACE) { DbgPrtW(L"VK_SPACE was pressed~\r\n"); } } } while (0); return CallNextHookEx(g_hHookKeyboard, iCode, wParam, lParam);}BOOL GetFilePathName_host(std::wstring & strPathName){ WCHAR szModuleMe[MAX_PATH + 1] = { L'\0'}; ::GetModuleFileName(NULL, szModuleMe, MAX_PATH); strPathName = szModuleMe; return TRUE;}BOOL IsNeedSkipHook(){ BOOL bRc = TRUE; std::wstring strPathName = L""; do { if (!GetFilePathName_host(strPathName)) break; // Dbgview.exe devenv.exe // 放过调试器, 要不桌面都挂掉了 if ((std::wstring::npos != strPathName.find(L"Dbgview.exe")) || (std::wstring::npos != strPathName.find(L"devenv.exe"))) { break; } bRc = FALSE; ///< 如果HookDll的宿主不是调试器进程, 就不需要跳过Hook的处理 } while (0); return bRc;}
首次调用HookDll的主程序(win32窗口程序)预览
// MainProgWin32.cpp : Defines the entry point for the application.//#include "stdafx.h"#include <crtdbg.h>#include "MainProgWin32.h"#include "../HookDll/HookDllExport.h"#define MAX_LOADSTRING 100// Global Variables:HINSTANCE hInst;// current instanceTCHAR szTitle[MAX_LOADSTRING];// The title bar textTCHAR szWindowClass[MAX_LOADSTRING];// the main window class name// HOOKDLL_API LONGLONG WINAPI version();typedef HOOKDLL_API LONGLONG (WINAPI *PFN_version)();HMODULE g_hDll = NULL;VOID DbgPrtW(LPCTSTR lpFmt, ...);void loadHookDll(const WCHAR* pcDllPathName);void unLoadHookDll(HMODULE& hDll);LRESULT CALLBACK WndProc_WM_CREATE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);LRESULT CALLBACK WndProc_WM_DESTROY(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);// Forward declarations of functions included in this code module:ATOMMyRegisterClass(HINSTANCE hInstance);BOOLInitInstance(HINSTANCE, int);LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here.MSG msg;HACCEL hAccelTable;// Initialize global stringsLoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_MAINPROGWIN32, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// Perform application initialization:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MAINPROGWIN32));// Main message loop:while (GetMessage(&msg, NULL, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){TranslateMessage(&msg);DispatchMessage(&msg);}}return (int) msg.wParam;}//// FUNCTION: MyRegisterClass()//// PURPOSE: Registers the window class.//// COMMENTS://// This function and its usage are only necessary if you want this code// to be compatible with Win32 systems prior to the 'RegisterClassEx'// function that was added to Windows 95. It is important to call this function// so that the application will get 'well formed' small icons associated// with it.//ATOM MyRegisterClass(HINSTANCE hInstance){WNDCLASSEX wcex;wcex.cbSize = sizeof(WNDCLASSEX);wcex.style= CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc= WndProc;wcex.cbClsExtra= 0;wcex.cbWndExtra= 0;wcex.hInstance= hInstance;wcex.hIcon= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINPROGWIN32));wcex.hCursor= LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName= MAKEINTRESOURCE(IDC_MAINPROGWIN32);wcex.lpszClassName= szWindowClass;wcex.hIconSm= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));return RegisterClassEx(&wcex);}//// FUNCTION: InitInstance(HINSTANCE, int)//// PURPOSE: Saves instance handle and creates main window//// COMMENTS://// In this function, we save the instance handle in a global variable and// create and display the main program window.//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){ HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE;}//// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)//// PURPOSE: Processes messages for the main window.//// WM_COMMAND- process the application menu// WM_PAINT- Paint the main window// WM_DESTROY- post a quit message and return////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;switch (message){case WM_COMMAND:wmId = LOWORD(wParam);wmEvent = HIWORD(wParam);// Parse the menu selections:switch (wmId){case IDM_ABOUT:DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}break; case WM_CREATE: WndProc_WM_CREATE(hWnd, message, wParam, lParam); break;case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// TODO: Add any drawing code here...EndPaint(hWnd, &ps);break;case WM_DESTROY: WndProc_WM_DESTROY(hWnd, message, wParam, lParam);PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;}// Message handler for about box.INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){UNREFERENCED_PARAMETER(lParam);switch (message){case WM_INITDIALOG:return (INT_PTR)TRUE;case WM_COMMAND:if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL){EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}break;}return (INT_PTR)FALSE;}void loadHookDll(const WCHAR* pcDllPathName){ /// 加载dll, 由DllMain 去SetWindowsHookEx if ((NULL == g_hDll) && (NULL != pcDllPathName)) { g_hDll = LoadLibraryW(pcDllPathName); DbgPrtW(L"LoadLibraryW(L\"%s\") = 0x%p\r\n", pcDllPathName, g_hDll); }}void unLoadHookDll(HMODULE& hDll){ if (NULL != hDll) { FreeLibrary(hDll); hDll = NULL; }}LRESULT CALLBACK WndProc_WM_CREATE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ LONGLONG llVer = 0; PFN_version pfn_version = NULL; loadHookDll(L"HookDll.dll"); pfn_version = (PFN_version)GetProcAddress(g_hDll, "version"); _ASSERT(NULL != pfn_version); if (NULL != pfn_version) { llVer = pfn_version(); _tprintf(L"HookDll version = 0x%I64x\r\n", llVer); // dll load ok and can call it's interface } return S_OK;}LRESULT CALLBACK WndProc_WM_DESTROY(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ unLoadHookDll(g_hDll); return S_OK;}VOID DbgPrtW(LPCTSTR lpFmt, ...){ WCHAR g_dbgmsg[4096]; ///< @todo ls 如果要显示的内容, 超过4096会报错, 需要再处理 va_list arglist; va_start(arglist, lpFmt); _vsnwprintf(g_dbgmsg,sizeof(g_dbgmsg), lpFmt, arglist); va_end(arglist); OutputDebugString(g_dbgmsg);};
<2015-0628>
maiamirehuo@csdn 看了上面的Demo, 问到要怎么Hook自己的进程.
我写了个Demo工程给他.
效果图:
工程下载点: srcHookMySelf_2015_0628_0215.rar
工程预览:
// HookMySelf.cpp : Defines the entry point for the application.//#include "stdafx.h"#include "HookMySelf.h"#define MAX_LOADSTRING 100// Global Variables:HINSTANCE hInst;// current instanceTCHAR szTitle[MAX_LOADSTRING];// The title bar textTCHAR szWindowClass[MAX_LOADSTRING];// the main window class nameHHOOK g_hHookMouse = NULL; ///< 当被注入的程序是console时,没有鼠标消息HHOOK g_hHookKeyboard = NULL;// Forward declarations of functions included in this code module:ATOMMyRegisterClass(HINSTANCE hInstance);BOOLInitInstance(HINSTANCE, int);LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);void DbgPrtW(wchar_t *fmt,...);void SetWndHook();void UnSetWndHook();void SetWndHook_Mouse();LRESULT CALLBACK cbProcMouse(int iCode, WPARAM wParam, LPARAM lParam);void SetWndHook_Keyboard();LRESULT CALLBACK cbProcKeyboard(int iCode, WPARAM wParam, LPARAM lParam);int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here.MSG msg;HACCEL hAccelTable;// Initialize global stringsLoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_HOOKMYSELF, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// Perform application initialization:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HOOKMYSELF));// Main message loop:while (GetMessage(&msg, NULL, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){TranslateMessage(&msg);DispatchMessage(&msg);}}return (int) msg.wParam;}//// FUNCTION: MyRegisterClass()//// PURPOSE: Registers the window class.//// COMMENTS://// This function and its usage are only necessary if you want this code// to be compatible with Win32 systems prior to the 'RegisterClassEx'// function that was added to Windows 95. It is important to call this function// so that the application will get 'well formed' small icons associated// with it.//ATOM MyRegisterClass(HINSTANCE hInstance){WNDCLASSEX wcex;wcex.cbSize = sizeof(WNDCLASSEX);wcex.style= CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc= WndProc;wcex.cbClsExtra= 0;wcex.cbWndExtra= 0;wcex.hInstance= hInstance;wcex.hIcon= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HOOKMYSELF));wcex.hCursor= LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName= MAKEINTRESOURCE(IDC_HOOKMYSELF);wcex.lpszClassName= szWindowClass;wcex.hIconSm= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));return RegisterClassEx(&wcex);}//// FUNCTION: InitInstance(HINSTANCE, int)//// PURPOSE: Saves instance handle and creates main window//// COMMENTS://// In this function, we save the instance handle in a global variable and// create and display the main program window.//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){ HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE;}//// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)//// PURPOSE: Processes messages for the main window.//// WM_COMMAND- process the application menu// WM_PAINT- Paint the main window// WM_DESTROY- post a quit message and return////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;switch (message){case WM_COMMAND:wmId = LOWORD(wParam);wmEvent = HIWORD(wParam);// Parse the menu selections:switch (wmId){case IDM_ABOUT:DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}break;case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// TODO: Add any drawing code here...EndPaint(hWnd, &ps);break; case WM_CREATE: SetWndHook(); break;case WM_DESTROY: UnSetWndHook();PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;}// Message handler for about box.INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){UNREFERENCED_PARAMETER(lParam);switch (message){case WM_INITDIALOG:return (INT_PTR)TRUE;case WM_COMMAND:if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL){EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}break;}return (INT_PTR)FALSE;}void SetWndHook(){ do { if (NULL == g_hHookMouse) SetWndHook_Mouse(); /// Set Other Wnd Hook if (NULL == g_hHookKeyboard) SetWndHook_Keyboard(); } while (0);}void UnSetWndHook(){ if (NULL != g_hHookMouse) { DbgPrtW(L"UnhookWindowsHookEx(0x%p)\r\n", g_hHookMouse); UnhookWindowsHookEx(g_hHookMouse); g_hHookMouse = NULL; } else { DbgPrtW(L"NULL == g_hHookMouse, need not unHook\r\n"); } /// UnSet Other Wnd Hook if (NULL != g_hHookKeyboard) { DbgPrtW(L"UnhookWindowsHookEx(0x%p)\r\n", g_hHookKeyboard); UnhookWindowsHookEx(g_hHookKeyboard); g_hHookKeyboard = NULL; } else { DbgPrtW(L"NULL == g_hHookKeyboard, need not unHook\r\n"); }}void SetWndHook_Mouse(){ DWORD dwTid = 0; DWORD dwID = 0; HWND hIEModule = NULL; DWORD dwErr = 0; hIEModule = (HWND)GetModuleHandle(NULL); DbgPrtW(L"[hIEModule] hIEModule is:0x%x \n",hIEModule); dwTid = GetWindowThreadProcessId(hIEModule,&dwID); if (NULL == g_hHookMouse) { /// SetWindowsHookEx 对窗口程序才有效的, 如果是控制台程序, 无效的 /// 会得到 ERROR_HOOK_NEEDS_HMOD 错误 g_hHookMouse = SetWindowsHookEx( WH_MOUSE, (HOOKPROC)cbProcMouse, NULL /*GetModuleHandle(NULL)*/, ::GetCurrentThreadId()); dwErr = GetLastError(); // WH_KEYBOARD DbgPrtW(L"[g_hHookMouse] g_hHookMouse = 0x%p\r\n", g_hHookMouse); if (NULL == g_hHookMouse) { // ERROR_HOOK_NEEDS_HMOD DbgPrtW(L"g_hHookMouse SetWindowsHookEx LastError = %d", dwErr); } }}void SetWndHook_Keyboard(){ DWORD dwTid = 0; DWORD dwID = 0; HWND hIEModule = NULL; DWORD dwErr = 0; hIEModule = (HWND)GetModuleHandle(NULL); DbgPrtW(L"[hIEModule] hIEModule is:0x%x \n",hIEModule); dwTid = GetWindowThreadProcessId(hIEModule,&dwID); if (NULL == g_hHookKeyboard) { /// SetWindowsHookEx 对窗口程序才有效的, 如果是控制台程序, 无效的 /// 会得到 ERROR_HOOK_NEEDS_HMOD 错误 g_hHookKeyboard = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)cbProcKeyboard, NULL /*GetModuleHandle(NULL)*/, ::GetCurrentThreadId()); dwErr = GetLastError(); DbgPrtW(L"[g_hHookKeyboard] g_hHookKeyboard = 0x%p\r\n", g_hHookKeyboard); if (NULL == g_hHookKeyboard) { // ERROR_HOOK_NEEDS_HMOD DbgPrtW(L"g_hHookKeyboard SetWindowsHookEx LastError = %d", dwErr); } }}LRESULT CALLBACK cbProcMouse(int iCode, WPARAM wParam, LPARAM lParam){ do { if (wParam == WM_LBUTTONDOWN) DbgPrtW(L"WM_LBUTTONDOWN hit~\r\n"); } while (0); return CallNextHookEx(g_hHookMouse, iCode, wParam, lParam);}LRESULT CALLBACK cbProcKeyboard(int iCode, WPARAM wParam, LPARAM lParam){ do { if (HC_ACTION == iCode) { if (wParam == VK_SPACE) { DbgPrtW(L"VK_SPACE was pressed~\r\n"); } } } while (0); return CallNextHookEx(g_hHookKeyboard, iCode, wParam, lParam);}void DbgPrtW(wchar_t *fmt,...){ va_list marker; wchar_t szBufW[4096]; do { ::ZeroMemory(szBufW, sizeof(szBufW)); va_start(marker, fmt); wvsprintfW(szBufW, fmt, marker); va_end(marker); OutputDebugStringW(szBufW); } while (0);}
- note : Call SetWindowsHookEx In DLL
- How to Call C# DLL in Delphi7
- Risk in MBCS call Unicode dll.
- SETWINDOWSHOOKEX
- SetWindowsHookEx
- SetWindowsHookEx
- SetWindowsHookEx
- SetWindowsHookEx
- SetWindowsHookEx
- SetWindowsHookEx
- SetWindowsHookEx
- SetWindowsHookEx
- Using SetWindowsHookEx for DLL Injection on Windows
- Let EXE call Dll source in VS2010 (VS2010Dll调试方法)
- Let EXE call Dll source in VS2010 (VS2010Dll调试方法)
- inject dll note it
- DLL线程注入 SetWindowsHookEx complete example source code
- Call dll function..
- mfc中CImageList的使用
- Windows下如何自定义窗体控件
- MFC工具栏添加自定义控件
- TCP/IP详讲
- 黑马程序员——Html、Css、JavaScript、Dom
- note : Call SetWindowsHookEx In DLL
- Html.RenderPartial与Html.RenderAction 用法
- 数字出现次数
- 软件测试
- Windows Server 2012 R2超级虚拟化之二 增强的用户体验
- Javascript自定义菜单插件
- 卡特兰-HDU1515-HDU2067
- [C++] num++ v.s. ++num in C++
- 使用状态机实现简单的AI