什麼是Detours
簡單地說,Detours是微軟提供的一個開發庫,使用它可以簡單、高校、穩定地實現API HOOK的功能。
Detours是一個可以在x86、x64和IA64平臺上測試任意Win32函數的程序開發庫。它可以通過爲目標函數重寫在內存中的代碼而達到攔截Win32函數的目的。Detours還可以將任意的DLL或數據片段(稱之爲有效載荷)注入到任意Win32二進制文件中。Detours 被廣泛應用在微軟內部和其他行業中。
你可以從微軟官方網站下載到Detours的express版本,目前最新版本是2.1,它包含有下列的嶄新特性:
l 完整的Detours API文檔
l 附加和拆卸處理模塊
l 支持附加和拆卸Detours的時候更新對等線程
l 靜態和動態注入單個API
l 支持監視注入後的進程
l 改進後更加健壯的API可以將一個掛鉤函數,通過一個進程附着到dll上
l 新的API通過複製將有效載荷注入到目標進程中
l 支持x64和IA64平臺上的64-位源代碼(僅專業版可用)
l 支持Visual Studio 2005,Visual Studio .NET 2003, Visual Studio .NET (VC8)以及Visual Studio (VC7)開發工具
Detours的使用
Detours開發包被下載回來會不能直接使用,安裝完畢後需要自己使用nmake生成相應的DLL以及lib文件。這裏我已經編譯好了,隨文附上,一共有四個文件,分別是detoured.dll、detoured.lib、detours.lib、detours.h。
我們需要編寫一個DLL,然後將該DLL注入到目標進程的空間中,(注意這裏我們需要將生成的hook.dll和detoured.dll都複製到目標進程目錄,或者將他們複製到system32目錄等地方)下面我給一個例子,如下所示:
// HOOK.CPP
#include "Detours.h"
#pragma comment(lib,"detours.lib")
#pragma comment(lib,"detoured.lib")
// 共享數據段
#pragma data_seg("MyData")
DWORD nPid = 0; // 受保護的進程PID
#pragma data_seg()
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
{
// 安裝 HOOK
SetHook(TRUE);
break;
}
case DLL_PROCESS_DETACH:
{
// 卸載 HOOK
SetHook(FALSE);
}
case DLL_THREAD_DETACH:
default:
break;
}
return TRUE;
}
/*
* 函數:SetHook
*
* 作用:安裝/卸載 API HOOK
*
* 參數:TRUE - 安裝,FALSE - 卸載
*
* 返回:無
*/
void SetHook(BOOL flag)
{
if (flag)
{
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
// HOOK 函數列表
DetourAttach(&(PVOID&)Old_OpenProcess, New_OpenProcess);
DetourTransactionCommit();
}
else
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
// 取消 HOOK 函數列表
DetourDetach(&(PVOID&)Old_OpenProcess, New_OpenProcess);
DetourTransactionCommit();
}
}
/*
* 函數:New_OpenProcess
*
* 作用:攔截系統 OpenProcess 函數調用
*/
HANDLE WINAPI New_OpenProcess(DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId)
{
// 是否爲可信任程序
if (strcmp(szCurrentApp, szTrustFile) != 0)
{
// 是否爲受保護進程
if (dwProcessId == nPid)
{
return NULL;
}
}
return Old_OpenProcess( dwDesiredAccess,
bInheritHandle,
dwProcessId);
}
// HOOK.H
static HANDLE (WINAPI* Old_OpenProcess)(DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId) = OpenProcess;
HANDLE WINAPI New_OpenProcess(DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId);
然後要在def文件中將New_OpenProcess函數導出,最後將生成的HOOK.DLL注入到其他進程空間就可以了。