Jump to content
Tuts 4 You

Change return of Assembly.GetCallingAssembly fails in .NET 7


CodeExplorer

Recommended Posts

Posted

Change return of Assembly.GetCallingAssembly fails in .NET 7
Having this code:
 

        public static Assembly PGetCallingAssembly()
        {
            return assembly;
        }

        public static void PathGetExecuting()
        {
            Assembly.GetCallingAssembly();
            Assembly.GetExecutingAssembly();
            PGetCallingAssembly();
            int lpNumberOfBytesWritten = 0;
            MethodInfo metGetExecutingAssembly = typeof(Assembly).GetMethod("GetExecutingAssembly", BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
            MethodInfo metGetCallingAssembly = typeof(Assembly).GetMethod("GetCallingAssembly", BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
            MethodInfo metPGetCallingAssembly = typeof(MainForm).GetMethod("PGetCallingAssembly", BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
            IntPtr AGetCalling = IntPtr.Zero;
            IntPtr functionPointer = IntPtr.Zero;
            IntPtr AGetExecuting = IntPtr.Zero;
            byte[] lpBuffer = new byte[] { 0xb8, 1, 2, 3, 4, 0xff, 0xe0 };
            if ((metGetCallingAssembly != null) && (metPGetCallingAssembly != null))
            {
                AGetCalling = metGetCallingAssembly.MethodHandle.GetFunctionPointer();
                functionPointer = metPGetCallingAssembly.MethodHandle.GetFunctionPointer();
                AGetExecuting = metGetExecutingAssembly.MethodHandle.GetFunctionPointer();

                if (((AGetCalling != IntPtr.Zero) && (functionPointer != IntPtr.Zero)) && (AGetExecuting != IntPtr.Zero))
                {

                    if (IntPtr.Size == 4)
                    {
                        byte[] buffer2 = BitConverter.GetBytes((uint)(int)functionPointer);
                        lpBuffer[1] = buffer2[0];
                        lpBuffer[2] = buffer2[1];
                        lpBuffer[3] = buffer2[2];
                        lpBuffer[4] = buffer2[3];
                    }
                    else if (IntPtr.Size == 8)
                    {
                        lpBuffer = new byte[] { 0x48, 0xb8, 1, 2, 3, 4, 5, 6, 7, 8, 0xff, 0xe0 };
                        byte[] buffer2 = BitConverter.GetBytes((ulong)(long)functionPointer);
                        lpBuffer[1 + 1] = buffer2[0];
                        lpBuffer[1 + 2] = buffer2[1];
                        lpBuffer[1 + 3] = buffer2[2];
                        lpBuffer[1 + 4] = buffer2[3];
                        lpBuffer[1 + 5] = buffer2[4];
                        lpBuffer[1 + 6] = buffer2[5];
                        lpBuffer[1 + 7] = buffer2[6];
                        lpBuffer[1 + 8] = buffer2[7];
                    }

                    int res_1 = WriteProcessMemory(-1, AGetExecuting, lpBuffer, lpBuffer.Length, ref lpNumberOfBytesWritten);

                    int res_2 = WriteProcessMemory(-1, AGetCalling, lpBuffer, lpBuffer.Length, ref lpNumberOfBytesWritten);


                    Assembly asm1 = Assembly.GetCallingAssembly();
                    Assembly asm2 = Assembly.GetExecutingAssembly();

                }
            }

        }

 

 

Assembly asm1 = Assembly.GetCallingAssembly(); still return original value;
any explanation why this happens?
Any alternatives to this code, instead of using Harmony:
https://research.checkpoint.com/2024/net-hooking-harmonizing-managed-territory/

 

Posted (edited)

.net7 is dead

switch to .net8/9 or 10

 

Edited by jackyjask
  • Like 1
Posted (edited)

another points of concerns:

1) this is .net (IL bytecode) system, why do you treat it as a native one?

eg:

lpBuffer = new byte[] { 0xb8, 1, 2, 3, 4, 0xff, 0xe0 };   -->  mov eax, 0x04030201 jmp eax

at least you are damaging register EAX of the CPU (what if it was using by .net engine?

2) next, how do you know that address is having native code and not .net IL bytes?

3) also, even if you are sure 100% that address is having native code, you are using brutal WriteProcessMemory WINAPI wihtout setting appropriate execution bits on memory page

too many questions...

Edited by jackyjask
  • Like 1
Posted
1 hour ago, jackyjask said:

1) this is .net (IL bytecode) system, why do you treat it as a native one?

Everything get compiled to native code in the end.
I don't know why on .NET 7/8 MethodHandle.GetFunctionPointer() doesn't return the native compiled address,
I've just used Harmony lib in the end.
 

  • Like 1
Posted
30 minutes ago, CodeExplorer said:

Everything get compiled to native code in the end.

even if yes, you are vandalically damaging CPU registers

  • Like 1
Posted
1 hour ago, jackyjask said:

even if yes, you are vandalically damaging CPU registers

That is not the problem, eax registers is changed anyway for returning the value;
and it is not used by runtime in other ways.
Patched address is not called at all.

I found this article:
.NET Inside Out Part 23 – Machine code address of any .NET Core method
https://blog.adamfurmanek.pl/2020/08/22/net-inside-out-part-23/index.html

 

  • Like 1
Posted

the article says about 

ReadyToRun 

are you doing this?

 

the article was written back in 2020

 

.NET7/8/9 was released later

 

  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...