Getting the pointer of a function...

Posts 113 of 13 · Page 1 of 1
Getting the pointer of a function...
So, i have a class:
Code:
class ByPass
    {
        public delegate uint GetPointer(int Index);
        public static unsafe void CreateBypass(uint CShell)
        {
            Console.WriteLine("Bypass Experimenting");
            Type BypassType = Type.GetType("ByPass");
            MethodInfo ReturnPointer = BypassType.GetMethod("Bypass");


            //Console.WriteLine("Function Pointer: " + Storage.DecToHex(ReturnPointer.MethodHandle.GetFunctionPointer().ToInt32()));


            //var func = (GetPointer)Marshal.GetDelegateForFunctionPointer((IntPtr)Bypass, typeof(GetPointer));
            Console.WriteLine("Done");
        }


        public static uint Bypass(int GunIndex)
        {
            return 0;
        }
    }
So, this is in a Dll project, which got injected into a game....
But every time, i run the function, the Thread stop for a few second, and then the game just exit...
What is the problem with it ?

I need the Pointer to that function (in IntPtr) because:
-A command will be overwritten (byte patch) inside the game, to call that function...
-I don't know, if the parameter list will work or not, maybe someone can help me with that...
Sounds like an exception is being thrown then. Perhaps your code is failing to find the type or the method.
Wrap the coded in a try/catch and print out the exception to see if that is the cause.
My guess is
Code:
Type BypassType = Type.GetType("ByPass");
Include the namespace and class name.
Like
Code:
Type BypassType = Type.GetType("ByPass.Class1");
Or whatever the class name is.
Add some error handling aswell
Quote Originally Posted by Pingo View Post
My guess is
Code:
Type BypassType = Type.GetType("ByPass");
Include the namespace and class name.
Like
Code:
Type BypassType = Type.GetType("ByPass.Class1");
Or whatever the class name is.
Add some error handling aswell
Adding NameSpace solved the problem, don't need the error handling...
Second error:
i try to call it from a delegate (to test, if the pointer is right)
The function is baig called properly, but the parameter is invalid...

Code:
public delegate uint GetPointer(int GunIndex);
public static unsafe void CreateBypass(uint CShell)
        {
            Console.WriteLine("Bypass Experimenting");
            Type BypassType = Type.GetType("RabirDimensionalBeast.ByPass");
            MethodInfo ReturnPointer = BypassType.GetMethod("Bypass");




            Console.WriteLine("Function Pointer: 0x" + Storage.DecToHex(ReturnPointer.MethodHandle.GetFunctionPointer().ToInt32()));
            uint FunctionPointer = (uint)ReturnPointer.MethodHandle.GetFunctionPointer().ToInt32();


            var func = (GetPointer)Marshal.GetDelegateForFunctionPointer((IntPtr)FunctionPointer, typeof(GetPointer));
            func(4);
            Console.WriteLine("Done");
        }




        public static uint Bypass(int GunIndex)
        {
            Console.WriteLine("Access: " + GunIndex.ToString());
            return 0;
        }


Console output:
Code:
Done
Access: 0
Function Pointer: 0x2AC440
Bypass Experimenting


But i call it with "4" -_-...
Just a stab in the dark but try this.
Code:
        IntPtr Func(string FunctionName, object[] Parameters)
        {
            Type BypassType;
            MethodInfo ReturnPointer;

            foreach (Type T in Assembly.GetExecutingAssembly().GetTypes())
            {
                BypassType = T;
                if ((ReturnPointer = BypassType.GetMethod(FunctionName)) != null)
                {
                    ReturnPointer.Invoke(Activator.CreateInstance(BypassType), Parameters);
                    return ReturnPointer.MethodHandle.GetFunctionPointer();
                }
            }
            return IntPtr.Zero;
        }

        public static uint Bypass(int GunIndex)
        {
            Console.WriteLine("Access: " + GunIndex.ToString());
            return 0;
        }
