As a side-project for learning more about c#'s native side, i wanted to hook a virtual method in a virtual method table.
I successfully can call the function, but changing the pointer to the virtual method to my own method crashs when the function is called.
I made a small c++ application for this learning purpose and here is it
#include <iostream>
#include <conio.h>
using namespace std;
class Class
{
public:
virtual void Function ( ) = 0;
virtual void Function2 ( ) = 0;
virtual void Function3 ( ) = 0;
};
class ClassI : Class
{
public:
void Function ( )
{
cout << "Function1" << endl;
}
void Function2 ( )
{
cout << "Function2" << endl;
}
void Function3 ( )
{
cout << "Function3" << endl;
}
};
int main ( )
{
ClassI* a = new ClassI ( );
int aaaa = 10;
int* aaa = &aaaa;
cout << "AddressOfClass: " << &a << endl;
getch ( );
a->Function ( );
getch ( );
delete a;
return 0;
}
I get a instance of the Class pointer and output it and wait for input.
After input i run the function i want to hook.
Now in my c# side, i created a dll and the dll is in the process'es memory space through clr injection.
I verified the injection works with a bunch of ways.
public class EntryPoint
{
#region Delegates
private delegate void orgFunction();
private static orgFunction oFunction;
#endregion
public static void Hooked()
{
Console.WriteLine("HookedFunction");
oFunction();
}
[DllExport("DllMain",CallingConvention.Cdecl)]
public static void DllMain()
{
unsafe
{
Delegate Hook = new Action(Hooked);
IntPtr* vtable = (IntPtr*)*(IntPtr*)0x00F3FE10;
oFunction = Marshal.GetDelegateForFunctionPointer<orgFunction>(*(IntPtr*)vtable[0]);
uint OldProtection;
MUtil.MEMORY_BASIC_INFORMATION mbi;
MUtil.VirtualQuery((IntPtr)vtable, out mbi, (IntPtr)sizeof(MUtil.MEMORY_BASIC_INFORMATION));
MUtil.VirtualProtect(mbi.BaseAddress, (uint)mbi.RegionSize, 0x04, out OldProtection);
vtable[0] = Marshal.GetFunctionPointerForDelegate(Hook);
MUtil.VirtualProtect(mbi.BaseAddress, (uint)mbi.RegionSize, OldProtection, out OldProtection);
}
}
}
That is what i am doing at the c# side.
after getting the oFunction, for test i did call it and removed the other code and it worked.
but hooking it everything is fine but when in the c++ program i send a input and it runs the function we hooked, the app crashes.
I also update the address each time i run the c++ program so ye.
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION
{
public IntPtr BaseAddress;
public IntPtr AllocationBase;
public uint AllocationProtect;
public IntPtr RegionSize;
public uint State;
public uint Protect;
public uint Type;
}
[DllImport("kernel32.dll")]
public static extern UIntPtr VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, IntPtr dwLength);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool VirtualProtect(IntPtr address, uint size, uint newProtect, out uint oldProtect);
Edit:
I decided to make a simple little test, i changed oFunction to vmtable[2]
oFunction = Marshal.GetDelegateForFunctionPointer<orgFunction>(*(IntPtr*) vtable[1] );
That code above crashed me and i was quite surpired, this brings me the idea that getting the address of ClassI instance might give as the address of the first function instead of the vmtable which i don't think is the case.
-
Thanks for reading this, have a good day/night.
Best regards.