Example #1
0
        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);
 }
Example #3
0
        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();
        }
Example #8
0
        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);
        }
Example #9
0
        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);
            }
        }
Example #10
0
        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));
        }
Example #11
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);
        }
Example #12
0
        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));
        }