Injecting hook for method that does not exists (lol?)

Started by RawCode, January 04, 2017, 05:44:39 AM

Previous topic - Next topic

RawCode

Sometimes people tell me, what my own code can and can't do, sometimes they are right, sometimes they are wrong, this is second case.

Yes, technically you can't inject new code into method, that have no references, but this does not mean, that you can't inject code into method one step above.

All and every virtual method is instance one, you can't (legally) have method both static and virtual, reason behind this is virtual dispatch table, that stored inside all and every object, value types don't have vtable, but this does not belong to this thread.

Unlike "static" methods, virtual ones are never (by normal code) called directly, you can call virtual method directly by natives and reflection, but normal code never does this.
Instead, object and vtable index are passed into dispatch table function, that select proper method to be called for passed object and jump into that method.

What this means?
We always have object reference and can perform secondary dispatch inside our managed code.
Yes some objects does not have virtual method we want, instead, we will hook base method, copy paste entire code and inject additional branch with custom code for that specific object type.
Sounds simple, well, you already can copypaste methods from game into your "detours" it's about copy pasting two methods into single body and add branch condition to select proper one.

Little setup code, we have one base type that have one method we don't want.
Additional type that have virtual method override.
Type that does not have override and should use hook.
And type that does not have override and should use hook.
public class basex
{
virtual public void showmewhatyougot()
{
Console.WriteLine ("this is base method");
}
}

public class havemyown : basex
{
virtual public void showmewhatyougot()
{
Console.WriteLine ("i have my own implementation of method");
}
}

//out task to hook method only for this class
//base class and donthave_and_dont_allow_hook should call original method
public class donthave_allow_hook : basex
{
virtual public void showmewhatyougot1()
{
Console.WriteLine ("this will not call");
}
}

public class donthave_and_dont_allow_hook : basex
{
virtual public void showmewhatyougot1()
{
Console.WriteLine ("this will not call");
}
}


replacement method is

static public void MAGIC(basex thisx)
{
if (thisx is donthave_and_dont_allow_hook)
{
//code of base method is copypasted here
Console.WriteLine ("this is base method from hook");
return;
}
if (thisx.GetType() == typeof(basex))
{
//code from base method is copypasted here second time
//for reason described below
Console.WriteLine ("this is base method from hook");
return;
}
//replacement code
Console.WriteLine ("hooked method that does not exists WOA!");
}


Only thing is actually complicated, is filter for base class, issue is simple, every child class will pass "is basex" condition and basex class also will pass this condition, if you want to filter base class, you must perform exact type check, instanceof or "assignablefrom" will fail.

new basex ().showmewhatyougot ();
new donthave_allow_hook ().showmewhatyougot ();
new donthave_and_dont_allow_hook ().showmewhatyougot ();
new havemyown ().showmewhatyougot ();


result is
this is base method from hook
hooked method that does not exists WOA!
this is base method from hook
i have my own implementation of method


Similar tricks are possible by:
Injecting SAME code everywhere and calling MethodBase.GetCurrentMethod (), when method is passed by "jmp" instruction, it does not have it's own stackframe and will be detected by stackwalker as original method.

Injecting code, including inline cases and getting one stackframe above, to get information about, what method called us, acting based on that, invoking custom code of full copy of original.