using System; using Mono.Cecil; using Mono.Cecil.Cil; class P { static int Main(string[] a) { string src = a[0], dst = a[1]; var m = ModuleDefinition.ReadModule(src); var tsAppDomain = new TypeReference("System", "AppDomain", m, m.TypeSystem.CoreLibrary, false); var getCurrentDomain = new MethodReference("get_CurrentDomain", tsAppDomain, tsAppDomain){ HasThis = false }; var getBaseDir = new MethodReference("get_BaseDirectory", m.TypeSystem.String, tsAppDomain){ HasThis = true }; var mGetCurrent = m.ImportReference(getCurrentDomain); var mGetBase = m.ImportReference(getBaseDir); int patched = 0; foreach (var t in m.GetTypes()) foreach (var meth in t.Methods) { if (!meth.HasBody) continue; var il = meth.Body.Instructions; for (int i = 1; i < il.Count; i++) { var ins = il[i]; if (ins.OpCode == OpCodes.Call && ins.Operand is MethodReference mr && mr.Name == "initialize" && mr.DeclaringType.Name == "Entry" && mr.Parameters.Count == 2 && il[i-1].OpCode == OpCodes.Ldnull) { // assumes the ldnull is not a branch or handler target; Replace // does not retarget operands pointing at the removed instruction var proc = meth.Body.GetILProcessor(); var ldnull = il[i-1]; var call1 = proc.Create(OpCodes.Call, mGetCurrent); var call2 = proc.Create(OpCodes.Callvirt, mGetBase); proc.Replace(ldnull, call1); proc.InsertAfter(call1, call2); patched++; Console.WriteLine($"Patched {t.FullName}.{meth.Name}: ldnull -> AppDomain.CurrentDomain.BaseDirectory"); } } } if (patched == 0) { Console.WriteLine("No patch site found"); return 2; } m.Write(dst); Console.WriteLine($"Wrote {dst}, patched={patched}"); return 0; } }