Top Banner
DLL Injection DLL Injection
28

01 DLL Injection WindowHook

Oct 14, 2014

Download

Documents

linuxtyh
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 01 DLL Injection WindowHook

DLL InjectionDLL InjectionDLL InjectionDLL Injection

Page 2: 01 DLL Injection WindowHook

使用 SetWindowsHookEx 來設定 Hook function

HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hinstDll, 0);

當有任何 message 被 post 過來 , 就會呼叫我們的攔截程式

當有任何 message 被 post 過來 , 就會呼叫我們的攔截程式

我們指定的攔截程式碼(Hook procedure)

我們指定的攔截程式碼(Hook procedure)

包含攔截 function 的DLL

包含攔截 function 的DLL

指定要 Monitor 所有的 thread

指定要 Monitor 所有的 thread

指定 hook 的形式

WH_CALLWNDPROC: 設定當目標收到 Message 之前 , 呼叫你的 function WH_CALLWNDPROCRET: 當目標已經把 Message 處理完 , 呼叫你的 function

可以設定的值 ( 部分 ) 參考 MSDN可以設定的值 ( 部分 ) 參考 MSDN

Page 3: 01 DLL Injection WindowHook

z

系統如何應對 SetWindowsHookEx?

BOOL WINAPI SetDIPSHook(DWORD dwThreadId){ // 安裝 hook function GetMsgProc 到指定的 thread HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hinstDll,\ dwThreadId);}

Step 1: Process B Send 一個 message 給一個視窗處理

Step 1: Process B Send 一個 message 給一個視窗處理 Step 2:

系統檢查是否有 WH_GETMESSAGE 攔截被安裝

Step 2: 系統檢查是否有

WH_GETMESSAGE 攔截被安裝

Step 3: 系統檢查 GetMsgProc 是否被映射到 Process B 的位址空間中

Step 3: 系統檢查 GetMsgProc 是否被映射到 Process B 的位址空間中

Step 4: 載入包含 GetMsgProc 的 DLL

並 遞增 DLL counter

Step 4: 載入包含 GetMsgProc 的 DLL

並 遞增 DLL counter

Step 5: 1. 呼叫 GetMsgProc () 2. 再度遞增 DLL counter

Step 5: 1. 呼叫 GetMsgProc () 2. 再度遞增 DLL counter

返回時 , 遞減 DLLcounter

返回時 , 遞減 DLLcounter

Why? 防止 Process B 在執行 GetMsgProc 時 , 有其他 thread 呼叫 UnhookWindowsHookEx, 導致 DLL UnMap Why? 防止 Process B 在執行 GetMsgProc 時 , 有其他 thread 呼叫 UnhookWindowsHookEx, 導致 DLL UnMap

把 GetMsgProc 安裝到目標 process 中

把 GetMsgProc 安裝到目標 process 中

00 1111 22

00

Page 4: 01 DLL Injection WindowHook

解除 Hook• BOOL UnhookWindowsHookEx(HHOOK hhook);

Step 1: 找出系統中 , 所有被注入該 DLL 的 process

Step 1: 找出系統中 , 所有被注入該 DLL 的 process

Step 2: 遞減那些 process 對 DLL 的

reference counter

Step 2: 遞減那些 process 對 DLL 的

reference counter

Page 5: 01 DLL Injection WindowHook

範例程式 : 新版本操控程式 : SetMouseMessageHook

呼叫 SetHook(dwThreadID);呼叫 SetHook(dwThreadID);

DLL 掛鉤程式 : MouseProcLibrary.dll

MyHook_MouseProc( );MyHook_MouseProc( );

SetHook(dwThreadID) 實作SetHook(dwThreadID) 實作

滑鼠訊息掛鉤程式

安裝掛鉤

目標視窗 : TargetWindow

while(GetMessage(…)){ …}

while(GetMessage(…)){ …}

Message-loop

只要滑鼠有動作 ,就會先呼叫 掛鉤

安裝掛鉤到指定的 thread

Page 6: 01 DLL Injection WindowHook

範例程式

• 將桌面的 icon 位置存起來

• 將桌面的 icon 位置讀回來SimpleDIP.cpp

Page 7: 01 DLL Injection WindowHook

ProgmanProgmanProgram ManagerProgram Manager

到底是誰在管理桌面 ?

spy 拉到最後一項

修正修正

Page 8: 01 DLL Injection WindowHook

WinAPI WINMAIN(…){ … SetDIPSHook …}

WinAPI WINMAIN(…){ … SetDIPSHook …}

SetDIPSHook{ SetWindowsHookEx(…)}

SetDIPSHook{ SetWindowsHookEx(…)}

Explorer 相關的程式碼(SysListView32)

Explorer 相關的程式碼(SysListView32)

SetDIPSHook{ SetWindowsHookEx(…)}

SetDIPSHook{ SetWindowsHookEx(…)}

GetMsgProc(){

}

GetMsgProc(){

}GetMsgProc(){

}

GetMsgProc(){

}

1

載入 DLPSLIB.dll( 寄生程式 )

載入 DLPSLIB.dll( 寄生程式 )

DLPSLIB.dll DLPSLIB.dll

2

建立隱藏的 dialog建立隱藏的 dialog34

通知注射完成(Message)

通知注射完成(Message)

5

要求處理事情要求處理事情

存取資料存取資料6

先看看架構 : 總共有三個檔案互動

SimpleDIP.exe

目標 process

隱藏的 dialog

設定要 將 GetMsgProc()注射進 目標 Process

Post Message 給 process以啟動目標 Process 呼叫GetMsgProc();

Page 9: 01 DLL Injection WindowHook

開始寫程式嘍 !!

1

23

Page 10: 01 DLL Injection WindowHook

加入 resource

Page 11: 01 DLL Injection WindowHook

修改 ID = IDC_SAVE修改 ID = IDC_SAVE

修改 ID = IDC_RESTORE修改 ID = IDC_RESTORE

1

2

修改 ID = IDD_DIALOG1修改 ID = IDD_DIALOG1

Page 12: 01 DLL Injection WindowHook

加入 Message Handle#include <Windows.h> // Windows 程式必要的標頭檔#include <WindowsX.h>#include "resource.h" // 對應到你剛剛建立的 Dialog template#include <tchar.h> // for TCHAR 字元

int WINAPI _tWinMain( ..) { 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 1: 建立一個 Dialog 讓使用者選擇 是否要將 [ 桌面的 icon] 位置存起來

自訂的Dialog 訊息處理函式( 見下頁 )

自訂的Dialog 訊息處理函式( 見下頁 )

視窗主程式視窗主程式

{ Message Handle function 的 prototype 片段 方便巨集定義的片段 …}

將傳回 使用者按鍵 的選項將傳回 使用者按鍵 的選項

Page 13: 01 DLL Injection WindowHook

當使用者按下按鈕時// Dialog 的訊息處理主要函式 BOOL WINAPI Dlg_Proc( HWND hwnd, UINT uMsg, …) { switch (uMsg) { chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand); } return(FALSE);}

// 方便巨集 chHANDLE_DLGMSG 定義// 利用 SetDlgMsgResult 將 Dialog 的 message 導向指定的// function#define chHANDLE_DLGMSG(hwnd, message, fn) case (message): return (SetDlgMsgResult(hwnd, uMsg, \ HANDLE_##message((hwnd), (wParam), (lParam), (fn))))

// 方便巨集 chHANDLE_DLGMSG 定義// 利用 SetDlgMsgResult 將 Dialog 的 message 導向指定的// function#define chHANDLE_DLGMSG(hwnd, message, fn) case (message): return (SetDlgMsgResult(hwnd, uMsg, \ HANDLE_##message((hwnd), (wParam), (lParam), (fn))))

void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, …) { switch (id) { case IDC_SAVE: case IDC_RESTORE: EndDialog(hwnd, id); break; }}

當使用者按下按鈕後 , destroys the modal Dialog box

程式藉由 id判斷到底是哪一個按鈕被按下

程式藉由 id判斷到底是哪一個按鈕被按下

Page 14: 01 DLL Injection WindowHook

休息一下

• 你可以把 Dialog 架框建好

Page 15: 01 DLL Injection WindowHook

將寄生的 DLL 程式注入指定的 process

int WINAPI _tWinMain( ..) {

// Step 1: 建立視窗 , 讀取使用者的需求

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

}

注入的寄生程式寫在下面

Page 16: 01 DLL Injection WindowHook

// Step 2: 取得桌面管理程式 (ProgMan)HWND hwndLV = GetFirstChild(GetFirstChild(FindWindow(TEXT("Progman"), NULL))); // Step 3: 將 DIPLib.dll 注射到 Explorer's 位址空間SetDIPSHook(GetWindowThreadProcessId(hwndLV, NULL));

// Step 4: 等待寄生程式的回應 MSG msg;GetMessage(&msg, NULL, 0, 0);

// Step 5: 因為寄生程式會建立一個隱藏的視窗 Richter DIPS123// 我們將利用這個視窗 , 操控寄生程式HWND hwndDIPS = FindWindow(NULL, TEXT("Richter DIPS123"));SendMessage(hwndDIPS, WM_APP, (WPARAM) hwndLV, (cWhatToDo == TEXT('S')));// Step 6: 操作完成 , 移除寄生程式SendMessage(hwndDIPS, WM_CLOSE, 0, 0);SetDIPSHook(0);

也可以用 Kernel Object 做同步 , 這裡使用 Message

也可以用 Kernel Object 做同步 , 這裡使用 Message

這是 DIPLib.dll 中的一個 function這是 DIPLib.dll 中

的一個 function

SysListView32SysListView32

Page 17: 01 DLL Injection WindowHook

Link DLL

Page 18: 01 DLL Injection WindowHook

WinAPI WINMAIN(…){ … SetDIPSHook …}

WinAPI WINMAIN(…){ … SetDIPSHook …}

SetDIPSHook{ SetWindowsHookEx(…)}

SetDIPSHook{ SetWindowsHookEx(…)}

Explorer 相關的程式碼(SysListView32)

Explorer 相關的程式碼(SysListView32)

SetDIPSHook{ SetWindowsHookEx(…)}

SetDIPSHook{ SetWindowsHookEx(…)}

GetMsgProc(){

}

GetMsgProc(){

}GetMsgProc(){

}

GetMsgProc(){

}

1

載入 DLPSLIB.dll( 寄生程式 )

載入 DLPSLIB.dll( 寄生程式 )

DLPSLIB.dll DLPSLIB.dll

2

建立隱藏的 dialog建立隱藏的 dialog34

通知注射完成(Message)

通知注射完成(Message)

5

要求處理事情要求處理事情

存取資料存取資料6

互動流程

SimpleDIP.exe

設定要 將 GetMsgProc()注射進 目標 Process

Post Message 給 process以啟動目標 Process 呼叫GetMsgProc();

Page 19: 01 DLL Injection WindowHook

互動流程

BOOL WINAPI SetDIPSHook( DWORD dwThreadId) { // 安裝 hook function GetMsgProc 到指定的 thread SetWindowsHookEx(…, GetMsgProc,…,dwThreadId);} Expoler.exe thread

idExpoler.exe thread

id

Expoler 的視窗處理 thread 會載入DIPSLib.dll

Hook function 已經存在於 Expoler的 address space

呼叫 Hook function, GetMsgProc

Exploer processExploer process

引發的一連串動作

寄生在 Expoler 的Function

寄生在 Expoler 的Function

Page 20: 01 DLL Injection WindowHook

SetDIPSHook 的部分// [ 設定 / 解除 ] 寄生 DLL// dwThreadId == 0 則解除BOOL WINAPI SetDIPSHook(DWORD dwThreadId) { BOOL fOk = FALSE; if (dwThreadId != 0) { // Step 1:

// 將我們的 thread ID 存起來 , 以便 當 server window 被建立起來時 , // GetMsgProc 可以 post a message 回來

g_dwThreadIdDIPS = GetCurrentThreadId();

// Step 2: g_hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hinstDll, dwThreadId); fOk = (g_hhook != NULL);

if (fOk) { // Step 3:

fOk = PostThreadMessage(dwThreadId, WM_NULL, 0, 0); } } else { // 當 dwThreadId ==0 時 , 表示我們要移除 hook 了 fOk = UnhookWindowsHookEx(g_hhook); g_hhook = NULL; } return(fOk);}

隨便送一個 no operation message, WM_NULL 給指定的 thread, 以便啟動我們的 hook function , GetMsgProc

隨便送一個 no operation message, WM_NULL 給指定的 thread, 以便啟動我們的 hook function , GetMsgProc

將 hook function GetMsgProc 安裝到指定的 thread 中

監控端的 thread

目標 thread要注入的 function

( 見下頁 )

也就是要被注射的 DLL

也就是要被注射的 DLL

Page 21: 01 DLL Injection WindowHook

LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {

static BOOL fFirstTime = TRUE;

if (fFirstTime) { // The DLL just got injected. fFirstTime = FALSE;

// Step 1: 建立一個 Dialog 用來處理 client 的 request // 所有送到這個 dialog message 都會交給 Dlg_Proc 管理 // 目前這個 Dialog 的 title = "Richter DIPS123" CreateDialog(g_hinstDll, MAKEINTRESOURCE(IDD_DIPS), NULL, Dlg_Proc); // Step 2: 告訴 DIPS application 目前 server 已經啟動 // 並且等待接受 requests PostThreadMessage(g_dwThreadIdDIPS, WM_NULL, 0, 0); }

// 將 hook 資訊傳給下一個可能的 hook return(CallNextHookEx(g_hhook, nCode, wParam, lParam));}

GetMsgProc 的部分

監控端的 thread

Page 22: 01 DLL Injection WindowHook

DLPSLIB 設定為 DLL Project

設定 dll 檔輸出位置設定 dll 檔輸出位置

設定 lib 檔輸出位置設定 lib 檔輸出位置

Page 23: 01 DLL Injection WindowHook

• 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

Page 24: 01 DLL Injection WindowHook

進一步的解析Message 巨集

我們已經知道利用

可以將 WM_COMMAND message 轉向呼叫我們自己寫的 Dlg_OnCommand function 處理

chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);

現在來看看詳細呼叫的情況

Page 25: 01 DLL Injection WindowHook

解析 chHANDLE_DLGMSGBOOL 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);}

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

#define chHANDLE_DLGMSG(hwnd, message, fn) case (message): return (SetDlgMsgResult(hwnd, uMsg,\ HANDLE_##message((hwnd), (wParam), (lParam), (fn))))

Dialog 訊息處理函式Dialog 訊息處理函式

case (WM_COMMAND): return(SetDlgMsgResult( hwnd, uMsg,\ HANDLE_WM_COMMAND(hwnd,wParam,lParam,Dlg_OnCommand))

case (WM_COMMAND): return(SetDlgMsgResult( hwnd, uMsg,\ HANDLE_WM_COMMAND(hwnd,wParam,lParam,Dlg_OnCommand))

原型定義在 cmnhdr.h原型定義在 cmnhdr.h

你的 function 位址

你的 function 位址

接下一頁

Page 26: 01 DLL Injection WindowHook

解析 chHANDLE_DLGMSGcase (WM_COMMAND): return(SetDlgMsgResult( hwnd, uMsg,\ HANDLE_WM_COMMAND(hwnd,wParam,lParam,Dlg_OnCommand))

case (WM_COMMAND): return(SetDlgMsgResult( hwnd, uMsg,\ HANDLE_WM_COMMAND(hwnd,wParam,lParam,Dlg_OnCommand))

21

#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn) \ ((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), (UINT)HIWORD(wParam)), 0L)

原型定義在 windowx.h for message crackers原型定義在 windowx.h for message crackers

你的 function 位址

接下一頁

Dlg_OnCommand(hwnd, \ (int)(LOWORD(wParam,(HWND)(lParam),(UINT)HIWORD(wParam)),0L)

Dlg_OnCommand(hwnd, \ (int)(LOWORD(wParam,(HWND)(lParam),(UINT)HIWORD(wParam)),0L)

你的 function 位址

Page 27: 01 DLL Injection WindowHook

#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) == WM_COMPAREITEM || \ (msg) == WM_VKEYTOITEM || \ (msg) == WM_CHARTOITEM || \ (msg) == WM_QUERYDRAGICON || \ (msg) == WM_INITDIALOG \ ) ? (BOOL)(result) : (SetWindowLongPtr((hwnd), DWLP_MSGRESULT, (LPARAM)(LRESULT)(result)), TRUE))

windowx.h for USER Macro APIswindowx.h for USER Macro APIs

解析一下 : 若 msg 是左邊的那些 , 則直接呼叫你的 function 否則 , 利用 SetWindowLongPtr 修改 Dialog MessageResult 屬性

(SetWindowLongPtr(hwnd,DWLP_MSGRESULT, (LPARAM)(LRESULT)(Dlg_OnCommand(hwnd, \ (int)(LOWORD(wParam,(HWND)(lParam),(UINT)HIWORD(wParam)),0L)), TRUE))

(SetWindowLongPtr(hwnd,DWLP_MSGRESULT, (LPARAM)(LRESULT)(Dlg_OnCommand(hwnd, \ (int)(LOWORD(wParam,(HWND)(lParam),(UINT)HIWORD(wParam)),0L)), TRUE))

展開的結果展開的結果

指定 Dialog 的 Message 改由 Dlg_OnCommand 呼叫指定 Dialog 的 Message 改由 Dlg_OnCommand 呼叫

2

Page 28: 01 DLL Injection WindowHook

全部合在一起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);}

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

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 呼叫指定 Dialog 的 Message 改由 Dlg_OnCommand 呼叫