在windows核心編程中的第22章中提到了插入DLL和掛接API這個內容,剛開始看到并不是很明白,所以當時關于注入DLL ,我選取的是一個相對我自己而言比較容易理解的遠程注入,在做畢設的過程中,我發現掛鉤注入DLL其實是更加方便和強悍的一種方法,我也在網上搜索過很多例子,試圖先尋找一個樣板依葫蘆畫瓢,可是一直沒有滿意的,所以自己下定決心寫了一個,發現也沒那么難,仔細一點就好了,下面是原理和實現的過程。
眾所周知,windows這個強大的消息是基于事件驅動的,事件驅動就會引發消息,所以在窗口接受到消息之前可以對其進行一些你想要的處理就會發生窗口處理消息之前先處理你所需要的操作,就達到了消息過濾的過程,這個主要基于windows的消息機制——系統一旦發生操作就會引發消息,并將消息放到消息隊列中,應用程序從消息隊列中獲取消息并發送到相應的窗口讓鉤子函數在這個函數“有機可趁”。消息過濾與我所要講的掛鉤注入DLL又有什么聯系呢,主要是掛鉤注入DLL中用到一個函數SetWindowsHookEx,這個函數大家網上一搜一堆解讀,這邊就不做贅述,其第一個參數就是消息鉤子,也就是說,DLL所要注入的那個進程發送了某種消息給窗口后才會引發鉤子鉤住并注入DLL,這與消息過濾其實是一個意思。我這邊主要做的是注入特定的進程,而不是全局鉤子,其實全局鉤子也很簡單,只需要將上述函數的最后一個參數設為0,但這樣會導致,但凡發送了相同消息給窗口的都會導致鉤子鉤住并注入DLL執行相應處理,這樣我就不知道是不是我要的線程發送了這個消息,所以最后一個參數我傳遞了指定線程的ID。下面是實現的過程——將自己寫的Hooking.dll通過自己寫的應用程序MyHook.exe注入到word進程,目前是在word進程已經存在,由于設置的是WH_CBT鉤子,所以一旦word進程最大化或者成為活動窗口之類的就會發送相應的消息,導致相應的處理,這里我只是做簡單的處理比如在桌面上建立一個小文件。
1.首先打開VS2008,創建一個工程,在該工程下面創建兩個項目,一個是Hooking的DLL項目,一個是MyHook項目,是負責設置掛鉤的
2.在該DLL中主要就是掛鉤函數SetWindowsHookExW(WH_CBT, HookmProc, g_hinstDll, dwThread)和處理函數LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam),之所以能將DLL注入到指定進程,就是因為,以dwThread為ID的指定進程向窗口發送與WH_CBT掛鉤相關聯的消息,導致其執行處理函數HookmProc,而處理函數又在以g_hinstDll為句柄的DLL中,所以必須先將DLL注入到指定進程才能執行該處理函數,處理函數這里只進行了簡單的操作證明其注入成功了,例如創建一個桌面文件。這里的DLL的句柄參數就是就是掛鉤函數所在的DLL ,但DLL并不執行掛鉤函數,而是作為接口,由MyHook.exe調用
3.所以MyHook模塊中主要就是加載Hooking.dll調用其接口函數SetHook,以指定被注入的線程的句柄為參數,在這之前,先要遍歷系統進程找到WINWORD.EXE并將其線程句柄獲得傳入,這里用到了快照方法,這個也不做贅述,網上一堆。
4.由此,先啟動word進程并將其窗口最小化,然后運行程序就會得到想要的效果,DLL被注入,再最大化word窗口,桌面就會出現小文件
5.總結一下,這中間遇到了一些問題,但都與掛鉤注入DLL無關,還是自己的基礎不牢。
下面要考慮的就是,加上監視word啟動的代碼,這樣一旦word啟動了就進行上述操作,不啟動則不進行Hooking.h:
#ifndef Hooking_H
#define Hooking_H
extern "C" _declspec(dllexport)BOOL WINAPI SetHook(DWORD dwThread);
#endif
Hooking.cpp:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include "Hooking.h"
LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam);
HHOOK g_hHook = NULL;
HINSTANCE g_hinstDll = NULL;
BOOL WINAPI Typedef_eSetHook(DWORD dwThread)
{
g_hinstDll = GetModuleHandle(L"Hooking.dll");
g_hHook = SetWindowsHookExW(WH_CBT, HookmProc, g_hinstDll, dwThread);
if (NULL == g_hHook)
{
printf("sethook failed!");
}
return TRUE;
}
LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CreateFileW(L"C:\\Users\\Administrator\\Desktop\\hook success.txt", GENERIC_READ|GENERIC_WRITE,
0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);
return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}
dllmian.cpp:
LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam);
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
/*g_hCurrentMoudle = hModule;
g_hHook = SetWindowsHookExW(WH_KEYBOARD, HookmProc, hModule, 0);*/
//LoadDll();//1.找出感興趣的進程 2.從證書中獲取密鑰 3.加載文件過濾DLL
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Hooking.def:
LIBRARY "Hooking"
EXPORTS
Typedef_eSetHook @1
在windows核心編程中的第22章中提到了插入DLL和掛接API這個內容,剛開始看到并不是很明白,所以當時關于注入DLL ,我選取的是一個相對我自己而言比較容易理解的遠程注入,在做畢設的過程中,我發現掛鉤注入DLL其實是更加方便和強悍的一種方法,我也在網上搜索過很多例子,試圖先尋找一個樣板依葫蘆畫瓢,可是一直沒有滿意的,所以自己下定決心寫了一個,發現也沒那么難,仔細一點就好了,下面是原理和實現的過程。
眾所周知,windows這個強大的消息是基于事件驅動的,事件驅動就會引發消息,所以在窗口接受到消息之前可以對其進行一些你想要的處理就會發生窗口處理消息之前先處理你所需要的操作,就達到了消息過濾的過程,這個主要基于windows的消息機制——系統一旦發生操作就會引發消息,并將消息放到消息隊列中,應用程序從消息隊列中獲取消息并發送到相應的窗口讓鉤子函數在這個函數“有機可趁”。消息過濾與我所要講的掛鉤注入DLL又有什么聯系呢,主要是掛鉤注入DLL中用到一個函數SetWindowsHookEx,這個函數大家網上一搜一堆解讀,這邊就不做贅述,其第一個參數就是消息鉤子,也就是說,DLL所要注入的那個進程發送了某種消息給窗口后才會引發鉤子鉤住并注入DLL,這與消息過濾其實是一個意思。我這邊主要做的是注入特定的進程,而不是全局鉤子,其實全局鉤子也很簡單,只需要將上述函數的最后一個參數設為0,但這樣會導致,但凡發送了相同消息給窗口的都會導致鉤子鉤住并注入DLL執行相應處理,這樣我就不知道是不是我要的線程發送了這個消息,所以最后一個參數我傳遞了指定線程的ID。下面是實現的過程——將自己寫的Hooking.dll通過自己寫的應用程序MyHook.exe注入到word進程,目前是在word進程已經存在,由于設置的是WH_CBT鉤子,所以一旦word進程最大化或者成為活動窗口之類的就會發送相應的消息,導致相應的處理,這里我只是做簡單的處理比如在桌面上建立一個小文件。
1.首先打開VS2008,創建一個工程,在該工程下面創建兩個項目,一個是Hooking的DLL項目,一個是MyHook項目,是負責設置掛鉤的
2.在該DLL中主要就是掛鉤函數SetWindowsHookExW(WH_CBT, HookmProc, g_hinstDll, dwThread)和處理函數LRESULT CALLBACK HookmProc(int nCode, WPARAM wParam, LPARAM lParam),之所以能將DLL注入到指定進程,就是因為,以dwThread為ID的指定進程向窗口發送與WH_CBT掛鉤相關聯的消息,導致其執行處理函數HookmProc,而處理函數又在以g_hinstDll為句柄的DLL中,所以必須先將DLL注入到指定進程才能執行該處理函數,處理函數這里只進行了簡單的操作證明其注入成功了,例如創建一個桌面文件。這里的DLL的句柄參數就是就是掛鉤函數所在的DLL ,但DLL并不執行掛鉤函數,而是作為接口,由MyHook.exe調用
3.所以MyHook模塊中主要就是加載Hooking.dll調用其接口函數SetHook,以指定被注入的線程的句柄為參數,在這之前,先要遍歷系統進程找到WINWORD.EXE并將其線程句柄獲得傳入,這里用到了快照方法,這個也不做贅述,網上一堆。
4.由此,先啟動word進程并將其窗口最小化,然后運行程序就會得到想要的效果,DLL被注入,再最大化word窗口,桌面就會出現小文件
5.總結一下,這中間遇到了一些問題,但都與掛鉤注入DLL無關,還是自己的基礎不牢。
下面要考慮的就是,加上監視word啟動的代碼,這樣一旦word啟動了就進行上述操作,不啟動則不進行
MyHook.h:
#pragma once
typedef BOOL(WINAPI *Typedef_eSetHook)(DWORD);
extern Typedef_eSetHook SetHook;
MyHook.cpp:
#include <Windows.h>
#include <TlHelp32.h>
#include "stdio.h"
#include "MyHook.h"
#include <conio.h>
Typedef_eSetHook SetHook = NULL;
BOOL LoadNativeLibrary()
{
HMODULE hDll = LoadLibraryW(L"..\\Debug\\Hooking.dll");
if (hDll != NULL)
{
SetHook = (Typedef_eSetHook)GetProcAddress(hDll, MAKEINTRESOURCEA(1));
}
else
{
printf("LoadLibrary failed\n");
}
if(NULL == SetHook)
{
printf("SetHook is null\n");
OutputDebugStringA("0x103200 no init func.");
}
return TRUE;
}
int main()
{
LoadNativeLibrary();
DWORD dwProcessID = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, dwProcessID);
if (hSnapshot == NULL)
{
return 0;
}
PROCESSENTRY32 processinfo = {0};
processinfo.dwSize = sizeof(processinfo);
Process32FirstW(hSnapshot, &processinfo);
do
{
if (0 == lstrcmpiW(processinfo.szExeFile, L"WINWORD.EXE"))
{
dwProcessID = processinfo.th32ProcessID;
break;
}
} while (Process32NextW(hSnapshot, &processinfo));
CloseHandle(hSnapshot);
unsigned long pTID;
_asm {
mov eax, fs:[0x18]
add eax, 36
mov [pTID], eax
}
DWORD threadID;
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, false, dwProcessID);
ReadProcessMemory(hProcess, (const void *)pTID, &threadID, 4, NULL);
SetHook(threadID);
printf("...");
getche();
return 0;
}
其實一開始我主要是糾結于哪個函數放在哪個cpp還是dll里面,還有word干嘛了會讓setwindowshook函數將dll注入到其進程。后來我想自己肯定要有一個應用程序去執行掛鉤這個過程,本來想把setwindowshook這個函數也放在自己的應用程序里,后來想想最好把其和處理函數放在一起,然后處理函數必然要在dll里,于是就把setwindowshook函數也放在dll里,因為放在dll里他也不會執行,只要自己的應用程序去執行就行了,所以把setwindowshook這個函數封裝起來作為接口傳給自己的應用程序,應用程序一調用就進行掛鉤了而且也把這個dll注入到了相應進程了。
以上肯定還有很多不完善和不正確的表述,也歡迎大家指出,謝謝!!!