全局鈎子注入DLL


0x00 原理說明:

Windows系統基於消息驅動,每個進程都有各自的消息隊列,每個進程都會GetMessage

調用WIN32API SetWindowsHookEx 可以在系統的鈎子鏈中安裝一個指定的鈎子

如果使用 SetWindowsHookEx 安裝 WH_GETMESSAGE 類型的鈎子,並且鈎子過程函數放在DLL中,就可以實現全局的DLL注入

0x01 關鍵API說明:

實現全局鈎子注入DLL最核心的API:

HHOOK WINAPI SetWindowsHookEx(
  _In_ int       idHook,
  _In_ HOOKPROC  lpfn,
  _In_ HINSTANCE hMod,
  _In_ DWORD     dwThreadId
);

參數說明:

1、 idHook:鈎子類型,此處填寫WH_GETMESSAGE

2、 lpfn:鈎子的過程函數,也就是鈎子觸發的時候要執行的代碼

3、 hMod:鈎子過程函數所在的DLL模塊句柄,在DLL初始化的獲得(DllMain的第一個參數)

4、 dwThreadId:與鈎子程序關聯的線程ID,此處填0,表示關聯系統中的所有線程

返回值:

鈎子句柄

0x02 編寫需要注入的DLL:

DLL大致需要實現以下內容:

1、 設置鈎子

2、 取消鈎子

3、 鈎子過程函數

4、 導出相關函數

DLL的主要實現代碼如下:

#include "pch.h"

HHOOK g_hHook;
HMODULE g_hModule;

LRESULT CALLBACK GetMsgProc(
     _In_ int    code,
     _In_ WPARAM wParam,
     _In_ LPARAM lParam
)
{
     return CallNextHookEx(g_hHook, code, wParam, lParam);
}

BOOL LoadHook(void)
{
     g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hModule, 0);
     if (g_hHook){
         MessageBox(NULL, TEXT("鈎子加載成功!"), TEXT("提示"), MB_OK);
         return TRUE;   
     }
     else
         return FALSE;
}

VOID UnloadHook(void)
{
     if(g_hHook)
         UnhookWindowsHookEx(g_hHook);
}

BOOL APIENTRY DllMain( HMODULE hModule,
                        DWORD  ul_reason_for_call,
                        LPVOID lpReserved
                      )
{
     switch (ul_reason_for_call)
     {
     case DLL_PROCESS_ATTACH:
         g_hModule = hModule;
         MessageBox(NULL, TEXT("加載DLL!"), TEXT("提示"), MB_OK);
         break;
     case DLL_THREAD_ATTACH:
     case DLL_THREAD_DETACH:
     case DLL_PROCESS_DETACH:
         break;
     }
     return TRUE;
}

新建def文件導出相關函數:

LIBRARY


EXPORTS
LoadHook
UnloadHook

編譯生成 TestDLL.dll 文件

0x03 編寫調用程序:

DLL不能主動執行,因此需要編寫調用程序:

#include <windows.h>
#include <stdio.h>

#define  DLL_NAME    "TestDLL.dll"

int main(int argc, char* argv[])
{
     do{
         HMODULE hModule = LoadLibraryA(DLL_NAME);
         if(hModule == NULL)
             break;
         FARPROC pfnLoadHook = GetProcAddress(hModule, "LoadHook");
         FARPROC pfnUnloadHook = GetProcAddress(hModule, "UnloadHook");
         if(pfnLoadHook==NULL || pfnUnloadHook==NULL)
             break;
         if (pfnLoadHook())
             printf("全局鈎子加載成功!\r\n");
         else{
             printf("全局鈎子加載失敗!\r\n");
             break;
         }
         printf("按任意鍵卸載全局鈎子!\r\n");
         getchar();
         pfnUnloadHook();
         printf("全局鈎子卸載完成!\r\n");
     }while(FALSE);

    getchar();
     return 0;
}

注:為了簡化出錯處理,使用了 do-while(0) 結構

0x04 驗證:

先打開PCHunter查看:

1

可以看到此時系統應用層沒有任何全局消息鈎子

為了方便觀察,打開系統自帶的Notepad,並使用調試器附加:

2

編譯生成 TestDLL.dll 文件和調用程序放在同一路徑下,並且執行調用程序:

3

可以發現已經成功將DLL注入到了當前系統的很多進程當中,用調試器附加的Notepad進程可以非常直觀的看到結果

同時在PCHunter中也可以直觀的看到結果:

4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM