Skip to content

Commit 5f0998b

Browse files
committed
[SLIMDETOURS] Small refactors
- [HOOK] COM initialization should be done by the caller - [HOOK] Improve COM hook initialization - [SLIMDETOURS] **Refactor some APIs and add some comments**, code improvements
1 parent d87330b commit 5f0998b

16 files changed

Lines changed: 462 additions & 244 deletions

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ If your project configuration name is neither "Release" nor "Debug", [MSBuild sh
5252

5353
The usage has been simplified, e.g. the hook only needs one line:
5454
```C
55-
SlimDetoursSetHook((PVOID*)&g_pfnXxx, Hooked_Xxx);
55+
SlimDetoursInlineHook(TRUE, (PVOID*)&g_pfnXxx, Hooked_Xxx); // Hook
56+
...
57+
SlimDetoursInlineHook(FALSE, (PVOID*)&g_pfnXxx, Hooked_Xxx); // Unhook
5658
```
57-
For more simplified API see [Wrapper.c](https://github.com/KNSoft/KNSoft.SlimDetours/blob/main/Source/SlimDetours/Wrapper.c).
59+
For more simplified API see [InlineHook.c](https://github.com/KNSoft/KNSoft.SlimDetours/blob/main/Source/SlimDetours/InlineHook.c).
5860
5961
### Details
6062

README.zh-CN.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ NuGet包[KNSoft.SlimDetours](https://www.nuget.org/packages/KNSoft.SlimDetours)
5252

5353
用法已进行了简化,例如挂钩仅需一行:
5454
```C
55-
SlimDetoursSetHook((PVOID*)&g_pfnXxx, Hooked_Xxx);
55+
SlimDetoursInlineHook(TRUE, (PVOID*)&g_pfnXxx, Hooked_Xxx); // 挂钩
56+
...
57+
SlimDetoursInlineHook(FALSE, (PVOID*)&g_pfnXxx, Hooked_Xxx); // 脱钩
5658
```
57-
更多简化的API参考[Wrapper.c](https://github.com/KNSoft/KNSoft.SlimDetours/blob/main/Source/SlimDetours/Wrapper.c)。
59+
更多简化的API参考[InlineHook.c](https://github.com/KNSoft/KNSoft.SlimDetours/blob/main/Source/SlimDetours/InlineHook.c)。
5860
5961
### 详细说明
6062

Source/Demo/COMHook.c

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ TEST_FUNC(COMHook)
5959
HRESULT hr;
6060
IOpenControlPanel* pocp1;
6161
IOpenControlPanel* pocp2;
62-
IOpenControlPanel* pocp3;
6362

6463
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
6564
if (FAILED(hr))
@@ -68,21 +67,22 @@ TEST_FUNC(COMHook)
6867
return;
6968
}
7069

71-
hr = CoCreateInstance(&CLSID_OpenControlPanel, NULL, CLSCTX_INPROC_SERVER, &IID_IOpenControlPanel, &pocp1);
70+
hr = SlimDetoursCOMHook(&CLSID_OpenControlPanel,
71+
&IID_IOpenControlPanel,
72+
FIELD_OFFSET(IOpenControlPanelVtbl, GetPath),
73+
(PVOID*)&g_pfnIOpenControlPanel_GetPath,
74+
Hooked_IOpenControlPanel_GetPath);
7275
if (FAILED(hr))
7376
{
74-
TEST_SKIP("CoCreateInstance failed with: 0x%08lX\n", hr);
77+
TEST_SKIP("SlimDetoursCOMHook failed with: 0x%08lX\n", hr);
7578
goto _Exit_0;
7679
}
7780

78-
hr = SlimDetoursSetTableHook((PVOID*)pocp1->lpVtbl,
79-
FIELD_OFFSET(IOpenControlPanelVtbl, GetPath),
80-
(PVOID*)&g_pfnIOpenControlPanel_GetPath,
81-
Hooked_IOpenControlPanel_GetPath);
81+
hr = CoCreateInstance(&CLSID_OpenControlPanel, NULL, CLSCTX_INPROC_SERVER, &IID_IOpenControlPanel, &pocp1);
8282
if (FAILED(hr))
8383
{
84-
TEST_SKIP("SlimDetoursSetVTableHook failed with: 0x%08lX\n", hr);
85-
goto _Exit_1;
84+
TEST_SKIP("CoCreateInstance failed with: 0x%08lX\n", hr);
85+
goto _Exit_0;
8686
}
8787
TEST_OK(Test_IOpenControlPanel_GetPath(pocp1));
8888

@@ -94,16 +94,6 @@ TEST_FUNC(COMHook)
9494
}
9595
TEST_OK(Test_IOpenControlPanel_GetPath(pocp2));
9696

97-
hr = CoCreateInstance(&CLSID_OpenControlPanel, NULL, CLSCTX_INPROC_SERVER, &IID_IOpenControlPanel, &pocp3);
98-
if (FAILED(hr))
99-
{
100-
TEST_SKIP("CoCreateInstance failed with: 0x%08lX\n", hr);
101-
goto _Exit_2;
102-
}
103-
TEST_OK(Test_IOpenControlPanel_GetPath(pocp3));
104-
105-
pocp2->lpVtbl->Release(pocp3);
106-
_Exit_2:
10797
pocp2->lpVtbl->Release(pocp2);
10898
_Exit_1:
10999
pocp1->lpVtbl->Release(pocp1);

Source/Demo/DelayHook.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
static BOOL g_bDelayAttach = FALSE;
1212

1313
static
14+
_Function_class_(DETOUR_DELAY_ATTACH_CALLBACK_FN)
1415
VOID
1516
CALLBACK
1617
DelayAttachCallback(

Source/Demo/Main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ Hooked_EqualRect(
8080
{
8181
BOOL Ret;
8282

83-
InterlockedIncrement(&g_lEqualRectCount);
83+
_InterlockedIncrement(&g_lEqualRectCount);
8484
UnitTest_FormatMessage("Hooked EqualRect enter: lprc1 = (%ld, %ld, %ld, %ld), lprc2 = (%ld, %ld, %ld, %ld)\n",
8585
lprc1->top,
8686
lprc1->right,
@@ -90,9 +90,9 @@ Hooked_EqualRect(
9090
lprc2->right,
9191
lprc2->bottom,
9292
lprc2->left);
93-
InterlockedIncrement(&g_lEqualRectRefCount);
93+
_InterlockedIncrement(&g_lEqualRectRefCount);
9494
Ret = g_pfnEqualRect(lprc1, lprc2);
95-
InterlockedDecrement(&g_lEqualRectRefCount);
95+
_InterlockedDecrement(&g_lEqualRectRefCount);
9696
UnitTest_FormatMessage("Hooked EqualRect leave with return value: %ld\n", Ret);
9797
return Ret;
9898
}

Source/Demo/TwiceSimpleHook.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ static LONG volatile g_lEqualRect = 0;
1010
static FN_EqualRect* g_pfnEqualRect1 = NULL;
1111
static FN_EqualRect* g_pfnEqualRect2 = NULL;
1212

13+
static
1314
BOOL
1415
WINAPI
1516
Hooked_EqualRect1(
@@ -21,6 +22,7 @@ Hooked_EqualRect1(
2122
return g_pfnEqualRect1(lprc1, lprc2);
2223
}
2324

25+
static
2426
BOOL
2527
WINAPI
2628
Hooked_EqualRect2(
@@ -46,16 +48,16 @@ TEST_FUNC(TwiceSimpleHook)
4648
}
4749

4850
g_pfnEqualRect1 = g_pfnEqualRect2 = g_pfnEqualRect;
49-
hr = SlimDetoursSetHook((PVOID)&g_pfnEqualRect1, Hooked_EqualRect1);
51+
hr = SlimDetoursInlineHook(TRUE, (PVOID)&g_pfnEqualRect1, Hooked_EqualRect1);
5052
if (FAILED(hr))
5153
{
52-
TEST_SKIP("1st SlimDetoursSetHook failed with 0x%08lX\n", hr);
54+
TEST_SKIP("1st SlimDetoursInlineHook failed with 0x%08lX\n", hr);
5355
return;
5456
}
55-
hr = SlimDetoursSetHook((PVOID)&g_pfnEqualRect2, Hooked_EqualRect2);
57+
hr = SlimDetoursInlineHook(TRUE, (PVOID)&g_pfnEqualRect2, Hooked_EqualRect2);
5658
if (FAILED(hr))
5759
{
58-
TEST_SKIP("2nd SlimDetoursSetHook failed with 0x%08lX\n", hr);
60+
TEST_SKIP("2nd SlimDetoursInlineHook failed with 0x%08lX\n", hr);
5961
return;
6062
}
6163

Source/KNSoft.SlimDetours.vcxproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,10 @@
207207
<ClCompile Include="SlimDetours\Thread.c" />
208208
<ClCompile Include="SlimDetours\Trampoline.c" />
209209
<ClCompile Include="SlimDetours\Transaction.c" />
210-
<ClCompile Include="SlimDetours\Wrapper.c" />
210+
<ClCompile Include="SlimDetours\InlineHook.c" />
211211
<None Include="packages.config" />
212212
<None Include="SlimDetours\SlimDetours.NDK.inl" />
213+
<None Include="SlimDetours\Utils.inl" />
213214
</ItemGroup>
214215
<ItemGroup>
215216
<ClInclude Include="Detours\src\detours.h" />

Source/KNSoft.SlimDetours.vcxproj.filters

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<ClCompile Include="SlimDetours\Transaction.c">
2828
<Filter>SlimDetours</Filter>
2929
</ClCompile>
30-
<ClCompile Include="SlimDetours\Wrapper.c">
30+
<ClCompile Include="SlimDetours\InlineHook.c">
3131
<Filter>SlimDetours</Filter>
3232
</ClCompile>
3333
<ClCompile Include="Detours\src\creatwth.cpp">
@@ -86,5 +86,8 @@
8686
<Filter>SlimDetours</Filter>
8787
</None>
8888
<None Include="packages.config" />
89+
<None Include="SlimDetours\Utils.inl">
90+
<Filter>SlimDetours</Filter>
91+
</None>
8992
</ItemGroup>
9093
</Project>

Source/SlimDetours/FuncTableHook.c

Lines changed: 90 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
22
* KNSoft.SlimDetours (https://github.com/KNSoft/KNSoft.SlimDetours) Function Table Hook Implementation
3-
*
4-
* Hook function address in a read-only table, used by COM/IAT/EAT/... hooking.
5-
*
3+
*
4+
* Hook function address in a read-only table, used by COM/IAT/... hooking.
5+
*
66
* Copyright (c) KNSoft.org (https://github.com/KNSoft). All rights reserved.
77
* Licensed under the MIT license.
88
*/
@@ -75,11 +75,11 @@ detour_hook_table_funcs(
7575
Method = Add2Ptr(pFuncTable, pHooks[i].ulOffset);
7676
if (bEnable)
7777
{
78-
*pHooks[i].ppOriginal = *Method;
79-
*Method = pHooks[i].pDetour;
78+
*pHooks[i].ppOldFunc = *Method;
79+
*Method = pHooks[i].pNewFunc;
8080
} else
8181
{
82-
*Method = *pHooks[i].ppOriginal;
82+
*Method = *pHooks[i].ppOldFunc;
8383
}
8484
}
8585

@@ -89,32 +89,105 @@ detour_hook_table_funcs(
8989

9090
HRESULT
9191
NTAPI
92-
SlimDetoursSetTableHook(
92+
SlimDetoursFuncTableHook(
9393
_In_ PVOID* pFuncTable,
9494
_In_ ULONG ulOffset,
95-
_Out_ PVOID* ppOriginal,
96-
_In_ PVOID pDetour)
95+
_Out_opt_ PVOID* ppOldFunc,
96+
_In_ PVOID pNewFunc)
9797
{
98-
return HRESULT_FROM_NT(detour_hook_table_func(pFuncTable, ulOffset, ppOriginal, pDetour));
98+
return HRESULT_FROM_NT(detour_hook_table_func(pFuncTable, ulOffset, ppOldFunc, pNewFunc));
9999
}
100100

101101
HRESULT
102102
NTAPI
103-
SlimDetoursUnsetTableHook(
103+
SlimDetoursFuncTableHooks(
104+
_In_ BOOL bEnable,
104105
_In_ PVOID* pFuncTable,
105-
_In_ ULONG ulOffset,
106-
_In_ PVOID pOriginal)
106+
_In_ ULONG ulCount,
107+
_Inout_updates_(ulCount) PDETOUR_FUNC_TABLE_HOOK pHooks)
107108
{
108-
return HRESULT_FROM_NT(detour_hook_table_func(pFuncTable, ulOffset, NULL, pOriginal));
109+
return HRESULT_FROM_NT(detour_hook_table_funcs(bEnable, pFuncTable, ulCount, pHooks));
109110
}
110111

112+
/* COM Hook */
113+
114+
typedef
115+
_Check_return_
116+
HRESULT
117+
STDAPICALLTYPE
118+
FN_CoCreateInstanceEx(
119+
_In_ REFCLSID Clsid,
120+
_In_opt_ IUnknown* punkOuter,
121+
_In_ DWORD dwClsCtx,
122+
_In_opt_ COSERVERINFO* pServerInfo,
123+
_In_ DWORD dwCount,
124+
_Inout_updates_(dwCount) MULTI_QI* pResults);
125+
126+
static PVOID g_hComBase = NULL;
127+
128+
static CONST UNICODE_STRING g_usCombaseDllName = RTL_CONSTANT_STRING(L"combase.dll");
129+
static CONST ANSI_STRING g_asCoCreateInstanceEx = RTL_CONSTANT_STRING("CoCreateInstanceEx");
130+
static FN_CoCreateInstanceEx* g_pfnCoCreateInstanceEx = NULL;
131+
132+
static PS_RUNONCE g_stRunOnceCombaseInit = PS_RUNONCE_INIT;
133+
static NTSTATUS g_lCombaseInitStatus = STATUS_UNSUCCESSFUL;
134+
111135
HRESULT
112136
NTAPI
113-
SlimDetoursEnableTableHooks(
137+
SlimDetoursCOMHooks(
114138
_In_ BOOL bEnable,
115-
_In_ PVOID* pFuncTable,
139+
_In_ REFCLSID rCLSID,
140+
_In_ REFCLSID rIID,
116141
_In_ ULONG ulCount,
117142
_Inout_updates_(ulCount) PDETOUR_FUNC_TABLE_HOOK pHooks)
118143
{
119-
return HRESULT_FROM_NT(detour_hook_table_funcs(bEnable, pFuncTable, ulCount, pHooks));
144+
NTSTATUS Status;
145+
HRESULT hr;
146+
MULTI_QI MQI = { rIID };
147+
148+
/* Initialize combase.dll */
149+
if (PS_RunOnceBegin(&g_stRunOnceCombaseInit))
150+
{
151+
Status = LdrLoadDll(NULL, NULL, (PUNICODE_STRING)&g_usCombaseDllName, &g_hComBase);
152+
if (!NT_SUCCESS(Status))
153+
{
154+
goto _Init_Exit;
155+
}
156+
Status = LdrGetProcedureAddress(g_hComBase, (PANSI_STRING)&g_asCoCreateInstanceEx, 0, (PVOID*)&g_pfnCoCreateInstanceEx);
157+
if (!NT_SUCCESS(Status))
158+
{
159+
LdrUnloadDll(g_hComBase);
160+
g_hComBase = NULL;
161+
goto _Init_Exit;
162+
}
163+
Status = STATUS_SUCCESS;
164+
_Init_Exit:
165+
g_lCombaseInitStatus = Status;
166+
PS_RunOnceEnd(&g_stRunOnceCombaseInit, Status == STATUS_SUCCESS);
167+
}
168+
if (!NT_SUCCESS(g_lCombaseInitStatus))
169+
{
170+
return HRESULT_FROM_NT(g_lCombaseInitStatus);
171+
}
172+
173+
/* Create COM Object and set VTable Hooks */
174+
hr = g_pfnCoCreateInstanceEx(rCLSID, NULL, CLSCTX_ALL, NULL, 1, &MQI);
175+
if (FAILED(hr))
176+
{
177+
goto _Create_Fail_0;
178+
}
179+
_Analysis_assume_(MQI.pItf != NULL);
180+
Status = detour_hook_table_funcs(bEnable, (PVOID*)MQI.pItf->lpVtbl, ulCount, pHooks);
181+
if (!NT_SUCCESS(Status))
182+
{
183+
hr = HRESULT_FROM_NT(Status);
184+
goto _Create_Fail_1;
185+
}
186+
hr = S_OK;
187+
188+
/* Cleanup */
189+
_Create_Fail_1:
190+
MQI.pItf->lpVtbl->Release(MQI.pItf);
191+
_Create_Fail_0:
192+
return hr;
120193
}

0 commit comments

Comments
 (0)