CodeExplorer Posted yesterday at 10:34 AM Posted yesterday at 10:34 AM 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/
jackyjask Posted yesterday at 10:38 AM Posted yesterday at 10:38 AM (edited) .net7 is dead switch to .net8/9 or 10 Edited yesterday at 10:39 AM by jackyjask 1
jackyjask Posted yesterday at 10:49 AM Posted yesterday at 10:49 AM (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 yesterday at 10:50 AM by jackyjask 1
CodeExplorer Posted yesterday at 12:39 PM Author Posted yesterday at 12:39 PM 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. 1
jackyjask Posted yesterday at 01:09 PM Posted yesterday at 01:09 PM 30 minutes ago, CodeExplorer said: Everything get compiled to native code in the end. even if yes, you are vandalically damaging CPU registers 1
CodeExplorer Posted yesterday at 02:28 PM Author Posted yesterday at 02:28 PM 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 1
jackyjask Posted yesterday at 02:50 PM Posted yesterday at 02:50 PM the article says about ReadyToRun are you doing this? the article was written back in 2020 .NET7/8/9 was released later 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now