Unmanaged function call in struct from VTable

Is it possible to call functions from C # into an unmanaged function in a structure (via VTable).

For example, I connect an application to a process, and I re-create structures for each class (application).

public struct SomeStruct { [FieldOffset(0x00)] public IntPtr * VTable; [FieldOffset(0x10)] public uint SomeValue; } 

Then I usually do:

 var * data = (SomeStruct*)(Address); 

And I want to call a function from a VTable structure in one of the following ways:

 Invoke<delegate>(data->VTable[0x3C])(delegateArguments) 

or

 var eax = Invoke<Func<uint,uint>(data->VTable[0x3C])(arg1,arg2) 

Also, can this be done efficiently (since these vtable functions could be called many times)?

Perhaps through Reflection Emit?

From what I know, marshalling should create a delegate function every time I call Invoke<> func.

+4
source share
2 answers

Given that the virtual method table contains pointers to functions, assuming that you know the offset (which it seems you are doing), you can get the value of the pointer in IntPtr by calling the ReadIntPtr method in the Marshall class , for example:

 IntPtr ptr = Marshal.ReadIntPtr(data.VTable, 0x3C); 

Then you can call the GetDelegateForFunctionPointer method on the Marshal class to get a delegate of the appropriate type, for example:

 // Assuming a signature of f(int, int) returning int Func<int, int, int> func = (Func<int, int, int>) Marshal.GetDelegateForFunctionPointer(ptr, typeof(Func<int, int, int>)); 

You can then call the delegate as needed.

+2
source

Well, I found a possible solution:

I created a generic Invoke method that creates and caches all delegates for future use. Also

  public void Select(uint target) { fixed (void* pThis = &this) { Generic.Invoke<Action<uint, uint>>(this.VTable[0xC0], CallingConvention.ThisCall) ((uint)pThis, target); } } [FieldOffset(0x00)] public uint* VTable; 

Caches:

  public static T Invoke<T>(uint addr, CallingConvention conv) where T : class { var type = typeof(T); if (!cache.Contains(type)) cache.Set<T>(type, NativeHelper.GetDelegateForFunctionPointer<T>(addr, conv)); return cache.Get<T>(type); } 

And the function that creates the function (and works for general Func / Action)

 public static T GetDelegateForFunctionPointer<T>(uint ptr, CallingConvention conv) where T : class { var delegateType = typeof(T); var method = delegateType.GetMethod("Invoke"); var returnType = method.ReturnType; var paramTypes = method .GetParameters() .Select((x) => x.ParameterType) .ToArray(); var invoke = new DynamicMethod("Invoke", returnType, paramTypes, typeof(Delegate)); var il = invoke.GetILGenerator(); for (int i = 0; i < paramTypes.Length; i++) il.Emit(OpCodes.Ldarg, i); il.Emit(OpCodes.Ldc_I4, ptr); il.EmitCalli(OpCodes.Calli, conv, returnType, paramTypes); il.Emit(OpCodes.Ret); return invoke.CreateDelegate(delegateType) as T; } 
+1
source

Source: https://habr.com/ru/post/1434262/


All Articles