IMethod ResolveMethod_Helper(ITypeDefOrRef declaringType, MethodData data) { TypeDef declaringDef = declaringType.ResolveTypeDefThrow(); MethodSig methodSig = GetMethodSig(data); // Has a GenericMVar if (data.HasGenericArguments) { MethodSig detectedSig = null; MethodDef method = FindMethodCheckBaseType(declaringType, data, out detectedSig); if (method == null || detectedSig == null) { throw new Exception(String.Format( "Unable to find generic method from the declaring/base types: DeclaringType={0}, MethodName={1}, MethodSig={2}", declaringType.ReflectionFullName, data.Name, methodSig)); } MethodSpec methodSpec = new MethodSpecUser(method, ToGenericInstMethodSig(data)); return(this.Importer.Import(methodSpec)); } else // No GenericMVars { MethodDef method = declaringDef.FindMethodCheckBaseType(data.Name, methodSig); if (method == null) { throw new Exception(String.Format( "Unable to find method from the declaring/base types: DeclaringType={0}, MethodName={1}, MethodSig={2}", declaringType.ReflectionFullName, data.Name, methodSig)); } return(this.Importer.Import(method)); } }
object ResolveOperand(object operand, GenericArguments genericArgs) { if (operand is MemberRef) { var memberRef = (MemberRef)operand; if (memberRef.IsFieldRef) { var field = ResolveField(memberRef.FieldSig, genericArgs); memberRef = new MemberRefUser(memberRef.Module, memberRef.Name, field, memberRef.Class); } else { var method = ResolveMethod(memberRef.MethodSig, genericArgs); memberRef = new MemberRefUser(memberRef.Module, memberRef.Name, method, memberRef.Class); } return(memberRef); } if (operand is TypeSpec) { var sig = ((TypeSpec)operand).TypeSig; return(genericArgs.ResolveType(sig).ToTypeDefOrRef()); } if (operand is MethodSpec) { var spec = (MethodSpec)operand; spec = new MethodSpecUser(spec.Method, ResolveInst(spec.GenericInstMethodSig, genericArgs)); return(spec); } return(operand); }
void UpdateReference(CEContext moduleCtx, TypeSig valueType, List <Tuple <MethodDef, Instruction> > references, int buffIndex, Func <DecoderDesc, byte> typeID) { foreach (var instr in references) { Tuple <MethodDef, DecoderDesc> decoder = moduleCtx.Decoders[moduleCtx.Random.NextInt32(moduleCtx.Decoders.Count)]; uint id = (uint)buffIndex | (uint)(typeID(decoder.Item2) << 30); id = moduleCtx.ModeHandler.Encode(decoder.Item2.Data, moduleCtx, id); var targetDecoder = new MethodSpecUser(decoder.Item1, new GenericInstMethodSig(valueType)); moduleCtx.ReferenceRepl.AddListEntry(instr.Item1, Tuple.Create(instr.Item2, id, (IMethod)targetDecoder)); } }
public override void ProcessOperand(TypeService service, MethodDef method, IList <Instruction> body, ref int index, MethodDef operand) { ScannedMethod tMethod = service.GetItem(operand.MDToken) as ScannedMethod; ScannedItem currentMethod = service.GetItem(method.MDToken) as ScannedMethod; if (tMethod != null) { var newspec = new MethodSpecUser(tMethod.TargetMethod, tMethod.CreateGenericMethodSig(currentMethod)); body[index].Operand = newspec; } }
internal override void ProcessOperand(TypeService service, MethodDef method, IList <Instruction> body, ref int index, MethodDef operand) { Debug.Assert(service != null, $"{nameof(service)} != null"); Debug.Assert(method != null, $"{nameof(method)} != null"); Debug.Assert(body != null, $"{nameof(body)} != null"); Debug.Assert(operand != null, $"{nameof(operand)} != null"); Debug.Assert(index >= 0, $"{nameof(index)} >= 0"); Debug.Assert(index < body.Count, $"{nameof(index)} < {nameof(body)}.Count"); var declType = service.GetItem(operand.DeclaringType); var targetMethod = service.GetItem(operand); if (declType?.IsScambled == true) { var methodD = new MemberRefUser(operand.Module, operand.Name, operand.MethodSig, declType.CreateGenericTypeSig(service.GetItem(method.DeclaringType)).ToTypeDefOrRef()); if (targetMethod?.IsScambled == true) { var newSpec = new MethodSpecUser(methodD, targetMethod.CreateGenericMethodSig(service.GetItem(method), service)); Debug.Assert(newSpec.GenericInstMethodSig.GenericArguments.Count == targetMethod.TargetMethod.GenericParameters.Count, $"{nameof(newSpec)}.GenericInstMethodSig.GenericArguments.Count == {nameof(targetMethod)}.TargetMethod.GenericParameters.Count"); body[index].Operand = newSpec; } else { body[index].Operand = methodD; } } else if (targetMethod?.IsScambled == true) { var newSpec = new MethodSpecUser(targetMethod.TargetMethod, targetMethod.CreateGenericMethodSig(service.GetItem(method), service)); Debug.Assert(newSpec.GenericInstMethodSig.GenericArguments.Count == targetMethod.TargetMethod.GenericParameters.Count, $"{nameof(newSpec)}.GenericInstMethodSig.GenericArguments.Count == {nameof(targetMethod)}.TargetMethod.GenericParameters.Count"); body[index].Operand = newSpec; } }
private void RerouteEntrypoint(ITypeService service, ConfuserContext context) { var originalEntry = context.CurrentModule.EntryPoint; if (originalEntry != null) { originalEntry.Name = "_start"; var param = originalEntry.Parameters.FirstOrDefault()?.Type; var newEntry = new MethodDefUser("Main", originalEntry.MethodSig, originalEntry.ImplAttributes, originalEntry.Attributes); IMethod callSig = originalEntry; var scannedEntry = service.GetScannedItem(originalEntry); if (scannedEntry != null) { callSig = new MethodSpecUser(originalEntry, new GenericInstMethodSig(scannedEntry.GenericCallTypes.ToArray())); } newEntry.Body = new dnlib.DotNet.Emit.CilBody(false, new Instruction[] { Instruction.Create(param == null ? OpCodes.Nop : OpCodes.Ldarg_0), Instruction.Create(OpCodes.Call, callSig), Instruction.Create(OpCodes.Ret), }, new ExceptionHandler[0], new LocalList()); originalEntry.DeclaringType.Methods.Add(newEntry); context.CurrentModule.EntryPoint = newEntry; ProtectionParameters.SetParameters(context, newEntry, ProtectionParameters.GetParameters(context, originalEntry)); service.RewriteMethodInstructions(newEntry); } }
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) { if (!parameters.Targets.Any()) { return; } context.CurrentModuleWriterOptions.WriterEvent += InsertVMBodies; // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop foreach (MethodDef method in parameters.Targets.WithProgress(context.Logger)) { if (!method.HasBody || method.DeclaringType.IsGlobalModuleType || method.Body.HasExceptionHandlers) { continue; } var module = method.Module; if (!Context.Bodies.ContainsKey(module)) { Context.Bodies.Add(module, new VMBody()); } var translated = Dispatcher.TranslateMethod(Context.Bodies[module], method); if (translated == null) { continue; } Context.Bodies[module].Translated.Add(method, translated); Context.Bodies[module].MethodToIndex.Add(method, Context.Bodies[module].Translated.Count - 1); context.CheckCancellation(); } foreach (var pair in Context.Bodies) { if (pair.Value.Translated.Count < 1) { continue; } var target = pair.Key.Import(Context.Entry); foreach (var translated in pair.Value.Translated.WithProgress(context.Logger)) { var method = translated.Key; method.Body = new CilBody { MaxStack = 1 }; var body = method.Body.Instructions; body.Add(OpCodes.Ldtoken.ToInstruction(method.DeclaringType)); body.Add(OpCodes.Ldc_I4.ToInstruction(pair.Value.MethodToIndex[method])); AddParameters(method); var genericType = method.ReturnType == method.Module.CorLibTypes.Void ? target.DeclaringType.ToTypeSig() : method.ReturnType; var sig = new MethodSpecUser((MemberRef)target, new GenericInstMethodSig(genericType)); body.Add(OpCodes.Call.ToInstruction(sig)); if (method.ReturnType == method.Module.CorLibTypes.Void) { body.Add(OpCodes.Pop.ToInstruction()); } body.Add(OpCodes.Ret.ToInstruction()); context.CheckCancellation(); } } Context.RuntimeModule.Dispose(); }
private MethodDef WriteDelegateProceeder(MethodDef innerMethod, string methodName, MethodParameters parametersList, ModuleDef module) { if (innerMethod == null) { return(null); } // currently, this is unsupported // (since I have no idea how it works) if (innerMethod.DeclaringType.HasGenericParameters || innerMethod.HasGenericParameters) { return(null); } var proceederMethodSignature = new MethodSig(CallingConvention.Default, 0, module.CorLibTypes.Object, new TypeSig[] { module.CorLibTypes.Object, new SZArraySig(module.CorLibTypes.Object) }); var proceederMethodAttributes = MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.HideBySig; var proceederMethod = new MethodDefUser(GetDelegateProceederName(methodName, innerMethod.DeclaringType), proceederMethodSignature, proceederMethodAttributes); proceederMethod.Body = new CilBody(); proceederMethod.GenericParameters.AddRange(innerMethod.GenericParameters.Select(p => p.Clone(innerMethod))); // object, object[] -> this, arguments var instructions = new Instructions(proceederMethod.Body.Instructions, module); var declaringType = innerMethod.DeclaringType.ToTypeSig(); if (innerMethod.DeclaringType.HasGenericParameters) { var genericTypeArgs = new List <TypeSig>(); for (int genericTypeParameterIndex = 0; genericTypeParameterIndex < innerMethod.DeclaringType.GenericParameters.Count; genericTypeParameterIndex++) { genericTypeArgs.Add(new GenericVar(genericTypeParameterIndex, innerMethod.DeclaringType)); } declaringType = new GenericInstSig((ClassOrValueTypeSig)innerMethod.DeclaringType.ToTypeSig(), genericTypeArgs); //instructions.Emit(OpCodes.Castclass, innerMethod.DeclaringType.ToTypeSig()); // arg.0 --> (target type) arg.0 } if (!innerMethod.IsStatic) { instructions.Emit(OpCodes.Ldarg_0); if (declaringType.IsValueType) { instructions.Emit(OpCodes.Unbox, declaringType); // arg.0 --> (target type) arg.0 } else { instructions.Emit(OpCodes.Castclass, declaringType); // arg.0 --> (target type) arg.0 } } //instructions.Emit(OpCodes.Ldnull); var localVariables = new Local[innerMethod.Parameters.Count]; for (int parameterIndex = 0; parameterIndex < parametersList.Count; parameterIndex++) { var parameter = parametersList[parameterIndex]; if (parameter.ParamDef == null) { parameter.CreateParamDef(); } var parameterType = parameter.Type; Local local = null; // the local type for references is the dereferenced type if (parameterType is ByRefSig) { parameterType = parameterType.Next; localVariables[parameterIndex] = local = new Local(parameterType); proceederMethod.Body.Variables.Add(local); } // on pure out values we don't care if (!parameter.ParamDef.IsOut) { instructions.Emit(OpCodes.Ldarg_1); // arguments[] instructions.EmitLdc(parameterIndex); // index instructions.Emit(OpCodes.Ldelem_Ref); // get array object instructions.EmitUnboxOrCastIfNecessary(parameterType); // when there is a local, use it (because we're going to pass the reference) if (local != null) { instructions.EmitStloc(local); } } // in all cases, if there is a local, it means we use it if (local != null) { instructions.Emit(OpCodes.Ldloca_S, local); } } if (proceederMethod.HasGenericParameters) { var genericArgs = new List <TypeSig>(); for (int genericParameterIndex = 0; genericParameterIndex < proceederMethod.GenericParameters.Count; genericParameterIndex++) { genericArgs.Add(new GenericMVar(genericParameterIndex, innerMethod)); } var genericInnerMethod = new MethodSpecUser(innerMethod, new GenericInstMethodSig(genericArgs)); instructions.Emit(OpCodes.Call, genericInnerMethod); } else { instructions.Emit(OpCodes.Call, innerMethod); } // collect ref/output parameters, if any for (int parameterIndex = 0; parameterIndex < innerMethod.Parameters.Count; parameterIndex++) { // when there is a local variable, it was either a ref or an out, so we need to box it again to array var localVariable = localVariables[parameterIndex]; if (localVariable == null) { continue; } instructions.Emit(OpCodes.Ldarg_1); // array[...] instructions.EmitLdc(parameterIndex); // index instructions.EmitLdloc(localVariable); // result instructions.EmitBoxIfNecessary(localVariable.Type); // box instructions.Emit(OpCodes.Stelem_Ref); // and store } if (!innerMethod.HasReturnType) { instructions.Emit(OpCodes.Ldnull); } else { instructions.EmitBoxIfNecessary(innerMethod.ReturnType); } instructions.Emit(OpCodes.Ret); innerMethod.DeclaringType.Methods.Add(proceederMethod); return(proceederMethod); }
private MosaType Load(TypeSig typeSig) { if (typeSig is LeafSig) { if (typeSig is TypeDefOrRefSig) { throw new AssemblyLoadException(); // Should have been loaded in MetadataLoader } else if (typeSig is GenericInstSig) { return(LoadGenericTypeInstanceSig((GenericInstSig)typeSig)); } else if (typeSig is GenericSig) { return(LoadGenericParam((GenericSig)typeSig)); } else if (typeSig is FnPtrSig) { var fnPtr = ((FnPtrSig)typeSig).MethodSig; var returnType = GetType(fnPtr.RetType); var pars = new List <MosaParameter>(); for (int i = 0; i < fnPtr.Params.Count; i++) { var parameter = metadata.Controller.CreateParameter(); using (var mosaParameter = metadata.Controller.MutateParameter(parameter)) { mosaParameter.Name = "A_" + i; mosaParameter.ParameterAttributes = MosaParameterAttributes.In; mosaParameter.ParameterType = GetType(fnPtr.Params[i]); } pars.Add(parameter); } return(metadata.TypeSystem.ToFnPtr(new MosaMethodSignature(returnType, pars))); } else { throw new NotSupportedException(); } } else // Non-leaf signature { var elementType = GetType(typeSig.Next); MosaType result; switch (typeSig.ElementType) { case ElementType.Ptr: result = elementType.ToUnmanagedPointer(); using (var ptrType = metadata.Controller.MutateType(result)) ptrType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig); break; case ElementType.ByRef: result = elementType.ToManagedPointer(); using (var ptrType = metadata.Controller.MutateType(result)) ptrType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig); break; case ElementType.CModReqd: case ElementType.CModOpt: result = metadata.Controller.CreateType(elementType); using (var modType = metadata.Controller.MutateType(result)) { modType.Modifier = GetType(((ModifierSig)typeSig).Modifier.ToTypeSig()); modType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig); modType.ElementType = elementType; } break; case ElementType.Pinned: result = elementType; // Pinned types are indicated in MosaLocal return(result); // Don't add again to controller case ElementType.SZArray: result = elementType.ToSZArray(); using (var arrayType = metadata.Controller.MutateType(result)) { arrayType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig); if (!typeSig.Next.HasOpenGenericParameter()) { var typeDesc = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >(); GetType(new GenericInstSig(szHelperEnumeratorSig, typeSig.Next)); GetType(new GenericInstSig(iListSig, typeSig.Next)); foreach (var method in szHelperMethods) { var methodSpec = new MethodSpecUser(method.Definition, new GenericInstMethodSig(typeDesc.Signature)); LoadGenericMethodInstance(methodSpec, new GenericArgumentResolver()); } } } if (!typeSig.Next.HasOpenGenericParameter()) { metadata.Resolver.EnqueueForArrayResolve(result); } return(result); case ElementType.Array: var array = (ArraySig)typeSig; var arrayInfo = new MosaArrayInfo(array.LowerBounds, array.Rank, array.Sizes); result = elementType.ToArray(arrayInfo); using (var arrayType = metadata.Controller.MutateType(result)) arrayType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig); break; default: throw new AssemblyLoadException(); } metadata.Controller.AddType(result); return(result); } }
internal static async Task <int> Execute(ModuleDefMD targetModule) { /* * {IL_0046: ldarg.0} * {IL_0047: ldarg.0} * {IL_0048: call UnityEngine.GameObject UnityEngine.Component::get_gameObject()} * {IL_004D: callvirt TrainerManager UnityEngine.GameObject::AddComponent<TrainerManager>()} * {IL_0052: stfld TrainerManager GameManager::trainerManager} * {IL_0057: ret} */ var gameManagerTypeDef = targetModule.Find("GameManager", true); var trainerManagerTypeDef = targetModule.Find("TrainerManager", true); var trainerManagerFieldDef = InjectionHelpers.AddField(targetModule, "GameManager", "trainerManager", trainerManagerTypeDef.ToTypeSig(), FieldAttributes.Private); if (trainerManagerFieldDef == null) { return(await Task.FromResult(1)); } var gameManagerStartMethodDef = gameManagerTypeDef.FindMethod("Start"); var unityEngine = targetModule.GetAssemblyRef(new UTF8String("UnityEngine")); var unityEngineComponentTypeRefUser = new TypeRefUser(targetModule, new UTF8String("UnityEngine"), new UTF8String("Component"), unityEngine); var unityEngineGameObjectTypeRefUser = new TypeRefUser(targetModule, new UTF8String("UnityEngine"), new UTF8String("GameObject"), unityEngine); var gameObjectTypeSig = unityEngineGameObjectTypeRefUser.ToTypeSig(); var getGameObjectMethodSig = MethodSig.CreateInstance(gameObjectTypeSig); var gameManagerStartMethodSig = MethodSig.CreateInstanceGeneric(1, new GenericMVar(0, gameManagerStartMethodDef)); // {UnityEngine.GameObject UnityEngine.Component::get_gameObject()} var getGameObjectMethodRefUser = new MemberRefUser(targetModule, new UTF8String("get_gameObject"), getGameObjectMethodSig, unityEngineComponentTypeRefUser); // {TrainerManager UnityEngine.GameObject::AddComponent<TrainerManager>()} var addComponentMethodRefUser = new MemberRefUser(targetModule, new UTF8String("AddComponent"), gameManagerStartMethodSig, unityEngineGameObjectTypeRefUser); var trainerManagerGenericInstMethodSig = new GenericInstMethodSig(trainerManagerTypeDef.ToTypeSig()); var addComponentMethodSpecUser = new MethodSpecUser(addComponentMethodRefUser, trainerManagerGenericInstMethodSig); var trainerManagerDefinitionMethodInstructions = new List <Instruction> { new Instruction(OpCodes.Ldarg_0), new Instruction(OpCodes.Ldarg_0), new Instruction(OpCodes.Call, getGameObjectMethodRefUser), new Instruction(OpCodes.Callvirt, addComponentMethodSpecUser), new Instruction(OpCodes.Stfld, trainerManagerFieldDef), new Instruction(OpCodes.Ret), }; var retInstruction = gameManagerStartMethodDef.Body.Instructions.LastOrDefault(); if (retInstruction != null && retInstruction.OpCode == OpCodes.Ret) { gameManagerStartMethodDef.Body.Instructions.Remove(retInstruction); } foreach (var instruction in trainerManagerDefinitionMethodInstructions) { gameManagerStartMethodDef.Body.Instructions.Add(instruction); } return(await Task.FromResult(0)); }
public static void Run() { // This is the file that will be created string newFileName = @"GenericExample2.exe"; // Create the module var mod = new ModuleDefUser("GenericExample2", Guid.NewGuid(), new AssemblyRefUser(new AssemblyNameInfo(typeof(int).Assembly.GetName().FullName))); // It's a console app mod.Kind = ModuleKind.Console; // Create the assembly and add the created module to it new AssemblyDefUser("GenericExample2", new Version(1, 2, 3, 4)).Modules.Add(mod); // Add the startup type. It derives from System.Object. TypeDef startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef); startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.AnsiClass; // Add the type to the module mod.Types.Add(startUpType); // Create the entry point method MethodDef entryPoint = new MethodDefUser("Main", MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String))); entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot; entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed; // Name the 1st argument (argument 0 is the return type) entryPoint.ParamDefs.Add(new ParamDefUser("args", 1)); // Add the method to the startup type startUpType.Methods.Add(entryPoint); // Set module entry point mod.EntryPoint = entryPoint; // Create System.Console type reference var systemConsole = mod.CorLibTypes.GetTypeRef("System", "Console"); // Create 'void System.Console.WriteLine(string,object)' method reference var writeLine2 = new MemberRefUser(mod, "WriteLine", MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String, mod.CorLibTypes.Object), systemConsole); var assemblyRef = mod.CorLibTypes.AssemblyRef; // Create 'System.Collections.ObjectModel.ReadOnlyCollection`1' type ref var roCollectionRef = new TypeRefUser(mod, "System.Collections.ObjectModel", "ReadOnlyCollection`1", assemblyRef); // Create 'ReadOnlyCollection<!!0>' signature for return type var roCollectionSig = new GenericInstSig(new ClassSig(roCollectionRef), new GenericMVar(0)); // Return type // Create 'ReadOnlyCollection<Int32>' type spec var roCollectionTypeSpec = new TypeSpecUser(new GenericInstSig(new ClassSig(roCollectionRef), mod.CorLibTypes.Int32)); // Create 'ReadOnlyCollection<Int32>.get_Count()' method reference var roCollectionGetCount = new MemberRefUser(mod, "get_Count", MethodSig.CreateInstance(mod.CorLibTypes.Int32), roCollectionTypeSpec); // Create 'System.Array' type ref var arrayRef = new TypeRefUser(mod, "System", "Array", assemblyRef); // Create 'ReadOnlyCollection<T> Array.AsReadOnly<T>(T[] array)' method reference // Apparently CreateStaticGeneric should be used only if at least one GenericMVar is used? Not 100% certain. var asReadOnly = new MemberRefUser(mod, "AsReadOnly", MethodSig.CreateStaticGeneric(1, roCollectionSig, new SZArraySig(new GenericMVar(0))), arrayRef); // Create 'Array.AsReadOnly<Int32>' method spec var asReadOnlySpec = new MethodSpecUser(asReadOnly, new GenericInstMethodSig(mod.CorLibTypes.Int32)); // Create 'ReadOnlyCollection<Int32>' signature for local var roCollectionInt32 = roCollectionTypeSpec.TryGetGenericInstSig(); // Method body locals IList <Local> locals = new List <Local>(); locals.Add(new Local(new SZArraySig(mod.CorLibTypes.Int32))); // local[0]: Int32[] locals.Add(new Local(roCollectionInt32)); // local[1]: class [mscorlib]System.Collections.ObjectModel.ReadOnlyCollection`1<Int32> var body = new CilBody(true, new List <Instruction>(), new List <ExceptionHandler>(), locals); // array = new Int32[2]; body.Instructions.Add(OpCodes.Ldc_I4_2.ToInstruction()); body.Instructions.Add(OpCodes.Newarr.ToInstruction(mod.CorLibTypes.Int32)); body.Instructions.Add(OpCodes.Stloc_0.ToInstruction()); // Store array to local[0] // array[0] = 5; body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4_5.ToInstruction()); body.Instructions.Add(OpCodes.Stelem_I4.ToInstruction()); // array[1] = 111; body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4_1.ToInstruction()); body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(111)); body.Instructions.Add(OpCodes.Stelem_I4.ToInstruction()); // collection = Array.AsReadOnly<Int32>(array) body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); body.Instructions.Add(OpCodes.Call.ToInstruction(asReadOnlySpec)); body.Instructions.Add(OpCodes.Stloc_1.ToInstruction()); // Console.WriteLine("Count: {0}", collection.Count) body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Count: {0}")); body.Instructions.Add(OpCodes.Ldloc_1.ToInstruction()); body.Instructions.Add(OpCodes.Callvirt.ToInstruction(roCollectionGetCount)); body.Instructions.Add(OpCodes.Box.ToInstruction(mod.CorLibTypes.Int32)); body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); // return 0; body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction()); body.Instructions.Add(OpCodes.Ret.ToInstruction()); entryPoint.Body = body; // Save the assembly mod.Write(newFileName); }
internal static async Task <int> Execute(ModuleDefMD targetModule) { // Fetch assembly refs var unityEngine = targetModule.GetAssemblyRef("UnityEngine"); // Fetch target type defs var characterActionsTypeDef = targetModule.Find("CharacterActions", true); var controllerTypeDef = targetModule.Find("Controller", true); var aiTypeDef = targetModule.Find("AI", true); // Fetch target method defs var aiStartMethodDef = aiTypeDef.FindMethod("Start"); var controllerStartMethodDef = controllerTypeDef.FindMethod("Start"); var characterActionsCreateWithControllerBindingsMethodDef = characterActionsTypeDef.FindMethod("CreateWithControllerBindings"); // Fetch target field defs var aiGoForGunsFieldDef = aiTypeDef.FindField("goForGuns"); var controllerHasControlFieldDef = controllerTypeDef.FindField("mHasControl"); var controllerPlayerActionsFieldDef = controllerTypeDef.FindField("mPlayerActions"); // Fetch type ref users var unityEngineComponentTypeRefUser = new TypeRefUser(targetModule, "UnityEngine", "Component", unityEngine); var unityEngineBehaviourTypeRefUser = new TypeRefUser(targetModule, "UnityEngine", "Behaviour", unityEngine); // Create method ref users var getComponentMethodRefUser = new MemberRefUser(targetModule, "GetComponent", MethodSig.CreateInstanceGeneric(1, new GenericMVar(0, aiStartMethodDef)), unityEngineComponentTypeRefUser); var setEnabledMethodRefUser = new MemberRefUser(targetModule, "set_enabled", MethodSig.CreateInstance(targetModule.CorLibTypes.Void, targetModule.CorLibTypes.Boolean), unityEngineBehaviourTypeRefUser); // Create method spec users var getComponentMethodSpecUser = new MethodSpecUser(getComponentMethodRefUser, new GenericInstMethodSig(aiTypeDef.ToTypeSig())); /* * * {IL_00C3: ldarg.0} * {IL_00C4: call AI UnityEngine.Component::GetComponent<AI>()} * {IL_00C9: ldc.i4.1} * {IL_00CA: callvirt System.Void UnityEngine.Behaviour::set_enabled(System.Boolean)} * */ var controllerStartInstructionSignature = new List <Instruction> { new Instruction(OpCodes.Ldarg_0), new Instruction(OpCodes.Call, getComponentMethodSpecUser), new Instruction(OpCodes.Ldc_I4_1), new Instruction(OpCodes.Callvirt, setEnabledMethodRefUser) }; var matchedControllerStartMethodInstructions = InjectionHelpers.FetchInstructionsBySigComparerSignature(controllerStartMethodDef.Body.Instructions, controllerStartInstructionSignature); if (matchedControllerStartMethodInstructions != null) { var lastMatchedInstruction = matchedControllerStartMethodInstructions.Last(); var injectionIndex = controllerStartMethodDef.Body.Instructions.IndexOf(lastMatchedInstruction) + 1; var controllerStartInstructionsToInject = new List <Instruction> { new Instruction(OpCodes.Ldarg_0), new Instruction(OpCodes.Call, getComponentMethodSpecUser), new Instruction(OpCodes.Ldc_I4_1), new Instruction(OpCodes.Stfld, aiGoForGunsFieldDef), new Instruction(OpCodes.Ldarg_0), new Instruction(OpCodes.Ldc_I4_1), new Instruction(OpCodes.Stfld, controllerHasControlFieldDef), new Instruction(OpCodes.Ldarg_0), new Instruction(OpCodes.Call, characterActionsCreateWithControllerBindingsMethodDef), new Instruction(OpCodes.Stfld, controllerPlayerActionsFieldDef), }; // Add new instructions after the matched signature for (var i = 0; i < controllerStartInstructionsToInject.Count; i++) { controllerStartMethodDef.Body.Instructions.Insert(injectionIndex + i, controllerStartInstructionsToInject[i]); } controllerStartMethodDef.Body.UpdateInstructionOffsets(); } else { return(await Task.FromResult(1)); } return(await Task.FromResult(0)); }