Dll注入:Windows消息鉤子注入

SetWindowsHook() 是Windows消息處理機制的一個平臺,應用程序能夠在上面設置子程以監視指定窗口的某種消息,並且所監視的窗口能夠是其餘進程所建立的。當消息到達後,在目標窗口處理函數以前處理它。ios

鉤子機制容許應用程序截獲處理window消息或特定事件。ide

HHOOK WINAPI SetWindowsHookEx(
__in int idHook, \\鉤子類型
__in HOOKPROC lpfn, \\回調函數地址
__in HINSTANCE hMod, \\實例句柄
__in DWORD dwThreadId); \\線程ID

使用API函數SetWindowsHookEx()把一個應用程序定義的鉤子子程安裝到鉤子鏈表中。 SetWindowsHookEx函數老是在Hook鏈的開頭安裝Hook子程。當指定類型的Hook監視的事件發生時,系統就調用與這個Hook關聯的 Hook鏈的開頭的Hook子程。每個Hook鏈中的Hook子程都決定是否把這個事件傳遞到下一個Hook子程。Hook子程傳遞事件到下一個 Hook子程須要調用CallNextHookEx函數。函數

系統鉤子

SetWindowsHookEx()函數的最後一個參數決定了此鉤子是系統鉤子仍是線程鉤子。佈局

線程鉤子

線程勾子用於監視指定線程的事件消息。線程勾子通常在當前線程或者當前線程派生的線程內。
 
系統勾子監視系統中的全部線程的事件消息。由於系統勾子會影響系統中全部的應用程序,因此勾子函數必須放在獨立的動態連接庫(DLL) 中。系統自動將包含"鉤子回調函數"的DLL映射到受 鉤子函數影響的全部進程的 地址空間中,即將這個DLL注入了那些進程。
 
若是對於同一事件(如鼠標消息)既安裝了線程鉤子又安裝了 系統鉤子,那麼系統會自動先調用線程鉤子,而後調用系統鉤子。
 
對同一事件消息可安裝多個鉤子處理過程,這些勾子處理過程造成了鉤子鏈。當前鉤子處理結束後應把鉤子信息傳遞給下一個 鉤子函數
 
每一種類型的Hook可使應用程序可以監視不一樣類型的 系統消息處理機制。下面描述全部能夠利用的Hook類型。
一、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks
WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你能夠監視發送到窗口過程的消息。系統在消息發送到接收窗口過程以前調用WH_CALLWNDPROC Hook子程,而且在窗口過程處理完消息以後調用WH_CALLWNDPROCRET Hook子程。
WH_CALLWNDPROCRET Hook傳遞 指針到CWPRETSTRUCT結構,再傳遞到Hook子程。
CWPRETSTRUCT結構包含了來自處理消息的窗口過程的返回值,一樣也包括了與這個消息關聯的消息參數。
二、WH_CBT Hook
在如下事件以前,系統都會調用WH_CBT Hook子程,這些事件包括:
1)激活,創建,銷燬,最小化,最大化,移動,改變尺寸等窗口事件;
2)完成系統指令;
3)來自系統消息隊列中的移動鼠標,鍵盤事件;
4)設置 輸入焦點事件;
5)同步系統消息隊列事件。
Hook子程的返回值肯定系統是否容許或者防止這些操做中的一個。
三、WH_DEBUG Hook
系統調用系統中與其餘Hook關聯的Hook子程以前,系統會調用WH_DEBUG Hook子程。你可使用這個Hook來決定是否容許系統調用與其餘Hook關聯的Hook子程。
四、WH_FOREGROUNDIDLE Hook
當應用程序的前臺 線程處於空閒狀態時,可使用WH_FOREGROUNDIDLE Hook執行低優先級的任務。當應用程序的前臺線程大概要變成空閒狀態時,系統就會調用WH_FOREGROUNDIDLE Hook子程。
五、WH_GETMESSAGE Hook
應用程序使用WH_GETMESSAGE Hook來監視從GetMessage or PeekMessage函數返回的消息。你可使用WH_GETMESSAGE Hook去監視鼠標和鍵盤輸入,以及其餘發送到 消息隊列中的消息。
六、WH_JOURNALPLAYBACK Hook
WH_JOURNALPLAYBACK Hook使應用程序能夠插入消息到系統消息隊列。可使用這個Hook回放經過使用WH_JOURNALRECORD Hook記錄下來的連續的鼠標和鍵盤事件。只要WH_JOURNALPLAYBACK Hook已經安裝,正常的鼠標和鍵盤事件就是無效的。
WH_JOURNALPLAYBACK Hook是全局Hook,它不能象線程特定Hook同樣使用。
WH_JOURNALPLAYBACK Hook返回超時值,這個值告訴系統在處理來自回放Hook當前消息以前須要等待多長時間(毫秒)。這就使Hook能夠控制實時事件的回放。
WH_JOURNALPLAYBACK是system-wide local hooks,它們不會被注射到任何行程位址空間。
七、WH_JOURNALRECORD Hook
WH_JOURNALRECORD Hook用來監視和記錄輸入事件。典型的,可使用這個Hook記錄連續的鼠標和鍵盤事件,而後經過使用WH_JOURNALPLAYBACK Hook來回放。
WH_JOURNALRECORD Hook是全局Hook,它不能象線程特定Hook同樣使用。
WH_JOURNALRECORD是system-wide local hooks,它們不會被注射到任何行程位址空間。
八、WH_KEYBOARD Hook
在應用程序中,WH_KEYBOARD Hook用來監視WM_KEYDOWN and WM_KEYUP消息,這些消息經過GetMessage or PeekMessage function返回。可使用這個Hook來監視輸入到 消息隊列中的鍵盤消息。
九、WH_KEYBOARD_LL Hook
WH_KEYBOARD_LL Hook監視輸入到線程消息隊列中的鍵盤消息。
十、WH_MOUSE Hook
WH_MOUSE Hook監視從GetMessage 或者 PeekMessage 函數返回的鼠標消息。使用這個Hook監視輸入到 消息隊列中的鼠標消息。
十一、WH_MOUSE_LL Hook
WH_MOUSE_LL Hook監視輸入到線程消息隊列中的鼠標消息。
十二、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks
WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使咱們能夠監視菜單,滾動條, 消息框,對話框消息而且發現用戶使用ALT+TAB or ALT+ESC 組合鍵切換窗口。WH_MSGFILTER Hook只能監視傳遞到菜單,滾動條,消息框的消息,以及傳遞到經過安裝了Hook子程的應用程序創建的對話框的消息。WH_SYSMSGFILTER Hook監視全部應用程序消息。
WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使咱們能夠在模式循環期間過濾消息,這等價於在主 消息循環中過濾消息。
經過調用CallMsgFilter function能夠直接的調用WH_MSGFILTER Hook。經過使用這個函數,應用程序可以在模式循環期間使用相同的代碼去過濾消息,如同在主消息循環裏同樣。
1三、WH_SHELL Hook
外殼應用程序可使用WH_SHELL Hook去接收重要的通知。當外殼應用程序是激活的而且當頂層窗口創建或者銷燬時, 系統調用WH_SHELL Hook子程。
WH_SHELL 共有5鍾狀況:
1)只要有個top-level、unowned 窗口被產生、起做用、或是被摧毀;
2)當Taskbar須要重畫某個按鈕;
3)當系統須要顯示關於Taskbar的一個程序的最小化形式;
4)當現在的 鍵盤佈局狀態改變;
5)當使用者按Ctrl+Esc去執行Task Manager(或相同級別的程序)。
 