Call it like
Code:
IntPtr FunctionPointer = Func("Bypass", new object[] { 4 });
Your console should output Access: 4
Quote Originally Posted by Pingo View Post
Just a stab in the dark but try this.
Code:
        IntPtr Func(string FunctionName, object[] Parameters)
        {
            Type BypassType;
            MethodInfo ReturnPointer;

            foreach (Type T in Assembly.GetExecutingAssembly().GetTypes())
            {
                BypassType = T;
                if ((ReturnPointer = BypassType.GetMethod(FunctionName)) != null)
                {
                    ReturnPointer.Invoke(Activator.CreateInstance(BypassType), Parameters);
                    return ReturnPointer.MethodHandle.GetFunctionPointer();
                }
            }
            return IntPtr.Zero;
        }

        public static uint Bypass(int GunIndex)
        {
            Console.WriteLine("Access: " + GunIndex.ToString());
            return 0;
        }
Call it like
Code:
IntPtr FunctionPointer = Func("Bypass", new object[] { 4 });
Your console should output Access: 4
Will try, thanks...


---------- Post added at 05:48 PM ---------- Previous post was at 05:46 PM ----------

Quote Originally Posted by atom0s View Post
Some things to note about your code:
- Why are you marking the function 'CreateBypass', unsafe when it isn't using unsafe code?

Code:
            uint FunctionPointer = (uint)ReturnPointer.MethodHandle.GetFunctionPointer().ToInt32();


            var func = (GetPointer)Marshal.GetDelegateForFunctionPointer((IntPtr)FunctionPointer, typeof(GetPointer));
Can just be written as:
Code:
var func = (GetPointer)Marshal.GetDelegateForFunctionPointer(ReturnPointer.MethodHandle.GetFunctionPointer(), typeof(GetPointer));
(GetFunctionPointer returns an IntPtr, no point to cast it to a uint first.)

As for the bad argument, perhaps its an issue with the calling convention or a missing argument in the call. You said that you are hooking/altering a game function to use your call or something in the above posts so without seeing all the code not much to be said. (Since this does look like you are not showing everything.)
1; It marked as Unsafe because it used to use unsafe content in some of its previous versions...
2; It must be converted to uint because IntPtr can be 8 byte length but it must be 4 byte length because:
2.1; The pointer will be injected to a process (to overwrite the official pointer for the function) to call my own function...

Also the process is Native, i'm not sure, if it will work with my Managed function, or not :/


Edit:
@
Pingo

So... It gives back a pointer, and it is the real pointer of the function...
But since, it will be used to call from a process (not the owner, its a Dll) it must be working when called via the Pointer...
You know the:
Code:
IntPtr FunctionPointer = Func("Bypass", new object[] { 4 }); //Output 4: Working...
            Console.WriteLine("ByPass Pointer: 0x"+Storage.DecToHex((int)FunctionPointer));


            Console.WriteLine("Call With Pointer: ");
            var func = (GetPointer)Marshal.GetDelegateForFunctionPointer(FunctionPointer, typeof(GetPointer)); //Output: 0; Function be called, parameter error...
            func(4);


The output is still "0" when i call it with the Pointer and delegate...

I think you figured out that it is the 28_3 bypass for crossfire...
So you know, it will be called with the Pointer, but i lost all my ideas, whats wrong with the parameter...

Also when i overwritten the old function, with this, Cf just shut down without error...
Some things to note about your code:
- Why are you marking the function 'CreateBypass', unsafe when it isn't using unsafe code?

Code:
            uint FunctionPointer = (uint)ReturnPointer.MethodHandle.GetFunctionPointer().ToInt32();


            var func = (GetPointer)Marshal.GetDelegateForFunctionPointer((IntPtr)FunctionPointer, typeof(GetPointer));
Can just be written as:
Code:
var func = (GetPointer)Marshal.GetDelegateForFunctionPointer(ReturnPointer.MethodHandle.GetFunctionPointer(), typeof(GetPointer));
(GetFunctionPointer returns an IntPtr, no point to cast it to a uint first.)

As for the bad argument, perhaps its an issue with the calling convention or a missing argument in the call. You said that you are hooking/altering a game function to use your call or something in the above posts so without seeing all the code not much to be said. (Since this does look like you are not showing everything.)
IntPtr wont be bigger than 4 bytes as long as you are compiling specifically for x86.

