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);}




原创粉丝点击