使用鍵盤鉤子實現注入的一個Demo
實現過程:
1.在動態庫裏導出一個本身的函數MyMessageProcess,在這裏面但是實現本身對消息的處理。
2.輸入所須要注入的進程ID,並得到線程ID
3.SetWindowsHookEx(WH_KEYBOARD, MyMessageProcess , DllModule, ThreadID);
4.在注入的進程內輸入鍵盤消息 會觸發Dll內的MyMessageProcess,實現鉤子注入
cpp部分:
#include "stdafx.h"
#include <Windows.h>
#include<TlHelp32.h>
#include<iostream>

using namespace std;

BOOL InjectDllBySetWindowsHook(ULONG32 ulTargetProcessID);
DWORD getThreadID(ULONG32 ulTargetProcessID);
int main()
{

    ULONG32 ulTargetProcessID;
    cout << "請輸入目標進程ID:";
    cin >> ulTargetProcessID;

    if (!InjectDllBySetWindowsHook(ulTargetProcessID))
    {
        cout << "Set Hook Unsuccess!\r\n" << endl;
        return 0;
    }
    cout << "Inject Success!\r\n" << endl;
    return 0;
    return 0;
}


BOOL InjectDllBySetWindowsHook(ULONG32 ulTargetProcessID)
{
    HANDLE  TargetProcessHandle = NULL;
    TargetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ulTargetProcessID);

    if (NULL == TargetProcessHandle)
    {
        printf("Couldn't get Target Process Handle\r\n");
        return FALSE;
    }

    HMODULE DllModule = LoadLibrary(L"Dll.dll");

    if (DllModule == NULL)
    {
        printf("cannt find dll\r\n");
        return FALSE;
    }

    //獲取Dll中導出的函數的地址
    HOOKPROC   Sub_1Address = NULL;
    Sub_1Address = (HOOKPROC)GetProcAddress(DllModule, "MyMessageProcess");
    if (Sub_1Address == NULL)
    {
        printf("cannt found MyMessageProcess");
        return FALSE;
    }

    DWORD ThreadID = getThreadID(ulTargetProcessID);

    HHOOK Handle = SetWindowsHookEx(WH_KEYBOARD,
        Sub_1Address, DllModule, ThreadID);

    if (Handle == NULL)
    {
        printf("cannt hook\r\n");
        return FALSE;
    }
    printf("hook success\r\n");
    getchar();
    getchar();
    getchar();
    UnhookWindowsHookEx(Handle);

    FreeLibrary(DllModule);
}


DWORD getThreadID(ULONG32 ulTargetProcessID)
{
    HANDLE Handle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (Handle != INVALID_HANDLE_VALUE)
    {
        THREADENTRY32 te;
        te.dwSize = sizeof(te);
        if (Thread32First(Handle, &te))
        {
            do
            {
                if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
                {
                    if (te.th32OwnerProcessID == ulTargetProcessID)
                    {
                        HANDLE hThread = OpenThread(READ_CONTROL, FALSE, te.th32ThreadID);
                        if (!hThread)
                        {
                            printf("Couldn't get thread handle\r\n");
                        }
                        else
                        {
                            return te.th32ThreadID;
                        }
                    }
                }
            } while (Thread32Next(Handle, &te));
        }
    }
    CloseHandle(Handle);
    return (DWORD)0;
}

Dll部分:spa

#pragma data_seg(SHARD_SEG_NAME)  
static HHOOK g_hHook;
#pragma data_seg()

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        MessageBox(NULL, L"Inject Success!", L"1", 0);
    }
    
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C"

__declspec(dllexport)LRESULT MyMessageProcess(int Code, WPARAM wParam, LPARAM lParam)
{
    //  
    //你本身對消息的處理  
    //  
    MessageBox(NULL, L"GetMessage!", L"Message", 0);
    return CallNextHookEx(g_hHook, Code, wParam, lParam);
}

可參考百度百科線程

相關文章
相關標籤/搜索