Compiled as AnyCPU:
IntPtr.Size = 0x00000008

Compiled as x86 specifically:
IntPtr.Size = 0x00000004


As for your function issue, the methods you are calling are static so they don't expect to be invoked as an instance.
Once you have the method info you can just directly invoke the static function:

Code:
namespace ConsoleApplication1
{
    using System;

    class Program
    {
        public delegate uint GetPointer(int nIndex);

        public static void CreateBypass(uint uiShell)
        {
            Console.WriteLine("== Bypass Start ==");

            var baseType = Type.GetType("ConsoleApplication1.Program");
            if (baseType != null)
            {
                var methodInfo = baseType.GetMethod("Bypass");
                if (methodInfo != null)
                {
                    methodInfo.Invoke(null, new object[] { 0x04 });
                }
            }

            Console.WriteLine("== Bypass Finish ==");
        }

        public static uint Bypass(int nIndex)
        {
            Console.WriteLine("[Bypass] Index was: {0}", nIndex);
            return 0;
        }

        static void Main(string[] args)
        {
            CreateBypass(4);
        }
    }
}
== Bypass Start ==
[Bypass] Index was: 4
== Bypass Finish ==

If you absolutely need to use the marshaled pointer you need to change the calling convention of your GetPointer delegate then, like I mentioned before.
Quote Originally Posted by atom0s View Post
IntPtr wont be bigger than 4 bytes as long as you are compiling specifically for x86.

Compiled as AnyCPU:
IntPtr.Size = 0x00000008

Compiled as x86 specifically:
IntPtr.Size = 0x00000004


As for your function issue, the methods you are calling are static so they don't expect to be invoked as an instance.
Once you have the method info you can just directly invoke the static function:

Code:
namespace ConsoleApplication1
{
    using System;

    class Program
    {
        public delegate uint GetPointer(int nIndex);

        public static void CreateBypass(uint uiShell)
        {
            Console.WriteLine("== Bypass Start ==");

            var baseType = Type.GetType("ConsoleApplication1.Program");
            if (baseType != null)
            {
                var methodInfo = baseType.GetMethod("Bypass");
                if (methodInfo != null)
                {
                    methodInfo.Invoke(null, new object[] { 0x04 });
                }
            }

            Console.WriteLine("== Bypass Finish ==");
        }

        public static uint Bypass(int nIndex)
        {
            Console.WriteLine("[Bypass] Index was: {0}", nIndex);
            return 0;
        }

        static void Main(string[] args)
        {
            CreateBypass(4);
        }
    }
}
== Bypass Start ==
[Bypass] Index was: 4
== Bypass Finish ==

If you absolutely need to use the marshaled pointer you need to change the calling convention of your GetPointer delegate then, like I mentioned before.
Actually, not i will call this function...
Let me explain:

