KeepingUpWithDetours

Detours工作原理

samples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <windows.h>
#include <detours.h>

static LONG dwSlept = 0;

// Target pointer for the uninstrumented Sleep API.
//
static VOID (WINAPI * TrueSleep)(DWORD dwMilliseconds) = Sleep;

// Detour function that replaces the Sleep API.
//
VOID WINAPI TimedSleep(DWORD dwMilliseconds)
{
// Save the before and after times around calling the Sleep API.
DWORD dwBeg = GetTickCount();
TrueSleep(dwMilliseconds);
DWORD dwEnd = GetTickCount();

InterlockedExchangeAdd(&dwSlept, dwEnd - dwBeg);
}

// DllMain function attaches and detaches the TimedSleep detour to the
// Sleep target function. The Sleep target function is referred to
// through the TrueSleep target pointer.
//
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
if (DetourIsHelperProcess()) {
return TRUE;
}

if (dwReason == DLL_PROCESS_ATTACH) {
DetourRestoreAfterWith();

DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
DetourTransactionCommit();
}
else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TrueSleep, TimedSleep);
DetourTransactionCommit();
}
return TRUE;
}

functions

basic

  • DetourTransactionBegin/创建hook任务

  • DetourUpdateThread/刷新线程

  • DetourAttach/DetourDetach/可以执行多次,hook/unhook多个API

    1
    2
    3
    4
    LONG DetourAttach(
    _Inout_ PVOID * ppPointer, //Pointer to the target pointer to which the detour will be attached.
    _In_ PVOID pDetour //Pointer to the detour function.
    );
  • DetourTransactionCommit/提交hook任务

  • DetourCreateProcessWithDlls/创建进程并加载特定dll

  • DetourRestoreAfterWith/创建新线程后修复内存中import table

comply

  • 编译环境:
    • x86 Native Tools Command Prompt for VS 2019
    • nmake.exe
    • sn.exe 强签名工具
  • Detour-master目录下执行

    1
    nmake -f ./MakeFile

    notes

  • 添加头文件和静态库,与源代码放在同一文件夹下

    1
    2
    #include "detours.h"
    #pragma comment(lib,"detours.lib")
  • 使用static类型,防止影响其他程序

    1
    2
    3
    4
    5
    static int (WINAPI *OldMessageBox)(
    HWND hWnd,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType) = MessageBox;
  • 用来替换的函数原型与原函数一致

    1
    2
    3
    4
    5
    6
    7
    8
    int WINAPI NewMessageBox(
    HWND hWnd,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType)
    {
    return 0;
    }
  • 要在Release模式下进行调试

references