Professional Documents
Culture Documents
使用 SetWindowsHookEx
來設定 Hook function
包含攔截 function 的
DLL
當有任何 message
指定 hook 的形式 被 post 過來 , 就會呼叫 我們指定的
我們的攔截程式 攔截程式碼
(Hook procedure)
指定要 Monitor
可以設定的值 ( 部分 ) 參考 MSDN 所有的 thread
WH_CALLWNDPROC:
設定當目標收到 Message 之前 , 呼叫你的 function
WH_CALLWNDPROCRET:
當目標已經把 Message 處理完 , 呼叫你的 function
系統如何應對
SetWindowsHookEx?
把 GetMsgProc 安裝到
BOOL WINAPI SetDIPSHook(DWORD dwThreadId){
目標 process 中
// 安裝 hook function GetMsgProc 到指 定的 thread
HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hinstDll,\
dwThreadId);
} 0
Step 1:
Process B Send 一個 message
給一個視窗處理 Step 2:
系統檢查是否有
WH_GETMESSAGE 攔截被安裝
Step 5: Step 4:
1. 呼叫 GetMsgProc () 載入 包含 GetMsgProc 的 DLL
2. 再度遞 增 DLL counter1 2 並 遞增 DLL counter 0 1
Why? 防止 Process B 在執行 GetMsgProc 時 , 有其他 thread 呼叫 UnhookWindowsHookEx, 導致 DLL UnMap
解除 Hook
• BOOL UnhookWindowsHookEx(HHOOK hhook);
Step 1:
找出系統中 , 所有 被注 入 該 DLL 的 process
Step 2:
遞減那些 process 對 DLL 的
reference counter
範例程式 : 新版本
操控程式 : SetMouseMessageHook 目標視窗 : TargetWindow
呼叫 SetHook(dwThreadID); while(GetMessage(…)){
…
}
Message-loop
安裝掛鉤到指定的 thread
安裝掛鉤
SetHook(dwThreadID) 實作
只要滑鼠有動作 ,
就會先呼叫 掛鉤
滑鼠訊息掛鉤程式
MyHook_MouseProc( );
SimpleDIP.cpp
到底是誰在管理桌面 ?
spy 拉到最後一項
先看看架構 : 總共有三個檔案互動 隱藏的 dialog 建立隱藏的 dialog
3
4
通知注射完成 目標 process
(Message) 6
存取資料
SimpleDIP.exe
SetDIPSHook{ SetDIPSHook{
SetWindowsHookEx(…) SetWindowsHookEx(…)
載入 DLPSLIB.dll }
}
設定要 將 GetMsgProc()
2 ( 寄生程式 )
注射進 目標 Process
GetMsgProc(){ GetMsgProc(){
Post Message 給 process
以啟動目標 Process 呼叫 }
} GetMsgProc();
DLPSLIB.dll DLPSLIB.dll
開始寫程式嘍 !!
3
2
加入 resource
修改 ID = IDD_DIALOG1
修改 ID = IDC_RESTORE
修改 ID = IDC_SAVE
加入 Message Handle
#include <Windows.h> // Windows 程式必要的標頭檔
#include <WindowsX.h>
#include "resource.h" // 對應到你剛剛建立的 Dialog template
#include <tchar.h> // for TCHAR 字元
// 方便巨集 chHANDLE_DLGMSG 定義
// 利用 SetDlgMsgResult 將 Dialog 的 message 導向指 定的
// function
#define chHANDLE_DLGMSG(hwnd, message, fn)
case (message): return (SetDlgMsgResult(hwnd, uMsg, \
HANDLE_##message((hwnd), (wParam), (lParam), (fn))))
休息一下
TCHAR cWhatToDo;
switch (DialogBox(hinstExe, MAKEINTRESOURCE(IDD_DIALOG1),
NULL,Dlg_Proc))
{ case IDC_SAVE:
cWhatToDo = TEXT('S');
break;
case IDC_RESTORE:
cWhatToDo = TEXT('R');
break;
}
// Step 2 ~ 6 : 處理與 操縱 寄生的 DLL function
注入的寄生程式寫在下面
// Step 2: 取得桌 面管 理程式 (ProgMan)
HWND hwndLV = GetFirstChild(GetFirstChild(FindWindow(TEXT("Progman"),
NULL)));
// Step 3: 將 DIPLib.dll 注射到 Explorer's 位址空 間
SetDIPSHook(GetWindowThreadProcessId(hwndLV, NULL)); SysListView32
這是 DIPLib.dll 中
的一個 function
TEXT('S')));
// Step 6: 操作完 成 , 移除寄生 程式
SendMessage(hwndDIPS, WM_CLOSE, 0, 0);
SetDIPSHook(0);
Link DLL
互動流程 建立隱藏的 dialog
3
4
通知注射完成
(Message) 6
存取資料
SimpleDIP.exe
SetDIPSHook{ SetDIPSHook{
SetWindowsHookEx(…) SetWindowsHookEx(…)
載入 DLPSLIB.dll }
} 2 ( 寄生程式 )
設定要 將 GetMsgProc()
注射進 目標 Process
GetMsgProc(){ GetMsgProc(){
Post Message 給 process
} 以啟動目標 Process 呼叫 }
GetMsgProc();
DLPSLIB.dll DLPSLIB.dll
互動流程
Exploer process
也就是要被注射的
SetDIPSHook 的部分
DLL
// [ 設定 / 解除 ] 寄生 DLL
// dwThreadId == 0 則解 除
BOOL WINAPI SetDIPSHook(DWORD dwThreadId) {
BOOL fOk = FALSE;
if (dwThreadId != 0) {
// Step 1:
// 將我們的 thread ID 存起來 , 以便 當 server window 被建 立起 來時 ,
監控端的 thread // GetMsgProc 可以 post a message 回來
g_dwThreadIdDIPS = GetCurrentThreadId(); 將 hook function GetMsgProc
安裝 到指定的 thread 中
// Step 2:
g_hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hinstDll, dwThreadId);
fOk = (g_hhook != NULL);
要注入的 function
( 見下頁 ) 目標 thread
if (fOk) {
// Step 3:
fOk = PostThreadMessage(dwThreadId, WM_NULL, 0, 0);
}
} else {
// 當 dwThreadId ==0 時 , 表示 我們 要移除 hook 了
fOk = UnhookWindowsHookEx(g_hhook);
g_hhook = NULL;
隨便送一個 no operation message, WM_NULL
} 給指定的 thread, 以便啟動 我們的 hook
return(fOk); function , GetMsgProc
}
GetMsgProc 的部分
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (fFirstTime) {
// The DLL just got injected.
fFirstTime = FALSE;
Dlg_Proc);
監控端的// Step
thread2: 告訴 DIPS application 目前 server 已經啟動
// 並且等待接受 requests
PostThreadMessage(g_dwThreadIdDIPS, WM_NULL, 0, 0);
}
設定 dll 檔輸出位置
設定 lib 檔輸出位置
• End
延伸閱讀 :
1. Monitor system events
ms-help://MS.MSDNQTR.2004JAN.1033/winui/winui/windowsuserinterface
/windowing/hooks/usinghooks.htm#system_events
2. . TaskSwitcher application
ms-help://MS.MSDNQTR.2004JAN.1033/dnwxp/html/xpvisualstyles.htm
進一步的解析 Message 巨集
我們已經知道利用
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
現在來看看
詳細呼叫的情況
解析 chHANDLE_DLGMSG
Dialog 訊息處理函式
BOOL WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
你的 function 位址
return(FALSE);
}
接下一頁
解析 chHANDLE_DLGMSG
case (WM_COMMAND): 你的 function 位址
return(SetDlgMsgResult( hwnd, uMsg,\
HANDLE_WM_COMMAND(hwnd,wParam,lParam,Dlg_OnCommand))
1
2
Dlg_OnCommand(hwnd, \
(int)(LOWORD(wParam,(HWND)(lParam),(UINT)HIWORD(wParam)),0L)
你的 function 位址
接下一頁
2 windowx.h for USER Macro APIs
#define SetDlgMsgResult(hwnd, msg, result) (( \
(msg) == WM_CTLCOLORMSGBOX || \
(msg) == WM_CTLCOLOREDIT || \
(msg) == WM_CTLCOLORLISTBOX || \
(msg) == WM_CTLCOLORBTN || \
(msg) == WM_CTLCOLORDLG || \
(msg) == WM_CTLCOLORSCROLLBAR || \
解析一下 :
(msg) == WM_CTLCOLORSTATIC || \ 若 msg 是左邊的那些 , 則直接呼叫你的 function
(msg) == WM_COMPAREITEM || \ 否則 , 利用 SetWindowLongPtr 修改 Dialog
(msg) == WM_VKEYTOITEM || \ MessageResult 屬性
(msg) == WM_CHARTOITEM || \
(msg) == WM_QUERYDRAGICON || \
(msg) == WM_INITDIALOG \
) ? (BOOL)(result) : (SetWindowLongPtr((hwnd), DWLP_MSGRESULT,
(LPARAM)(LRESULT)(result)), TRUE))
展開的結果
(SetWindowLongPtr(hwnd,DWLP_MSGRESULT,
(LPARAM)(LRESULT)(Dlg_OnCommand(hwnd, \
(int)(LOWORD(wParam,(HWND)(lParam),(UINT)HIWORD(wParam)),0L)),
指定 Dialog 的 Message 改由 Dlg_OnCommand 呼叫
TRUE))
全部合在一起
BOOL WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
case (WM_COMMAND):
return
(SetWindowLongPtr(hwnd,DWLP_MSGRESULT,
(LPARAM)(LRESULT)(Dlg_OnCommand(hwnd, \
(int)(LOWORD(wParam,(HWND)(lParam),(UINT)HIWORD(wParam)),0L)),
TRUE)) 指定 Dialog 的 Message 改由 Dlg_OnCommand 呼叫
;