Here is a process:
"crossfire.exe"
And it have a function: (actually not a real function, but just created at compile, i think)
Code:
DWORD GetPointerForWeapon(int WeaponIndex)
{
     return &WeaponArray[WeaponIndex];
}
And i have my own (made in C#)
Code:
byte[][] FakeWeaponArray = new byte[999][];

uint GetPointerForFakeWeapon(int WeaponIndex)
{
      fixed (byte* Ptr = FakeWeaponArray[WeaponIndex]
      return (uint)Ptr;
}
so the original being called like (in the process)
Code:
call CShell.dll + 0x99A45;
0x99A45 = Original....
0xAAAD5 = My own (C#) function...
And i'd like to change to: (this is the easy part, but the process can't really call it)
Code:
call CShell.dll + 0xAAAD5;
I think this will help you to understand...
Alright, so assuming that:
Code:
DWORD GetPointerForWeapon(int WeaponIndex)
{
     return &WeaponArray[WeaponIndex];
}
Is using 4 byte indexing, you can do the same in C# without needing fixed doing this:
Code:
uint GetPointerForWeapon(int WeaponIndex)
{
    return (uint)Marshal.ReadInt32(WeaponArrayPtr, (WeaponIndex * 4));
}
A common method to invoke a C# method inside a native process is to use the push/retn method. Such as:
push <addr_to_func_delegate>
retn

Which would be (in bytes): 0x68 0x?? 0x?? 0x?? 0x?? 0xC3
(Replacing the 0x?? with the function address to your delegate.)
Quote Originally Posted by atom0s View Post
Alright, so assuming that:
Code:
DWORD GetPointerForWeapon(int WeaponIndex)
{
     return &WeaponArray[WeaponIndex];
}
Is using 4 byte indexing, you can do the same in C# without needing fixed doing this:
Code:
uint GetPointerForWeapon(int WeaponIndex)
{
    return (uint)Marshal.ReadInt32(WeaponArrayPtr, (WeaponIndex * 4));
}
A common method to invoke a C# method inside a native process is to use the push/retn method. Such as:
push <addr_to_func_delegate>
retn

Which would be (in bytes): 0x68 0x?? 0x?? 0x?? 0x?? 0xC3
(Replacing the 0x?? with the function address to your delegate.)
So, i would call the
Code:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate uint GtePtrDelegate(int GunIndex);
Rather than the function ?
So i need Delegate pointer, rigth ?

So there is the Call function:
Code:
E8 860CE9FF           - call CShell.dll+226600  //This is the official code...
So i ned to get a pointer for the Delegate, and use that Pointer, not the function's right ?
You create a function pointer to the call using the delegate.

Here's a stripped down example of what I mean from a detour class I wrote for .NET:

Code:
    // Direct3DCreate9 delegate..
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
    delegate IntPtr delegate_Direct3DCreate9(ushort SDKVersion);

    // Creating delegate to my call..
    var lpFunctionDelegate = new delegate_Direct3DCreate9(Mine_Direct3DCreate9);
    
    // My new hooked callback..
    public IntPtr Mine_Direct3DCreate9(ushort SDKVersion)
    {
        Debug.Write("[Mine_Direct3DCreate9] Hooked Direct3DCreate9 called.");

        // Call the original function here..
        // Handle return as needed here..
    }
    
    // When writing the push and retn use the function pointer to our delegate..
    this.m_vPatchedBytes.Add(0x68);
    this.m_vPatchedBytes.AddRange(BitConverter.GetBytes(Marshal.GetFunctionPointerForDelegate(lpFunctionDelegate).ToInt32()));
    this.m_vPatchedBytes.Add(0xC3);
Quote Originally Posted by atom0s View Post
You create a function pointer to the call using the delegate.

Here's a stripped down example of what I mean from a detour class I wrote for .NET:

Code:
    // Direct3DCreate9 delegate..
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Auto, SetLastError = true)]
    delegate IntPtr delegate_Direct3DCreate9(ushort SDKVersion);

    // Creating delegate to my call..
    var lpFunctionDelegate = new delegate_Direct3DCreate9(Mine_Direct3DCreate9);
    
    // My new hooked callback..
    public IntPtr Mine_Direct3DCreate9(ushort SDKVersion)
    {
        Debug.Write("[Mine_Direct3DCreate9] Hooked Direct3DCreate9 called.");

        // Call the original function here..
        // Handle return as needed here..
    }
    
    // When writing the push and retn use the function pointer to our delegate..
    this.m_vPatchedBytes.Add(0x68);
    this.m_vPatchedBytes.AddRange(BitConverter.GetBytes(Marshal.GetFunctionPointerForDelegate(lpFunctionDelegate).ToInt32()));
    this.m_vPatchedBytes.Add(0xC3);

Hmm, i will look into it... I hope it will work...
But i need 6 free byte, and i only have 5... I'll have to find out something...

Here is the code what i wanna overwrite:
Code:
8B 44 24 04           - mov eax,[esp+04]
81 EC A0000000        - sub esp,000000A0
83 F8 FF              - cmp eax,FF
0F84 F7010000         - je CShell.dll+395B6A
56                    - push esi
50                    - push eax
E8 860CE9FF           - call CShell.dll+226600  //****************** This one, 5 bytes, i need 6 for the push + retn...
8B F0                 - mov esi,eax
83 C4 04              - add esp,04
85 F6                 - test esi,esi
0F84 E2010000         - je CShell.dll+395B69
Posts 113 of 13 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Need help?