CodeExplorer Posted July 26 Posted July 26 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 July 26 Posted July 26 (edited) .net7 is dead switch to .net8/9 or 10 Edited July 26 by jackyjask 1
jackyjask Posted July 26 Posted July 26 (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 July 26 by jackyjask 1
CodeExplorer Posted July 26 Author Posted July 26 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 July 26 Posted July 26 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 July 26 Author Posted July 26 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 July 26 Posted July 26 the article says about ReadyToRun are you doing this? the article was written back in 2020 .NET7/8/9 was released later 1
CodeExplorer Posted yesterday at 11:21 AM Author Posted yesterday at 11:21 AM Harmony works on .NET 7 and 8. But doesn't work on .NET 9 as the BinaryFormatter was deprecated and just throws error. https://steven-giesel.com/blogPost/4271d529-5625-4b67-bd59-d121f2d8c8f6 https://github.com/pardeike/Harmony/releases I've tried to compile Harmony source code with VS 2022 Community, it gives lot of errors. I seen they are alternatives like MonoMod https://lethal.wiki/dev/fundamentals/patching-code/monomod-examples but they are only for .NET 5 so wasn't updated from a lot of time. 1
jackyjask Posted yesterday at 12:35 PM Posted yesterday at 12:35 PM is .net MONO still alive? after MS ported/opensourced .NET to Linux/Mac - not sure it was making sense to support it anymore... 1
jackyjask Posted yesterday at 12:52 PM Posted yesterday at 12:52 PM @CodeExplorer I'd suggest to open up an issue on harmony GH repo https://github.com/pardeike/Harmony/issues asking for support .net 10/11 1
Washi Posted yesterday at 01:19 PM Posted yesterday at 01:19 PM (edited) 49 minutes ago, jackyjask said: is .net MONO still alive? after MS ported/opensourced .NET to Linux/Mac - not sure it was making sense to support it anymore... Mono still makes sense for environments that cannot work with JIT and require an interpreter (e.g., wasm), and is still the default implementation for legacy .NET Framework in e.g., wine. Also, MonoMod is not affiliated with Mono, nor does it work "just" for Mono. Its name originates from Unity using Mono, but it is built to also work for other versions of .NET, including .NET Framework, .NET Core and .NET. Harmony under the hood also uses MonoMod. If you want to use MonoMod directly instead of Harmony, it should be doable using MonoMod.RuntimeDetour. Example from their docs: // Create a Hook. using (var d = new Hook(methodInfoFrom, methodInfoTo)) { // When the detour goes out-of-scope (and thus has Dispose() called), the detour is undone. // If the object is collected by the garbage collector, the detour is also undone. } Edited 23 hours ago by Washi 1 2
CodeExplorer Posted 5 minutes ago Author Posted 5 minutes ago already solved my problems: namespace HarmonyLib { /// <summary>Patch serialization</summary> /// internal static class PatchInfoSerialization internal static class PatchInfoSerialization { // Token: 0x1700000A RID: 10 // (get) Token: 0x06000166 RID: 358 RVA: 0x0000AF48 File Offset: 0x00009148 internal static bool UseBinaryFormatter { get { if (PatchInfoSerialization.useBinaryFormatter == null) { bool value; bool flag = AppContext.TryGetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", out value); if (flag) { PatchInfoSerialization.useBinaryFormatter = new bool?(value); } else { PatchInfoSerialization.useBinaryFormatter = new bool?(true); } } return PatchInfoSerialization.useBinaryFormatter.Value; /* 0x00009154 7F9F000004 */ IL_0000: ldsflda valuetype [System.Runtime]System.Nullable`1<bool> HarmonyLib.PatchInfoSerialization::useBinaryFormatter /* 0x00009159 28CB02000A */ IL_0005: call instance bool valuetype [System.Runtime]System.Nullable`1<bool>::get_HasValue() /* 0x0000915E 2D28 */ IL_000A: brtrue.s IL_0034 /* 0x00009160 7228120070 */ IL_000C: ldstr "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization" /* 0x00009165 1201 */ IL_0011: ldloca.s V_1 /* 0x00009167 28CC02000A */ IL_0013: call bool [System.Runtime] 7F9F00000428CB02000A 162A and 00 until at 2D System.Text.Encodings.Web.dll missing https://www.nuget.org/packages/System.Text.Encodings.Web/8.0.0 So I've just patch UseBinaryFormatter to return false. 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