Detours学习1 - 开始使用Detours
Using Detours
要绕过目标函数,必须具备两个条件:一个是包含目标函数地址的目标指针,另一个是绕过函数。为了正确拦截目标函数、detour函数和目标指针必须具有完全相同的调用签名,包括参数数和调用约定。使用相同的调用约定可以确保适当地保留寄存器,并确保堆栈在detour函数和目标函数之间正确对齐。
用户代码必须包含detours.h
头文件并与detours链接detorus.lib
库。
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#pragma comment(lib, "detours.lib")
static VOID(WINAPI* TureSleep)(DWORD dwMilliseconds) = Sleep;
VOID WINAPI hkSleep(DWORD dwMilliseconds)
{
ULONGLONG dwBeg = GetTickCount64();
TureSleep(dwMilliseconds);
ULONGLONG dwEnd = GetTickCount64();
TCHAR buffer[512];
_stprintf_s(buffer, sizeof(buffer) / sizeof(TCHAR), _T("Sleeped %llu milli sec"), dwEnd - dwBeg);
MessageBox(NULL, buffer, _T(""), MB_OK);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if (DetourIsHelperProcess())
{
return TRUE;
}
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TureSleep, hkSleep);
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TureSleep, hkSleep);
DetourTransactionCommit();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
通过DetourAttach
在Hook事务中调用可以拦截目标函数。通过对DetourTransactionBegin
和DetourTransactionCommit
的调用来标记Hook事务。该DetourAttach
带有两个参数:目标函数指针的地址和指向DetourFunction
函数的指针。目标函数未作为参数提供,因为它必须已经存储在目标指针中。
该DetourUpdateThread
提供在目标线程中声明,以便在事务提交时更新指令指针。
该DetourAttach
分配和准备跳转调用目标函数。Hook事务提交时,将重写目标函数和跳转函数Trampoline
,并更新目标指针以指向跳转函数
一旦Hook目标函数,对目标函数的任何调用都将通过DetourFunction
函数重新路由。通过Trampoline
调用目标函数时,DetourFunction
函数负责复制参数。这很明确,因为目标函数是DetourFunction
函数的内部调用函数。
通过DetourDetach
在Hook事件中的调用,可以删除对目标函数的拦截。与DetourAttach
一样,DetourDetach
也有两个参数:目标指针的地址和指向DetourFunction
函数的指针。当Hook事务提交时,目标函数将被重写并恢复为其原始代码,Trampline
函数将被删除,目标指针将恢复为指向原始目标函数。
如果需要将Hook的API注入到目标程序中,则Hook需要编译成Dll。可以使用远程线程注入、Dll劫持等技术。也可以使用
DetourCreateProcessWithDllEx
或DetourCreateProcessWithDlls
将Dll注入到目标进程中。如果使用DetourCreateProcessWithDllEx
或DetourCreateProcessWithDlls
,则DllMain函数必须调用DetourRestoreAfterWith
。如果Dll可以在x86和x64混合环境中使用,则DllMain函数必须调用DetourIsHelperProcess
导出为序号1,rundll32.exe
以执行帮助任务来调用该API。
下面来注入一个刚刚到的Dll到一个进程中,测试一下效果
安装Detours库
VcPkg install detours:x86-windows VcPkg install detours:x64-windows