private void ApplySettings() { // apply settings here TypeDef sType = injModule.Find("ClustertruckSplit.Settings", false); if (sType == null) { throw new NullReferenceException("Settings Type not Found"); } MethodDef settingsMeth = sType.FindStaticConstructor(); for (int i = 0; i < settingsMeth.Body.Instructions.Count; i++) { Instruction inst = settingsMeth.Body.Instructions[i]; if (inst.OpCode == OpCodes.Ldc_I4_S && ((SByte)inst.Operand) == 10) { // sleep time settingsMeth.Body.Instructions[i].Operand = (SByte)pSettings.SleepTime; } else if (inst.OpCode == OpCodes.Ldstr) { switch ((string)inst.Operand) { case "LEVEL": settingsMeth.Body.Instructions[i].Operand = pSettings.LevelModeEnabled.ToString(); break; case "PAUSE": settingsMeth.Body.Instructions[i].Operand = pSettings.PauseEnabled.ToString(); break; case "RESET": settingsMeth.Body.Instructions[i].Operand = pSettings.ResetEnabled.ToString(); break; case "LiveSplit": settingsMeth.Body.Instructions[i].Operand = pSettings.PipeName; break; } } } tmpPatchDll = Environment.CurrentDirectory + @"\Data\DEL_" + Guid.NewGuid().ToString() + ".dll"; if (!Directory.Exists(tmpPatchDll)) { Directory.CreateDirectory(Path.GetDirectoryName(tmpPatchDll)); } dnlib.DotNet.Writer.ModuleWriterOptions mr = new dnlib.DotNet.Writer.ModuleWriterOptions(injModule); mr.MetaDataOptions.Flags = dnlib.DotNet.Writer.MetaDataFlags.PreserveAll; injModule.Write(tmpPatchDll, mr); ReloadDll(tmpPatchDll); // dnlib pls why you no unload? }
protected override void Handle(NetfuserEvent ev) { switch (ev) { case NetfuserEvent.Complete ce: var ctx = (IContextImpl)ce.Context; var opt = new dnlib.DotNet.Writer.ModuleWriterOptions(ctx.TargetModule) { WritePdb = ctx.MainSourceModule.PdbState != null }; if (!_dest.Exists) { _dest.Create(); } var mainDestPath = Path.Combine(_dest.FullName, ctx.MainSourceModule.Name); ctx.TargetModule.Write(mainDestPath, opt); if (ctx.SourceModules.TryGetValue(ModuleTreat.Copy, out var toCopy)) { foreach (var mod in toCopy) { File.Copy(mod.Location, Path.Combine(_dest.FullName, mod.Name), true); } } var srcFolder = Path.GetDirectoryName(ctx.MainSourceModule.Location); var srcNameMinusExt = Path.GetFileNameWithoutExtension(ctx.MainSourceModule.Location); var srcPathMinusExt = Path.Combine(srcFolder, srcNameMinusExt); var dstPathMinusExt = Path.Combine(_dest.FullName, Path.GetFileNameWithoutExtension(ctx.MainSourceModule.Name)); foreach (var suffix in ConfigSuffixes) { var cfgPath = srcPathMinusExt + suffix; if (File.Exists(cfgPath)) { File.Copy(cfgPath, dstPathMinusExt + suffix, true); } } ctx.MainSourceModule.Assembly.TryGetOriginalTargetFrameworkAttribute(out var fw, out var ver, out _); if (fw == ".NETCoreApp" && ver.Major >= 3 && !ctx.MainSourceModule.Name.EndsWith(ExeSuffix)) { var launcher = srcPathMinusExt + ExeSuffix; if (File.Exists(launcher)) { File.Copy(launcher, dstPathMinusExt + ExeSuffix, true); } } break; } }
private string injectDeepTrace(List <string> MethodToken, string assemblyPath, string outputDirectory, bool WithTrace = false) { AssemblyDef asmDef; // New assembly path string fileName = Path.GetFileName(assemblyPath); // Append Date and Time to new filename string newPath = Path.Combine(outputDirectory, DateTime.UtcNow.ToString("yyyy-MM-dd HH.mm.ss.fff", CultureInfo.InvariantCulture) + "_" + fileName); // Check if Output directory already exists, if not, create one if (!Directory.Exists(outputDirectory)) { try { Directory.CreateDirectory(outputDirectory); } catch (Exception ex) { //MessageBox.Show(ex.ToString()); MainWindow.Instance.mBox("Injector Exception", ex.ToString()); } } try { // AssemblyResolver if (_AssmeblyResolver == null) { _AssmeblyResolver = new AssemblyResolver(); } if (Directory.Exists(Path.GetDirectoryName(assemblyPath))) { AddSearchPath(Path.GetDirectoryName(assemblyPath)); } // how to use AssemblyResolver with dnLib? //_AssmeblyResolver // Load assembly //asmDef = AssemblyDef.Load(assemblyPath); ModuleDefMD mod = ModuleDefMD.Load(assemblyPath); // import our pritObj Class Importer importer = new Importer(mod); Type PrintObjType = typeof(PrintObj); ITypeDefOrRef _printObjTypeRef = importer.Import(PrintObjType); // This creates a new namespace Logging and class PrintObj in the new assembly, we don't want that //TypeDef _printObj = new TypeDefUser("Logging", "PrintObj", mod.CorLibTypes.Object.TypeDefOrRef); //var _printObjCtor = _printObj.FindDefaultConstructor(); //mod.Types.Add(_printObj); Type t = typeof(System.Reflection.MethodBase); string methodname = "GetCurrentMethod"; IMethod _methodGetCurrentMethod = importer.Import(t.GetMethod(methodname)); methodname = "set_CurrentMethod"; IMethod _methodSetMethod = importer.Import(PrintObjType.GetMethod(methodname)); t = typeof(System.Reflection.Assembly); methodname = "GetExecutingAssembly"; IMethod _methodGetExecutingAssembly = importer.Import(t.GetMethod(methodname)); methodname = "set_CurrentAssembly"; IMethod _methodSetExecutingAssembly = importer.Import(PrintObjType.GetMethod(methodname)); methodname = "get_CurrentArguments"; IMethod _methodGetArguments = importer.Import(PrintObjType.GetMethod(methodname)); methodname = "set_CurrentArguments"; IMethod _methodSetArguments = importer.Import(PrintObjType.GetMethod(methodname)); methodname = "PrintArgs"; IMethod _methodPrintArgs = importer.Import(PrintObjType.GetMethod(methodname)); methodname = ".ctor"; IMethod _printObjCtor = importer.Import(PrintObjType.GetMethod(methodname)); foreach (ModuleDef modDef in mod.Assembly.Modules) { foreach (TypeDef typDef in modDef.Types) { foreach (MethodDef metDef in typDef.Methods) { //if (MethodToken.Contains(metDef.MDToken.ToString()) && metDef.Name == "About1_Closed") if (MethodToken.Contains(metDef.MDToken.ToString())) { if (WithTrace) { Trace.WriteLine("Found method " + metDef.ToString() + " Token: " + metDef.MDToken.ToString()); } try { string variablesInfo = string.Empty; if (metDef.Body != null && metDef.Body.Variables != null && metDef.Body.Variables.Count > 0) { foreach (var variable in metDef.Body.Variables) { string varInfo = " Variable - Type: " + variable.Type.ToString() + " Name: " + variable.Name + NewLine; varInfo += " Index: " + variable.Index.ToString(); if (WithTrace) { Trace.WriteLine(varInfo); } variablesInfo += varInfo; } } /* * if we want to skip anything * if (metDef.IsConstructor || * metDef.IsAbstract || * metDef.IsSetter || * (metDef.IsSpecialName && !metDef.IsGetter) || // to allow getter methods * metDef.IsInstanceConstructor || * metDef.IsManaged == false * ) * { * if (WithTrace) Trace.WriteLine("Skipped unsupported metDef " + metDef.Name); * } * else if (metDef != null && metDef.Body != null) */ if (metDef != null && metDef.Body != null) { var instructions = metDef.Body.Instructions; var newInstructions = new List <Instruction>(); Instruction firstExistingInstruction = metDef.Body.Instructions[0]; uint firstExistingInstrunctionOffset = firstExistingInstruction.Offset; int fIndex = (int)firstExistingInstrunctionOffset; // not working // nop Test //instructions.Insert((int)firstExistingInstruction.Offset, new Instruction(OpCodes.Nop)); //instructions.Insert((int)firstExistingInstruction.Offset, new Instruction(OpCodes.Nop)); /// /// Simple TraceLine /// // Load fully qualified method name as string //not working: (int)firstExistingInstruction.Offset //newInstructions.Add(new Instruction(OpCodes.Ldstr, metDef.ToString() + variablesInfo)); //newInstructions.Add(new Instruction(OpCodes.Call, metDef.Module.Import(typeof(Trace).GetMethod("WriteLine", new[] { typeof(string) })))); /// /// PrintObj (injected Logging.dll) /// extended by using code and comments from CInject /// https://codeinject.codeplex.com/ /// /* * 0 0000 nop * 1 0001 newobj instance void [Logging]Logging.PrintObj::.ctor() * 2 0006 stloc V_0 (0) * 3 000A ldloc V_0 (0) * 4 000E call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetCurrentMethod() * 5 0013 callvirt instance void [Logging]Logging.PrintObj::set_CurrentMethod(class [mscorlib]System.Reflection.MethodBase) * 6 0018 nop * 7 0019 ldloc.s V_0 (0) * 8 001B ldc.i4 2 * 9 0020 newarr [mscorlib]System.Object * 10 0025 stloc.s V_1 (1) * 11 0027 ldloc.s V_1 (1) * 12 0029 ldc.i4 0 * 13 002E ldarg sender (1) * 14 0032 box [mscorlib]System.Object * 15 0037 stelem.ref * 16 0038 ldloc.s V_1 (1) * 17 003A ldc.i4 1 * 18 003F ldarg e (2) * 19 0043 stelem.ref * 20 0044 ldloc.s V_1 (1) * 21 0046 callvirt instance void [Logging]Logging.PrintObj::set_CurrentArguments(object[]) * 22 004B ldloc.s V_0 (0) * 23 004D callvirt instance void [Logging]Logging.PrintObj::PrintArgs() * 24 0052 nop * */ // Add new variables metDef.Body.InitLocals = true; Local printO = new Local(_printObjTypeRef.ToTypeSig()); metDef.Body.Variables.Add(printO); var objType = mod.CorLibTypes.Object.ToTypeDefOrRef(); var objTypeArr = importer.Import(typeof(object[])); Local oArray = new Local(objTypeArr.ToTypeSig()); metDef.Body.Variables.Add(oArray); newInstructions.Add(new Instruction(OpCodes.Nop)); // using MemberRef cTor will create the logging.PrintObj: new Logging.PrintObj() var objectCtor = new MemberRefUser(mod, ".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void), _printObjTypeRef); newInstructions.Add(new Instruction(OpCodes.Newobj, objectCtor)); newInstructions.Add(OpCodes.Stloc.ToInstruction(printO)); newInstructions.Add(OpCodes.Ldloc.ToInstruction(printO)); newInstructions.Add(new Instruction(OpCodes.Call, _methodGetCurrentMethod)); newInstructions.Add(new Instruction(OpCodes.Callvirt, _methodSetMethod)); newInstructions.Add(new Instruction(OpCodes.Nop)); newInstructions.Add(new Instruction(OpCodes.Ldloc_S, printO)); // DNlib counts additionally hidden "this" List <Parameter> pList = new List <Parameter>(); for (int i = 0; i < metDef.Parameters.Count; i++) { if (!metDef.Parameters[i].IsHiddenThisParameter) { pList.Add(metDef.Parameters[i]); } } newInstructions.Add(new Instruction(OpCodes.Ldc_I4, pList.Count)); newInstructions.Add(new Instruction(OpCodes.Newarr, objType)); newInstructions.Add(new Instruction(OpCodes.Stloc_S, oArray)); //for (int i = 0; i < metDef.Parameters.Count; i++) for (int i = 0; i < pList.Count; i++) { if (WithTrace) { Trace.WriteLine("Found Parameter " + pList[i].Name.ToString()); } bool processAsNormal = true; //if (metDef.Parameters[i].Type.IsByRef) if (pList[i].Type.IsByRef) { if (WithTrace) { Trace.WriteLine("(IsByRef) " + pList[i].Name.ToString()); } //* Sample Instruction set: //* L_002a: ldloc.2 //* L_002b: ldc.i4.0 //* L_002c: ldarg.1 //* L_002d: ldind.ref //* L_002e: stelem.ref //* newInstructions.Add(new Instruction(OpCodes.Ldloc_S, oArray)); newInstructions.Add(new Instruction(OpCodes.Ldc_I4, i)); newInstructions.Add(new Instruction(OpCodes.Ldarg, pList[i])); newInstructions.Add(new Instruction(OpCodes.Ldind_Ref)); newInstructions.Add(new Instruction(OpCodes.Stelem_Ref)); processAsNormal = false; } //else if (pList[i].IsHiddenThisParameter) //{ //processAsNormal = false; //} else if (pList[i].Type.IsClassSig) { if (WithTrace) { Trace.WriteLine("(IsClassSig) " + pList[i].Name.ToString() + " Type: " + pList[i].Type + " Type.ReflectionFullName: " + pList[i].Type.ReflectionFullName); } newInstructions.Add(new Instruction(OpCodes.Ldloc_S, oArray)); newInstructions.Add(new Instruction(OpCodes.Ldc_I4, i)); newInstructions.Add(new Instruction(OpCodes.Ldarg, pList[i])); //newInstructions.Add(new Instruction(OpCodes.Box, pList[i].Type)); // causing System.InvalidCastException: Type "dnlib.DotNet.ClassSig" cannot be converted to Type "dnlib.DotNet.TypeSpec" ClassSig cSig = new ClassSig(pList[i].Type.ToTypeDefOrRef()); Trace.WriteLine("(IsClassSig) cSig: " + cSig.ToString()); newInstructions.Add(new Instruction(OpCodes.Stelem_Ref)); processAsNormal = false; } else if (pList[i].Type.IsCorLibType) { if (WithTrace) { Trace.WriteLine("(IsCorLibType) " + pList[i].Name.ToString() + " Type: " + pList[i].Type + " Type.ReflectionFullName: " + pList[i].Type.ReflectionFullName); } if (WithTrace) { Trace.WriteLine("(IsCorLibType...) " + " ElementType: " + pList[i].Type.ElementType + " Type.FullName: " + pList[i].Type.FullName); } if (WithTrace) { Trace.WriteLine("(IsCorLibType...) " + " Module: " + pList[i].Type.Module + " Type.Next: " + pList[i].Type.Next); } if (WithTrace) { Trace.WriteLine("(IsCorLibType...) " + " ReflectionName: " + pList[i].Type.ReflectionName + " Type.ReflectionNamespace: " + pList[i].Type.ReflectionNamespace); } newInstructions.Add(new Instruction(OpCodes.Ldloc_S, oArray)); newInstructions.Add(new Instruction(OpCodes.Ldc_I4, i)); newInstructions.Add(new Instruction(OpCodes.Ldarg, pList[i])); //newInstructions.Add(new Instruction(OpCodes.Box, pList[i].Type)); // causing System.InvalidCastException: Type "dnlib.DotNet.CorLibTypeSig" cannot be converted to Type "dnlib.DotNet.TypeSpec" //newInstructions.Add(new Instruction(OpCodes.Box, mod.CorLibTypes.Int32)); // working for Int32 as example CorLibTypeSig cLibTypeSig = new CorLibTypeSig(pList[i].Type.ToTypeDefOrRef(), pList[i].Type.ElementType); newInstructions.Add(OpCodes.Box.ToInstruction(cLibTypeSig)); newInstructions.Add(new Instruction(OpCodes.Stelem_Ref)); processAsNormal = false; } //else if (metDef.Parameters[i].ParameterType.IsArray) //{ //} //else if (metDef.Parameters[i].ParameterType.IsDefinition) // delegate needs no seperate handling //{ //} //else if (metDef.Parameters[i].Type.IsFunctionPointer) else if (pList[i].Type.IsFunctionPointer) { if (WithTrace) { Trace.WriteLine("(IsFunctionPointer) " + pList[i].Name.ToString()); } } //else if (metDef.Parameters[i].ParameterType.IsOptionalModifier) //{ //} //else if (metDef.Parameters[i].Type.IsPointer) else if (pList[i].Type.IsPointer) { if (WithTrace) { Trace.WriteLine("(IsPointer) " + pList[i].Name.ToString()); } } else { processAsNormal = true; } //if (processAsNormal && !metDef.Parameters[i].Type.IsClassSig && !metDef.Parameters[i].Type.IsCorLibType) if (processAsNormal) { if (WithTrace) { Trace.WriteLine("processAsNormal: " + pList[i].Name.ToString()); } // Sample Instruction set: for simple PARAMETER //* L_0036: ldloc.s objArray //* L_0038: ldc.i4 0 //* L_003d: ldarg array //* L_0041: box Int32 <-------------- anything can be here //* L_0046: stelem.ref // Sample Instruction set: for ARRAY // L_0036: ldloc.s objArray // L_0038: ldc.i4 0 // L_003d: ldarg array // L_0041: box string[] // L_0046: stelem.ref newInstructions.Add(new Instruction(OpCodes.Ldloc_S, oArray)); newInstructions.Add(new Instruction(OpCodes.Ldc_I4, i)); newInstructions.Add(new Instruction(OpCodes.Ldarg, metDef.Parameters[i])); newInstructions.Add(new Instruction(OpCodes.Box, pList[i].Type)); newInstructions.Add(new Instruction(OpCodes.Stelem_Ref)); } } // fill Arguments array newInstructions.Add(new Instruction(OpCodes.Ldloc_S, oArray)); newInstructions.Add(new Instruction(OpCodes.Callvirt, _methodSetArguments)); // call PrintArgs newInstructions.Add(new Instruction(OpCodes.Ldloc_S, printO)); newInstructions.Add(new Instruction(OpCodes.Callvirt, _methodPrintArgs)); // Finally add instructions to beginning for (int j = 0; j < newInstructions.Count; j++) { instructions.Insert(j, newInstructions[j]); } } else { if (WithTrace) { Trace.WriteLine("metDef or metDef.Body was null"); } } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); MainWindow.Instance.mBox("Injector Exception", ex.ToString()); } } } } } // Save modified assembly //asmDef.Write(newPath); var wopts = new dnlib.DotNet.Writer.ModuleWriterOptions(mod); wopts.WritePdb = true; //write assembly if (mod.IsILOnly) { mod.Write(newPath); } else { mod.NativeWrite(newPath); } } catch (Exception ex) { if (WithTrace) { Trace.WriteLine(DateTime.Now + " injectDeepTrace exception: " + ex.ToString()); } return(DateTime.Now + " injectDeepTrace exception: " + ex.ToString()); } InjectedFile = newPath; Text = "Injector finished: " + newPath; return(newPath); }