一般來說,使用detours的**都具有固定的模式。detours 1.5和detours 2.1的介面函式變了很多,這裡按照2.1版本對基本的使用方法進行說明。常用的函式有下面幾個:
detourtransactionbegin():開始一次
截獲或者
解除截獲
過程。
detourupdatethread():列入乙個在detourtransaction過程中要進行update的執行緒。這個函式的作用稍微有一些複雜,會在後面專門說明。
detourattach()
:新增乙個要截獲的
目標函式。
detourdetach():
用來解除截獲
的函式。
detourtransactioncommit():執行當前的transaction過程。在這個函式中才會真正進行
截獲或者
解除截獲
操作。前面三個函式都只是做一些記錄工作。
在使用的時候,這幾個函式的呼叫步驟基本上也是按照上面列出來的順序。舉例來說,
我們要截獲
api函式messageboxa,將訊息框彈出的訊息修改掉,可以按下面的方法做
(這裡是
dll注入的方式)。
先寫乙個呼叫了
messageboxa的程式。
建立乙個mfc對話方塊工程
(在建立嚮導中選
"dialog based",其餘預設),開啟
ok按鈕的單擊
處理事件onbnclickedok
(),在其
中加入對messageboxa函式的呼叫,
如下:
[cpp]view plain
copy
void
編譯後的程式名稱
為.exe,執行它並單擊ok按鈕時會彈出相應訊息框。現在我們要截獲這個exe檔案中對messageboxa函式的呼叫,以跳轉到我們自己定義的d函式處。我們需要先編寫乙個dll以攔截目標函式,然後將該dll注入到目標程式
.exe的空間中。
1、編寫目標函式的攔截dll
建立乙個
win32的dll工程(在win32應用程式嚮導中選dll),名為apihook,也可以不用ide而是用原始的記事本來編寫dll。把detours.h和detours.lib、detoured.lib拷貝到工程目錄下。原始檔apihook.cpp的**如下:
[cpp]view plain
copy
#include "stdafx.h"
#include
#include "detours.h"
#pragma comment(lib,"detours.lib")
#pragma comment(lib,"detoured.lib")
#ifdef _managed
#pragma managed(push, off)
#endif
//目標函式原型宣告
typedef
int(winapi* pfnmessageboxa)(
hwnd
hwnd,
lpcstr
lptext,
lpcstr
lpcaption,
uint
utype);
//宣告乙個指向目標函式的指標
pfnmessageboxa g_pmessageboxa=::messageboxa;
//截獲函式
intwinapi hookmessageboxa(
hwnd
hwnd,
lpcstr
lptext,
lpcstr
lpcaption,
uint
utype)
//截獲操作
__declspec
(dllexport
) bool
starthook()
//完成事務
if(detourtransactioncommit()!=no_error)else
return
false;
} //解除截獲操作
__declspec
(dllexport
) bool
stophook()
//完成事務
if(detourtransactioncommit()!=no_error)else
return
false;
} bool
apientry dllmain(
hmodule
hmodule,
dword
ul_reason_for_call,
lpvoid
lpreserved)
return
true;
} #ifdef _managed
#pragma managed(pop)
#endif
攔截操作一般按如下步驟進行:
1) 首先需要定義目標函式的原型。如果目標函式是windows api,可以到msdn中查閱,但是需要注意ansi版本和unicode版本的區別。如果沒有確切的原型宣告,或者目標函式是通過逆向工程找出來的,那麼需要定義乙個和目標函式原型相容的宣告,即引數個數和呼叫約定要相同。如messageboxa的原型是:
[cpp]view plain
copy
intmessageboxa(
hwnd
hwnd,
lpcstr
lptext,
lpcstr
lpcaption,
uint
utype);
則使用typedef定義目標函式原型如下:
[cpp]view plain
copy
typedef
int(winapi *pfnmessageboxa)(
hwnd
hwnd,
lpcstr
lptext,
lpcstr
lpcaption,
uint
utype);
2) 定義指向目標函式的函式指標:
[cpp]view plain
copy
pfnmessageboxa g_pmessageboxa = ::messageboxa;
3) 定義截獲函式並編寫**,用於替換目標函式。
4) 呼叫detourtransactionbegin開始一次detours事務。
5) 對程序中每個可能呼叫到目標函式的執行緒,都需要使用detourupdatethread加入到update佇列中。這是因為攔截時修改目標函式的前幾個位元組,如果某個執行緒剛好執行到這幾個位元組的位置時,粗暴的修改掉會造成該執行緒出現異常。detours事務處理時,會先列舉並暫停update佇列中所有執行緒,獲取它們的指令指標,如果發現這種情況,則將指令指標修改到跳板**的對應位元組上。這樣就避免出現崩潰的問題。
6) 對每個需要攔截的函式,呼叫detourattach加入到事務列表中。
7) 呼叫detourtransactioncommit進行實際的攔截操作。
解除攔截的操作和上面的流程基本一樣,只是第6步改為呼叫detourdetach函式。另外,detours還包含一系列其他函式,如果需要使用的話,可以參考detours安裝目錄下的示例。
最後,在dll的載入事件加入攔截操作函式,在解除安裝事件中加入解除攔截的操作函式,把它編譯成apihook.dll。
總體來說,detours庫的**是非常穩定的,但是如果使用方法不對,會造成一些問題。有下面一些地方需要特別注意:
1) 一定要列舉執行緒並呼叫detourupdatethread函式。否則可能出現很低機率的崩潰問題,這種問題很難被檢查出來。
2) 如果攔截函式在dll中,那麼絕大多數情況下不能在unhook之後解除安裝這個dll,或者解除安裝存在造成崩潰的危險。因為某些執行緒的呼叫堆疊中可能還包含hook函式,這時解除安裝掉dll,呼叫堆疊返回到hook函式時記憶體位置已經不是合法的**了。
3) detours庫設計時並沒有考慮到解除安裝的問題,這是因為鉤子的解除安裝本身是不安全的。當detours庫**存在於dll中的時候,即使unhook了所有函式,清理了所有自己使用到的函式,還是會占用一些記憶體。解除安裝這個dll會造成記憶體洩露,特別是反覆的進行載入dll->hook->unhook->解除安裝dll的過程,會讓這個問題變得非常嚴重。
4) 有一些非常短的目標函式是無法hook的。因為jmp指令需要占用一定空間,有些函式太過短小,甚至不夠jmp指令的長度,自然是沒有辦法hook掉的。
5) detours不支援9x核心的windows系統。因為9x核心下的記憶體模型和nt核心下有非常大的差別。
2、將攔截dll注入到目標應用程式中
Detour開發包介紹 2 使用
一般來說,使用detours 的 都具有固定的模式。detours 1.5 和 detours 2.1 的介面函式變了很多,這裡按照 2.1 版本對基本的使用方法進行說明。常用的函式有下面幾個 detourtransactionbegin 開始一次 截獲 或者 解除截獲 過程。detourupdat...
Detour開發包介紹 2 使用
一般來說,使用detours的 都具有固定的模式。detours 1.5和detours 2.1的介面函式變了很多,這裡按照2.1版本對基本的使用方法進行說明。常用的函式有下面幾個 detourtransactionbegin 開始一次 截獲或者 解除截獲 過程。detourupdatethread...
Libnids開發包介紹
libnids開發包介紹 libnids是乙個用於網路入侵檢測開發的專業程式設計介面,它使用了libpcap所以它具有捕獲資料報的功能。同時,libnids提供了tcp資料流重組功能,所以對於分析基於tcp協議的各種協議libnids都能勝任.libnids還提供了對ip分片進行重組的功能,以及埠掃...