Skip to content

Commit 99b74db

Browse files
committed
feat: add vfunc hook and change api for vtable hook
1 parent 892edd4 commit 99b74db

File tree

6 files changed

+216
-55
lines changed

6 files changed

+216
-55
lines changed

plugify-plugin-polyhook.pplugin.in

Lines changed: 149 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@
123123
}
124124
},
125125
{
126-
"name": "HookVirtual",
126+
"name": "HookVirtualTable",
127127
"group": "Core",
128-
"description": "Sets a virtual hook",
129-
"funcName": "HookVirtual",
128+
"description": "Sets a virtual table hook",
129+
"funcName": "HookVirtualTable",
130130
"paramTypes": [
131131
{
132132
"type": "ptr64",
@@ -167,10 +167,10 @@
167167
}
168168
},
169169
{
170-
"name": "HookVirtualByFunc",
170+
"name": "HookVirtualTable2",
171171
"group": "Core",
172-
"description": "Sets a virtual hook by pointer",
173-
"funcName": "HookVirtualByFunc",
172+
"description": "Sets a virtual table hook by pointer",
173+
"funcName": "HookVirtualTable2",
174174
"paramTypes": [
175175
{
176176
"type": "ptr64",
@@ -210,6 +210,95 @@
210210
"description": "Returns hook pointer"
211211
}
212212
},
213+
214+
{
215+
"name": "HookVirtualFunc",
216+
"group": "Core",
217+
"description": "Sets a virtual function hook",
218+
"funcName": "HookVirtualFunc",
219+
"paramTypes": [
220+
{
221+
"type": "ptr64",
222+
"name": "pClass",
223+
"description": "Object pointer"
224+
},
225+
{
226+
"type": "int32",
227+
"name": "index",
228+
"description": "Vtable offset"
229+
},
230+
{
231+
"type": "uint8",
232+
"name": "returnType",
233+
"description": "Return type",
234+
"enum": {
235+
"name": "DataType"
236+
}
237+
},
238+
{
239+
"type": "uint8[]",
240+
"name": "arguments",
241+
"description": "Arguments type array",
242+
"enum": {
243+
"name": "DataType"
244+
}
245+
},
246+
{
247+
"type": "int32",
248+
"name": "varIndex",
249+
"description": "Index of a first variadic argument or -1",
250+
"default": -1
251+
}
252+
],
253+
"retType": {
254+
"type": "ptr64",
255+
"description": "Returns hook pointer"
256+
}
257+
},
258+
{
259+
"name": "HookVirtualFunc2",
260+
"group": "Core",
261+
"description": "Sets a virtual function hook by pointer",
262+
"funcName": "HookVirtualFunc2",
263+
"paramTypes": [
264+
{
265+
"type": "ptr64",
266+
"name": "pClass",
267+
"description": "Object pointer"
268+
},
269+
{
270+
"type": "ptr64",
271+
"name": "pFunc",
272+
"description": "Vtable member function address"
273+
},
274+
{
275+
"type": "uint8",
276+
"name": "returnType",
277+
"description": "Return type",
278+
"enum": {
279+
"name": "DataType"
280+
}
281+
},
282+
{
283+
"type": "uint8[]",
284+
"name": "arguments",
285+
"description": "Arguments type array",
286+
"enum": {
287+
"name": "DataType"
288+
}
289+
},
290+
{
291+
"type": "int32",
292+
"name": "varIndex",
293+
"description": "Index of a first variadic argument or -1",
294+
"default": -1
295+
}
296+
],
297+
"retType": {
298+
"type": "ptr64",
299+
"description": "Returns hook pointer"
300+
}
301+
},
213302
{
214303
"name": "UnhookDetour",
215304
"group": "Core",
@@ -228,10 +317,54 @@
228317
}
229318
},
230319
{
231-
"name": "UnhookVirtual",
320+
"name": "UnhookVirtualTable",
321+
"group": "Core",
322+
"description": "Removes a virtual hook table",
323+
"funcName": "UnhookVirtualTable",
324+
"paramTypes": [
325+
{
326+
"type": "ptr64",
327+
"name": "pClass",
328+
"description": "Object pointer"
329+
},
330+
{
331+
"type": "int32",
332+
"name": "index",
333+
"description": "Value to set"
334+
}
335+
],
336+
"retType": {
337+
"type": "bool",
338+
"description": "Returns true on success, false otherwise"
339+
}
340+
},
341+
{
342+
"name": "UnhookVirtualTable2",
343+
"group": "Core",
344+
"description": "Removes a virtual table hook by pointer",
345+
"funcName": "UnhookVirtualTable2",
346+
"paramTypes": [
347+
{
348+
"type": "ptr64",
349+
"name": "pClass",
350+
"description": "Object pointer"
351+
},
352+
{
353+
"type": "ptr64",
354+
"name": "pFunc",
355+
"description": "Vtable member function address"
356+
}
357+
],
358+
"retType": {
359+
"type": "bool",
360+
"description": "Returns true on success, false otherwise"
361+
}
362+
},
363+
{
364+
"name": "UnhookVirtualFunc",
232365
"group": "Core",
233-
"description": "Removes a virtual hook",
234-
"funcName": "UnhookVirtual",
366+
"description": "Removes a virtual function table",
367+
"funcName": "UnhookVirtualFunc",
235368
"paramTypes": [
236369
{
237370
"type": "ptr64",
@@ -250,10 +383,10 @@
250383
}
251384
},
252385
{
253-
"name": "UnhookVirtualByFunc",
386+
"name": "UnhookVirtualFunc2",
254387
"group": "Core",
255-
"description": "Removes a virtual hook by pointer",
256-
"funcName": "UnhookVirtualByFunc",
388+
"description": "Removes a virtual function hook by pointer",
389+
"funcName": "UnhookVirtualFunc2",
257390
"paramTypes": [
258391
{
259392
"type": "ptr64",
@@ -311,10 +444,10 @@
311444
}
312445
},
313446
{
314-
"name": "FindVirtualByFunc",
447+
"name": "FindVirtual2",
315448
"group": "Lookup",
316449
"description": "Attempts to find existing detour hook by pointer",
317-
"funcName": "FindVirtualByFunc",
450+
"funcName": "FindVirtual2",
318451
"paramTypes": [
319452
{
320453
"type": "ptr64",
@@ -333,10 +466,10 @@
333466
}
334467
},
335468
{
336-
"name": "GetVTableIndex",
469+
"name": "GetVirtualIndex",
337470
"group": "Lookup",
338471
"description": "Attempts to find virtual table index of virtual function",
339-
"funcName": "GetVTableIndex",
472+
"funcName": "GetVirtualIndex",
340473
"paramTypes": [
341474
{
342475
"type": "ptr64",

src/callback.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ namespace PLH {
123123

124124
private:
125125
static asmjit::TypeId getTypeId(DataType type) noexcept;
126-
static bool hasHiArgSlot(const asmjit::x86::Compiler& compiler, const asmjit::TypeId typeId) noexcept;
126+
static bool hasHiArgSlot(const asmjit::x86::Compiler& compiler, asmjit::TypeId typeId) noexcept;
127127

128128
std::weak_ptr<asmjit::JitRuntime> m_rt;
129129
std::array<std::vector<CallbackHandler>, 2> m_callbacks;

src/plugin.cpp

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Callback* PolyHookPlugin::hookDetour(void* pFunc, DataType returnType, std::span
8484
return m_detours.emplace(pFunc, DHook{std::move(detour), std::move(callback)}).first->second.callback.get();
8585
}
8686

87+
template<typename T>
8788
Callback* PolyHookPlugin::hookVirtual(void* pClass, int index, DataType returnType, std::span<const DataType> arguments, uint8_t varIndex) {
8889
if (!pClass || index == -1)
8990
return nullptr;
@@ -115,7 +116,7 @@ Callback* PolyHookPlugin::hookVirtual(void* pClass, int index, DataType returnTy
115116

116117
redirectMap[index] = JIT;
117118

118-
vtable = std::make_unique<VTableSwapHook>((uint64_t) pClass, redirectMap, &origVFuncs);
119+
vtable = std::make_unique<T>((uint64_t) pClass, redirectMap, &origVFuncs);
119120
if (!vtable->hook()) {
120121
for (auto& [_, cb] : callbacks) {
121122
m_removals.push({std::move(cb), Clock::now() + 1s});
@@ -130,8 +131,9 @@ Callback* PolyHookPlugin::hookVirtual(void* pClass, int index, DataType returnTy
130131
return callback.get();
131132
}
132133

134+
template<typename T>
133135
Callback* PolyHookPlugin::hookVirtual(void* pClass, void* pFunc, DataType returnType, std::span<const DataType> arguments, uint8_t varIndex) {
134-
return hookVirtual(pClass, getVirtualTableIndex(pFunc), returnType, arguments, varIndex);
136+
return hookVirtual<T>(pClass, getVirtualIndex(pFunc), returnType, arguments, varIndex);
135137
}
136138

137139
bool PolyHookPlugin::unhookDetour(void* pFunc) {
@@ -152,6 +154,7 @@ bool PolyHookPlugin::unhookDetour(void* pFunc) {
152154
return false;
153155
}
154156

157+
template<typename T>
155158
bool PolyHookPlugin::unhookVirtual(void* pClass, int index) {
156159
if (!pClass || index == -1)
157160
return false;
@@ -175,7 +178,7 @@ bool PolyHookPlugin::unhookVirtual(void* pClass, int index) {
175178
return true;
176179
}
177180

178-
vtable = std::make_unique<VTableSwapHook>((uint64_t) pClass, redirectMap, &origVFuncs);
181+
vtable = std::make_unique<T>((uint64_t) pClass, redirectMap, &origVFuncs);
179182
if (!vtable->hook()) {
180183
for (auto& [_, cb] : callbacks) {
181184
m_removals.push({std::move(cb), Clock::now() + 1s});
@@ -191,8 +194,9 @@ bool PolyHookPlugin::unhookVirtual(void* pClass, int index) {
191194
return false;
192195
}
193196

197+
template<typename T>
194198
bool PolyHookPlugin::unhookVirtual(void* pClass, void* pFunc) {
195-
return unhookVirtual(pClass, getVirtualTableIndex(pFunc));
199+
return unhookVirtual<T>(pClass, getVirtualIndex(pFunc));
196200
}
197201

198202
Callback* PolyHookPlugin::findDetour(void* pFunc) const {
@@ -216,7 +220,7 @@ Callback* PolyHookPlugin::findVirtual(void* pClass, int index) const {
216220
}
217221

218222
Callback* PolyHookPlugin::findVirtual(void* pClass, void* pFunc) const {
219-
return findVirtual(pClass, getVirtualTableIndex(pFunc));
223+
return findVirtual(pClass, getVirtualIndex(pFunc));
220224
}
221225

222226
void PolyHookPlugin::unhookAll() {
@@ -235,7 +239,7 @@ void PolyHookPlugin::unhookAllVirtual(void* pClass) {
235239
}
236240
}
237241

238-
int PolyHookPlugin::getVirtualTableIndex(void* pFunc, ProtFlag flag) const {
242+
int PolyHookPlugin::getVirtualIndex(void* pFunc, ProtFlag flag) const {
239243
constexpr size_t size = 12;
240244

241245
MemoryProtector protector((uint64_t)pFunc, size, flag, *(MemAccessor*)this);
@@ -348,28 +352,40 @@ PLUGIFY_WARN_IGNORE(4190)
348352
#endif
349353

350354
extern "C" {
355+
// Detour
351356
PLUGIN_API Callback* HookDetour(void* pFunc, DataType returnType, const plg::vector<DataType>& arguments, int varIndex) {
352357
return g_polyHookPlugin.hookDetour(pFunc, returnType, arguments, static_cast<uint8_t>(varIndex));
353358
}
354-
355-
PLUGIN_API Callback* HookVirtual(void* pClass, int index, DataType returnType, const plg::vector<DataType>& arguments, int varIndex) {
356-
return g_polyHookPlugin.hookVirtual(pClass, index, returnType, arguments, static_cast<uint8_t>(varIndex));
357-
}
358-
359-
PLUGIN_API Callback* HookVirtualByFunc(void* pClass, void* pFunc, DataType returnType, const plg::vector<DataType>& arguments, int varIndex) {
360-
return g_polyHookPlugin.hookVirtual(pClass, pFunc, returnType, arguments, static_cast<uint8_t>(varIndex));
361-
}
362-
363359
PLUGIN_API bool UnhookDetour(void* pFunc) {
364360
return g_polyHookPlugin.unhookDetour(pFunc);
365361
}
366362

367-
PLUGIN_API bool UnhookVirtual(void* pClass, int index) {
368-
return g_polyHookPlugin.unhookVirtual(pClass, index);
363+
// Virtual (VTableSwapHook)
364+
PLUGIN_API Callback* HookVirtualTable(void* pClass, int index, DataType returnType, const plg::vector<DataType>& arguments, int varIndex) {
365+
return g_polyHookPlugin.hookVirtual<VTableSwapHook>(pClass, index, returnType, arguments, static_cast<uint8_t>(varIndex));
366+
}
367+
PLUGIN_API Callback* HookVirtualTable2(void* pClass, void* pFunc, DataType returnType, const plg::vector<DataType>& arguments, int varIndex) {
368+
return g_polyHookPlugin.hookVirtual<VTableSwapHook>(pClass, pFunc, returnType, arguments, static_cast<uint8_t>(varIndex));
369+
}
370+
PLUGIN_API bool UnhookVirtualTable(void* pClass, int index) {
371+
return g_polyHookPlugin.unhookVirtual<VTableSwapHook>(pClass, index);
372+
}
373+
PLUGIN_API bool UnhookVirtualTable2(void* pClass, void* pFunc) {
374+
return g_polyHookPlugin.unhookVirtual<VTableSwapHook>(pClass, pFunc);
369375
}
370376

371-
PLUGIN_API bool UnhookVirtualByFunc(void* pClass, void* pFunc) {
372-
return g_polyHookPlugin.unhookVirtual(pClass, pFunc);
377+
// Virtual (VFuncSwapHook)
378+
PLUGIN_API Callback* HookVirtualFunc(void* pClass, int index, DataType returnType, const plg::vector<DataType>& arguments, int varIndex) {
379+
return g_polyHookPlugin.hookVirtual<VFuncSwapHook>(pClass, index, returnType, arguments, static_cast<uint8_t>(varIndex));
380+
}
381+
PLUGIN_API Callback* HookVirtualFunc2(void* pClass, void* pFunc, DataType returnType, const plg::vector<DataType>& arguments, int varIndex) {
382+
return g_polyHookPlugin.hookVirtual<VFuncSwapHook>(pClass, pFunc, returnType, arguments, static_cast<uint8_t>(varIndex));
383+
}
384+
PLUGIN_API bool UnhookVirtualFunc(void* pClass, int index) {
385+
return g_polyHookPlugin.unhookVirtual<VFuncSwapHook>(pClass, index);
386+
}
387+
PLUGIN_API bool UnhookVirtualFunc2(void* pClass, void* pFunc) {
388+
return g_polyHookPlugin.unhookVirtual<VFuncSwapHook>(pClass, pFunc);
373389
}
374390

375391
PLUGIN_API Callback* FindDetour(void* pFunc) {
@@ -380,12 +396,12 @@ extern "C" {
380396
return g_polyHookPlugin.findVirtual(pClass, index);
381397
}
382398

383-
PLUGIN_API Callback* FindVirtualByFunc(void* pClass, void* pFunc) {
399+
PLUGIN_API Callback* FindVirtual2(void* pClass, void* pFunc) {
384400
return g_polyHookPlugin.findVirtual(pClass, pFunc);
385401
}
386402

387-
PLUGIN_API int GetVTableIndex(void* pFunc) {
388-
return g_polyHookPlugin.getVirtualTableIndex(pFunc);
403+
PLUGIN_API int GetVirtualIndex(void* pFunc) {
404+
return g_polyHookPlugin.getVirtualIndex(pFunc);
389405
}
390406

391407
PLUGIN_API void UnhookAll() {

0 commit comments

Comments
 (0)