forked from microsoft/Detours
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathSlimDetours.h
280 lines (248 loc) · 9.17 KB
/
SlimDetours.h
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
* KNSoft.SlimDetours (https://github.com/KNSoft/KNSoft.SlimDetours)
* Copyright (c) KNSoft.org (https://github.com/KNSoft). All rights reserved.
* Licensed under the MIT license.
*
* Source base on Microsoft Detours:
*
* Microsoft Research Detours Package, Version 4.0.1
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT license.
*/
#pragma once
#include <Windows.h>
#if !defined(_X86_) && !defined(_AMD64_) && !defined(_ARM64_)
#error Unsupported architecture (x86, amd64, arm64)
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Improved original Detours API */
#define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0)
#define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1)
HRESULT
NTAPI
SlimDetoursTransactionBegin(VOID);
HRESULT
NTAPI
SlimDetoursTransactionAbort(VOID);
HRESULT
NTAPI
SlimDetoursTransactionCommit(VOID);
HRESULT
NTAPI
SlimDetoursAttach(
_Inout_ PVOID* ppPointer,
_In_ PVOID pDetour);
HRESULT
NTAPI
SlimDetoursDetach(
_Inout_ PVOID* ppPointer,
_In_ PVOID pDetour);
PVOID
NTAPI
SlimDetoursCodeFromPointer(
_In_ PVOID pPointer);
PVOID
NTAPI
SlimDetoursCopyInstruction(
_In_opt_ PVOID pDst,
_In_ PVOID pSrc,
_Out_opt_ PVOID* ppTarget,
_Out_opt_ LONG* plExtra);
/* Inline Hook, base on Detours */
/// <summary>
/// Set or unset a single inline hook
/// </summary>
/// <param name="bEnable">Set to TRUE to hook, or FALSE to unhook.</param>
/// <param name="ppPointer">See also SlimDetoursAttach or SlimDetoursDetach.</param>
/// <param name="pDetour">See also SlimDetoursAttach or SlimDetoursDetach.</param>
/// <returns>Returns HRESULT</returns>
/// <seealso cref="SlimDetoursAttach"/>
/// <seealso cref="SlimDetoursDetach"/>
HRESULT
NTAPI
SlimDetoursInlineHook(
_In_ BOOL bEnable,
_Inout_ PVOID* ppPointer,
_In_ PVOID pDetour);
typedef struct _DETOUR_INLINE_HOOK
{
PCSTR pszFuncName; // Can be an ordinal
PVOID* ppPointer; // Pointer to a variable contains the original function address before hooking,
// and will be replaced with trampoline address after hooking
PVOID pDetour; // Address of detour function
} DETOUR_INLINE_HOOK, *PDETOUR_INLINE_HOOK;
/// <summary>
/// Initialize an inline hook array
/// </summary>
/// <param name="hModule">Handle to the module exported those functions.</param>
/// <param name="ppPointer">See also <c>SlimDetoursAttach</c> or <c>SlimDetoursDetach</c>.</param>
/// <param name="pDetour">See also <c>SlimDetoursAttach</c> or <c>SlimDetoursDetach</c>.</param>
/// <returns>Return HRESULT</returns>
/// <remarks>
/// Get function address by <c>pszFuncName</c> and store in <c>*ppPointer</c>
/// for each <c>DETOUR_INLINE_HOOK</c> element.
/// </remarks>
/// <seealso cref="SlimDetoursAttach"/>
/// <seealso cref="SlimDetoursDetach"/>
HRESULT
NTAPI
SlimDetoursInitInlineHooks(
_In_ HMODULE hModule,
_In_ ULONG ulCount,
_Inout_updates_(ulCount) PDETOUR_INLINE_HOOK pHooks);
/// <summary>
/// Set or unset multiple inline hooks in a same target module
/// </summary>
/// <param name="bEnable">Set to TRUE to hook, or FALSE to unhook.</param>
/// <param name="ulCount">Number of elements in <c>pHooks</c> array.</param>
/// <param name="pHooks">A pointer point to an <c>DETOUR_INLINE_HOOK</c> array.</param>
/// <returns>Return HRESULT</returns>
/// <remarks>
/// <c>*ppPointer</c> and <c>pDetour</c> in <c>DETOUR_INLINE_HOOK</c>
/// should be initialized before calling this function.
/// </remarks>
/// <seealso cref="SlimDetoursInitInlineHooks"/>
/// <seealso cref="SlimDetoursInlineHook"/>
HRESULT
NTAPI
SlimDetoursInlineHooks(
_In_ BOOL bEnable,
_In_ ULONG ulCount,
_Inout_updates_(ulCount) PDETOUR_INLINE_HOOK pHooks);
/* Function Table Hook, by SlimDetours */
/// <summary>
/// Set or unset a single function hook in a function address table.
/// </summary>
/// <param name="pFuncTable">Pointer to the target function address table.</param>
/// <param name="ulOffset">Offset to the target function address in the table.</param>
/// <param name="ppOldFunc">Optional, pointer to a variable to save the old function address.</param>
/// <param name="pNewFunc">Address of the new function to overwrite.</param>
/// <returns>Return HRESULT</returns>
/// <remarks>
/// Function address table should be an array that each element is a function address.
/// SlimDetours overwrite corresponding function address in the table to implement the hooking.
/// This is useful to do COM/IAT/... hook, and automatically adjust write-protection on the table when writing it.
/// </remarks>
HRESULT
NTAPI
SlimDetoursFuncTableHook(
_In_ PVOID* pFuncTable,
_In_ ULONG ulOffset,
_Out_opt_ PVOID* ppOldFunc,
_In_ PVOID pNewFunc);
typedef struct _DETOUR_FUNC_TABLE_HOOK
{
ULONG ulOffset; // Offset to the target function address in the table
PVOID* ppOldFunc; // Pointer to a variable contains the old function address
PVOID pNewFunc; // Address of new function
} DETOUR_FUNC_TABLE_HOOK, *PDETOUR_FUNC_TABLE_HOOK;
/// <summary>
/// Set or unset multiple function hooks in a same function address table.
/// </summary>
/// <param name="bEnable">Set to TRUE to hook, or FALSE to unhook.</param>
/// <param name="pFuncTable">Pointer to the target function address table.</param>
/// <param name="ulCount">Number of elements in <c>pHooks</c> array.</param>
/// <param name="pHooks">A pointer point to an <c>DETOUR_FUNC_TABLE_HOOK</c> array.</param>
/// <returns>Return HRESULT</returns>
/// <seealso cref="SlimDetoursFuncTableHook"/>
HRESULT
NTAPI
SlimDetoursFuncTableHooks(
_In_ BOOL bEnable,
_In_ PVOID* pFuncTable,
_In_ ULONG ulCount,
_Inout_updates_(ulCount) PDETOUR_FUNC_TABLE_HOOK pHooks);
/// <summary>
/// Set or unset multiple function hooks in a same COM interface.
/// </summary>
/// <param name="bEnable">Set to TRUE to hook, or FALSE to unhook.</param>
/// <param name="rCLSID">See also <c>rclsid</c> parameter of <c>CoCreateInstance</c>.</param>
/// <param name="rIID">See also <c>riid</c> parameter of <c>CoCreateInstance</c>.</param>
/// <param name="ulCount">Number of elements in <c>pHooks</c> array.</param>
/// <param name="pHooks">A pointer point to an <c>DETOUR_FUNC_TABLE_HOOK</c> array.</param>
/// <returns>Return HRESULT</returns>
/// <remarks>
/// COM should be initialized before calling this function,
/// a wrong COM context (or apartment type) may cause hooks ineffective and even crash.
/// <c>DETOUR_FUNC_TABLE_HOOK.ulOffset</c> should be the offset to a function address in the vtable of COM object.
/// e.g. <c>FIELD_OFFSET(IOpenControlPanelVtbl, GetPath)</c>.
/// </remarks>
/// <seealso cref="CoInitialize"/>
/// <seealso cref="CoCreateInstance"/>
/// <seealso cref="SlimDetoursFuncTableHooks"/>
HRESULT
NTAPI
SlimDetoursCOMHooks(
_In_ BOOL bEnable,
_In_ REFCLSID rCLSID,
_In_ REFCLSID rIID,
_In_ ULONG ulCount,
_Inout_updates_(ulCount) PDETOUR_FUNC_TABLE_HOOK pHooks);
/// <summary>
/// Set or unset a singe function hook in a COM interface.
/// </summary>
/// <seealso cref="SlimDetoursCOMHooks"/>
FORCEINLINE
HRESULT
SlimDetoursCOMHook(
_In_ REFCLSID rCLSID,
_In_ REFCLSID rIID,
_In_ ULONG ulOffset,
_Out_opt_ PVOID* ppOldFunc,
_In_ PVOID pNewFunc)
{
DETOUR_FUNC_TABLE_HOOK Hook;
Hook.ulOffset = ulOffset;
if (ppOldFunc != NULL)
{
Hook.ppOldFunc = ppOldFunc;
Hook.pNewFunc = pNewFunc;
} else
{
Hook.ppOldFunc = &pNewFunc;
}
return SlimDetoursCOMHooks(ppOldFunc != NULL, rCLSID, rIID, 1, &Hook);
}
/* Delay Hook, by SlimDetours */
#if (NTDDI_VERSION >= NTDDI_WIN6)
typedef
_Function_class_(DETOUR_DELAY_ATTACH_CALLBACK_FN)
VOID
CALLBACK
DETOUR_DELAY_ATTACH_CALLBACK_FN(
_In_ HRESULT Result,
_In_ PVOID* ppPointer,
_In_ PCWSTR DllName,
_In_ PCSTR Function,
_In_opt_ PVOID Context);
typedef DETOUR_DELAY_ATTACH_CALLBACK_FN *PDETOUR_DELAY_ATTACH_CALLBACK_FN;
/// <summary>
/// Delay hook, set hooks automatically when target DLL loaded.
/// </summary>
/// <param name="ppPointer">Variable to receive the address of the trampoline when hook apply.</param>
/// <param name="pDetour">Pointer to the detour function.</param>
/// <param name="DllName">Name of target DLL.</param>
/// <param name="Function">Name of target function.</param>
/// <param name="Callback">Optional. Callback to receive delay hook notification.</param>
/// <param name="Context">Optional. A parameter to be passed to the callback function.</param>
/// <returns>
/// Returns HRESULT.
/// HRESULT_FROM_NT(STATUS_PENDING): Delay hook register successfully.
/// Other success status: Hook is succeeded right now, delay hook won't execute.
/// Otherwise, returns an error HRESULT from NTSTATUS.
/// </returns>
HRESULT
NTAPI
SlimDetoursDelayAttach(
_In_ PVOID* ppPointer,
_In_ PVOID pDetour,
_In_ PCWSTR DllName,
_In_ PCSTR Function,
_In_opt_ __callback PDETOUR_DELAY_ATTACH_CALLBACK_FN Callback,
_In_opt_ PVOID Context);
#endif /* (NTDDI_VERSION >= NTDDI_WIN6) */
#ifdef __cplusplus
}
#endif