Reloaded-Project / Reloaded.Hooks

Advanced native function hooks for x86, x64. Welcome to the next level!
GNU Lesser General Public License v3.0
213 stars 33 forks source link

Add HookedObjectVirtualFunctionTable #13

Closed 12354 closed 2 years ago

12354 commented 2 years ago

Hooking virtual functions is currently done in Reloaded.Hooks by making changes to the function itself in memory. This hooks the original function and therefore everytime the virtual function of an object is called, the hook will be called instead.

Hooking this way lead to problems for me(it appears mixing Reloaded.Hooks with already hooked SteamVR hooks is not currently supported/working)

I've added HookedObjectVirtualFunctionTable and (as a utility) ReloadedHooks.HookObjectVirtualFunctionTablePointer. This class hooks the virtual function table pointer of an object by copying its virtual function table and changing its vtable pointer to the copy. Therefore only this object's vtable is hooked, other objects are unaffected. To hook a function, the entry in the vtable copy is then changed. By hooking the vtable this way, it's clear our hooks are compatible with other already existing hooks.

I've implemented these new classes by following the already existing interfaces IVirtualFunctionTable and IHook

The naming of the new classes (HookedObjectVirtualFunctionTable and VTableEntryHook) should hopefully make the difference to the old VirtualFunctionTable clear enough, but feel free to change them.

I've also added tests which test calling the original functions of the vtable with the new class, hooking the vtable pointer and calling the unhooked virtual functions and hooking the vtable pointer and the functions and calling the functions.

Sewer56 commented 2 years ago

Thanks for contributing! Looks good to me at first glance. I'll doublecheck tomorrow after a nap and merge the change as needed.

For ReloadedHooks, please use <inheritdoc/> so it copies over from the base interface.

12354 commented 2 years ago

Thanks for your amazing library :)

Good point on inheritdoc, I'll be more thorough in the future.

Sewer56 commented 2 years ago

Sorry for the delay, I had... unexpected emotional complications. I also had to figure out a new tool for code coverage as OpenCover doesn't support net6.0 and is discontinued.

An updated library should be live about now, and soon propagate onto the likes of Reloaded.SharedLib.Hooks.ReloadedII, for those using it in conjunction with Reloaded-II.

12354 commented 2 years ago

No worries, thanks for the merge. I like the changes you made :)

I hope you have a happy new year anyways

Sewer56 commented 2 years ago

I forgot to mention. You might be interested in the Reloaded-II project.

EasyHook is getting pretty dated and .NET Framework doesn't receive updates anymore.

12354 commented 2 years ago

Thanks for the hint :). I am already not using EasyHook anymore, since I learned about Reloaded. I'm using a modified version of your Reloaded Bootstrapper to inject my .Net 6 assembly into other processes :) I checked out the entire reloaded project, and it's pretty amazing. I might do some more pull requests in the future.

Sewer56 commented 2 years ago

Important Note.

If you're using .NET 6 and hooking Windows APIs, be careful.

There is a blocking runtime issue (hence why Reloaded-II isn't using 6.0 yet) involving native->managed transitions. I found it just before .NET 6 release, but still haven't gotten around to fully investigating it (hence no issue report on the runtime repo), as I had other projects going on and a big Reloaded-II update to do.

Basically:

I should hopefully report this not too long from now; but it's just a warning for the time being. This only affects .NET 6, .NET 5 and earlier are not affected.