C# Hooking a vmtable



作为一个侧面项目,用于了解有关C#的本地侧的更多信息,我想在虚拟方法表中连接虚拟方法。

我可以成功调用该函数,但是当调用该功能时,将指针更改为我自己的方法崩溃。

我为此目的提出了一个小的C 应用程序,这是

#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;
}

我得到了类指针的实例并输出并等待输入。

输入后,我运行了要连接的功能。

现在在我的c#方面,我创建了一个dll,而dll则通过CLR注入在过程中。

我以多种方式验证了注射。

 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);
            }
        }
    }

这就是我在C#方面所做的。

获得了任务后,为了进行测试,我确实称其为"并删除了其他代码"并起作用。

但是将其连接一切都很好,但是当在C 程序中,我发送输入并运行我们挂钩的功能,应用程序崩溃。

我每次运行C 程序时也更新地址。

        [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);


编辑:

我决定进行一个简单的小测试,我更改为vmtable [2]

oFunction = Marshal.GetDelegateForFunctionPointer<orgFunction>(*(IntPtr*) vtable[1]  );

上面的代码使我崩溃了,我非常兴奋,这使我想到的是,获取Classi实例的地址可能会作为第一个功能的地址而不是VMTable提供的,而不是我认为不是这样。<<<<<<<<<<<</p>


-

感谢您阅读此书,祝您有一个愉快的白天/夜晚。

最好的问候。

做一个VMTable挂钩,您要做的只是用新的函数覆盖vtable内部的功能指针,以便您只需使用virtualProtect()在必要时使用virtualprotect()在必要时获得写入权限,然后使用writeProcessMemory()覆盖它。

您需要手动逆转VTable并使用WriteProcessMemory()。

手动覆盖它。
  1. 获取VTable的地址
  2. 添加vtableIndex*4或vtableIndex*8(取决于x86 vs x64)
  3. 用writeProcessMemory
  4. 覆盖此地址

最新更新