示例#1
0
        public static void CreateMethodRestore(MethodDef target, MethodDef newMethod, ModuleDefMD module)
        {
            AssemblyRef dnlib          = module.GetAssemblyRef(new UTF8String("dnlib"));
            TypeRefUser Instruction    = new TypeRefUser(module, new UTF8String("dnlib"), new UTF8String("Instruction"), dnlib);
            TypeSig     instructionSig = Instruction.ToTypeSig();

            var assemblyRef = module.CorLibTypes.AssemblyRef;

            var listRef            = new TypeRefUser(module, @"System.Collections.Generic", "List`1", assemblyRef);
            var listGenericInstSig = new GenericInstSig(new ClassSig(listRef), instructionSig);

            var listTypeSpec = new TypeSpecUser(listGenericInstSig);

            var listCtor         = new MemberRefUser(module, ".ctor", MethodSig.CreateInstance(module.CorLibTypes.Void), listTypeSpec);
            var instruictionCtor = new MemberRefUser(module, ".ctor", MethodSig.CreateInstance(module.CorLibTypes.Void), instructionSig.TryGetTypeSpec());

            var listAdd = new MemberRefUser(module, "Add", MethodSig.CreateInstance(module.CorLibTypes.Void, new GenericVar(0)), listTypeSpec);

            // sdsd

            newMethod.Body.Instructions.Add(OpCodes.Newobj.ToInstruction(listCtor));
            newMethod.Body.Instructions.Add(OpCodes.Stloc_0.ToInstruction()); // Store list to local[0]

            /*
             * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Dup));
             * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldsfld, OpCodes.Add));
             * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Ldc_I4_S, 0x37));
             * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Box, module.CorLibTypes.Int32));
             * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Newobj, instruictionCtor));
             * newMethod.Body.Instructions.Add(new Instruction(OpCodes.Callvirt, listAdd));
             */
        }
        AssemblyRef FindAssemblyRef(string asmSimpleName)
        {
            var asmRef = module.GetAssemblyRef(asmSimpleName);

            if (asmRef == null)
            {
                throw new ApplicationException(string.Format("Could not find assembly {0} in assembly references", asmSimpleName));
            }
            return(asmRef);
        }
示例#3
0
        string GetMscorlibFullname()
        {
            var mscorlibRef = module.GetAssemblyRef("mscorlib");

            if (mscorlibRef != null)
            {
                return(mscorlibRef.FullName);
            }

            return("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
        }
示例#4
0
        string tryGetRealAssemblyName(string assemblyName)
        {
            var simpleName = Utils.getAssemblySimpleName(assemblyName);

            var asmRef = module.GetAssemblyRef(simpleName);

            if (asmRef != null)
            {
                return(asmRef.FullName);
            }

            var asm = TheAssemblyResolver.Instance.Resolve(new AssemblyNameInfo(simpleName), module);

            return(asm == null ? null : asm.FullName);
        }
示例#5
0
        private static void Hook_SpriteFetcher_GetSprite(ModuleDefMD module)
        {
            TypeDef   cecilSource  = module.Find("SpriteFetcher", isReflectionName: true);
            MethodDef sourceMethod = cecilSource.Methods.Single(m => m.FullName == "UnityEngine.Sprite SpriteFetcher::GetSprite(ObjectTypes,System.Int32)");
            TypeDef   cecilTarget  = module.GetNuterraType(typeof(Hooks.ResourceLookup));
            MethodDef targetMethod = cecilTarget.Methods.Single(m => m.Name == nameof(Hooks.ResourceLookup.GetSprite));

            AssemblyRef   unityEngine        = module.GetAssemblyRef(new UTF8String("UnityEngine"));
            TypeRefUser   unityEngine_Object = new TypeRefUser(module, new UTF8String("UnityEngine"), new UTF8String("Object"), unityEngine);
            TypeSig       objectSig          = unityEngine_Object.ToTypeSig();
            MethodSig     op_Equality        = MethodSig.CreateStatic(module.CorLibTypes.Boolean, objectSig, objectSig);
            MemberRefUser op_EqualityMethod  = new MemberRefUser(module, new UTF8String("op_Inequality"), op_Equality, unityEngine_Object);

            var body = sourceMethod.Body.Instructions;
            var originalMethodStart = body.First();
            int index = 0;

            sourceMethod.Body.MaxStack = 6;
            body.Insert(index++, new Instruction(OpCodes.Ldarg_1));
            body.Insert(index++, new Instruction(OpCodes.Ldarg_2));
            body.Insert(index++, new Instruction(OpCodes.Call, targetMethod));
            body.Insert(index++, new Instruction(OpCodes.Stloc_0));
            body.Insert(index++, new Instruction(OpCodes.Ldloc_0));
            body.Insert(index++, new Instruction(OpCodes.Ldnull));
            body.Insert(index++, new Instruction(OpCodes.Call, op_EqualityMethod));
            body.Insert(index++, new Instruction(OpCodes.Brfalse_S, originalMethodStart));
            body.Insert(index++, new Instruction(OpCodes.Ldloc_0));
            body.Insert(index++, new Instruction(OpCodes.Ret));

            /*
             *      0	0000	ldarg.1
             *      1	0001	ldarg.2
             *      2	0002	call		class [UnityEngine]UnityEngine.Sprite Maritaria.BlockLoader::SpriteFetcher_GetSprite(valuetype ObjectTypes, int32)
             *      3	0007	stloc.0
             *      4	0008	ldloc.0
             *      5	0009	ldnull
             *      6	000A	call		bool [UnityEngine]UnityEngine.Object::op_Inequality(class [UnityEngine]UnityEngine.Object, class [UnityEngine]UnityEngine.Object)
             *      7	000F	brfalse.s	{ original method start instruction }
             *      8	0011	ldloc.0
             *      9	0012	ret
             *      ... remaining method code ...
             */
        }
        private string TryGetRealAssemblyName(IAssembly asm)
        {
            var simpleName = asm.Name;

            if (simpleName == module.CorLibTypes.AssemblyRef.Name)
            {
                return(module.CorLibTypes.AssemblyRef.FullName);
            }

            if (moduleMD != null)
            {
                var asmRef = moduleMD.GetAssemblyRef(simpleName);
                if (asmRef != null)
                {
                    return(asmRef.FullName);
                }
            }

            return(GetAssemblyFullName(simpleName));
        }
示例#7
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            // Fetch target type defs
            var controllerTypeDef = targetModule.Find("Controller", true);

            // Fetch target method defs
            var controllerJumpMethodDef = controllerTypeDef.FindMethod("Jump");

            // Fetch target field defs
            var controllerMovementStateFieldDef = controllerTypeDef.FindField("m_MovementState");

            /*
             *
             *  Remove redundant code that always sets 'movementState' to 'GroundJump' in the 'Controller.Jump' method.
             *
             *  Target instructions to patch:
             *
             *      62	00EE	ldarg.0
             *      63	00EF	ldloc.0
             *      64	00F0	brfalse	67 (00FB) ldc.i4.8
             *      65	00F5	ldc.i4.4
             *      66	00F6	br	68 (00FC) stfld valuetype Controller/MovementStateEnum Controller::m_MovementState
             *      67	00FB	ldc.i4.8
             *      68	00FC	stfld	valuetype Controller/MovementStateEnum Controller::m_MovementState
             *
             */

            var controllerJumpInstructionSignature = new List <Instruction> {
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldloc_0),
                new Instruction(OpCodes.Brfalse, new Instruction(OpCodes.Ldc_I4_8, null)),
                new Instruction(OpCodes.Ldc_I4_4),
                new Instruction(OpCodes.Br, new Instruction(OpCodes.Stfld, null)),
                new Instruction(OpCodes.Ldc_I4_8),
                new Instruction(OpCodes.Stfld, controllerMovementStateFieldDef)
            };

            var matchedControllerJumpMethodInstructions = InjectionHelpers.FetchInstructionsBySignature(controllerJumpMethodDef.Body.Instructions, controllerJumpInstructionSignature, false);

            if (matchedControllerJumpMethodInstructions != null)
            {
                // NOP the matched instructions
                matchedControllerJumpMethodInstructions.ForEach(matchedInstruction => matchedInstruction.OpCode = OpCodes.Nop);
            }
            else
            {
                return(await Task.FromResult(1));
            }

            /*
             *
             *  The 'Movement.Jump' method unsafely accesses the AudioClip array when selecting a random 'jump' sound to play.
             *  Add appropriate length check to fix the index out of bounds exception.
             *
             *  Target instructions to patch:
             *
             *      0	0000	ldarg.0
             *      1	0001	ldarg.1
             *      2	0002	ldarg.2
             *      3	0003	call	instance bool Movement::DoJump(bool, bool)
             *      4	0008	stloc.0
             *      5	0009	ldarg.0
             *      6	000A	ldfld	class [UnityEngine]UnityEngine.AudioSource Movement::au
             *      7	000F	ldarg.0
             *      8	0010	ldfld	class [UnityEngine]UnityEngine.AudioClip[] Movement::jumpClips
             *      9	0015	ldc.i4.0
             *      10	0016	ldarg.0
             *      11	0017	ldfld	class [UnityEngine]UnityEngine.AudioClip[] Movement::jumpClips
             *      12	001C	ldlen
             *      13	001D	conv.i4
             *      14	001E	call	int32 [UnityEngine]UnityEngine.Random::Range(int32, int32)
             *      15	0023	ldelem.ref
             *      16	0024	callvirt	instance void [UnityEngine]UnityEngine.AudioSource::PlayOneShot(class [UnityEngine]UnityEngine.AudioClip)
             *      17	0029	ldloc.0
             *      18	002A	ret
             *
             *
             *  Resulting instructions after patching:
             *
             *      0	0000	ldarg.0
             *      1	0001	ldarg.1
             *      2	0002	ldarg.2
             *      3	0003	call	instance bool Movement::DoJump(bool, bool)
             *      4	0008	ldarg.0
             *      5	0009	ldfld	class [UnityEngine]UnityEngine.AudioClip[] Movement::jumpClips
             *      6	000E	ldlen
             *      7	000F	brfalse.s	24 (0039) ret
             *      8	0011	ldarg.0
             *      9	0012	ldfld	class [UnityEngine]UnityEngine.AudioSource Movement::au
             *      10	0017	ldarg.0
             *      11	0018	ldfld	class [UnityEngine]UnityEngine.AudioClip[] Movement::jumpClips
             *      12	001D	ldc.i4.0
             *      13	001E	ldarg.0
             *      14	001F	ldfld	class [UnityEngine]UnityEngine.AudioClip[] Movement::jumpClips
             *      15	0024	ldlen
             *      16	0025	conv.i4
             *      17	0026	ldc.i4.1
             *      18	0027	sub
             *      19	0028	ldc.i4.0
             *      20	0029	call	int32 [mscorlib]System.Math::Max(int32, int32)
             *      21	002E	call	int32 [UnityEngine]UnityEngine.Random::Range(int32, int32)
             *      22	0033	ldelem.ref
             *      23	0034	callvirt	instance void [UnityEngine]UnityEngine.AudioSource::PlayOneShot(class [UnityEngine]UnityEngine.AudioClip)
             *      24	0039	ret
             *
             */

            // Fetch target type defs
            var movementTypeDef = targetModule.Find("Movement", true);

            // Fetch target method defs
            var movementJumpMethodDef   = movementTypeDef.FindMethod("Jump");
            var movementDoJumpMethodDef = movementTypeDef.FindMethod("DoJump");

            // Fetch target field defs
            var movementAuFieldDef        = movementTypeDef.FindField("au");
            var movementJumpClipsFieldDef = movementTypeDef.FindField("jumpClips");

            // Fetch reference assembly refs
            var mscorlibAssemblyRef    = targetModule.GetAssemblyRef(new UTF8String("mscorlib"));
            var unityEngineAssemblyRef = targetModule.GetAssemblyRef(new UTF8String("UnityEngine"));

            // Construct type ref users
            var systemMathTypeRefUser             = new TypeRefUser(targetModule, new UTF8String("System"), new UTF8String("Math"), mscorlibAssemblyRef);
            var unityEngineAudioClipTypeRefUser   = new TypeRefUser(targetModule, new UTF8String("UnityEngine"), new UTF8String("AudioClip"), unityEngineAssemblyRef);
            var unityEngineRandomTypeRefUser      = new TypeRefUser(targetModule, new UTF8String("UnityEngine"), new UTF8String("Random"), unityEngineAssemblyRef);
            var unityEngineAudioSourceTypeRefUser = new TypeRefUser(targetModule, new UTF8String("UnityEngine"), new UTF8String("AudioSource"), unityEngineAssemblyRef);

            // Construct member ref users
            var maxMethodRefUser         = new MemberRefUser(targetModule, new UTF8String("Max"), MethodSig.CreateStatic(targetModule.CorLibTypes.Int32, targetModule.CorLibTypes.Int32, targetModule.CorLibTypes.Int32), systemMathTypeRefUser);
            var randomRangeMethodRefUser = new MemberRefUser(targetModule, new UTF8String("Range"), MethodSig.CreateStatic(targetModule.CorLibTypes.Int32, targetModule.CorLibTypes.Int32, targetModule.CorLibTypes.Int32), unityEngineRandomTypeRefUser);
            var playOneShotMethodRefUser = new MemberRefUser(targetModule, new UTF8String("PlayOneShot"), MethodSig.CreateInstance(targetModule.CorLibTypes.Void, unityEngineAudioClipTypeRefUser.ToTypeSig()), unityEngineAudioSourceTypeRefUser);

            // Construct list of instructions to be injected
            var retInstruction = new Instruction(OpCodes.Ret);

            var movementJumpInstructions = new List <Instruction>()
            {
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldarg_1),
                new Instruction(OpCodes.Ldarg_2),
                new Instruction(OpCodes.Call, movementDoJumpMethodDef),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, movementJumpClipsFieldDef),
                new Instruction(OpCodes.Ldlen),
                new Instruction(OpCodes.Brfalse_S, retInstruction),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, movementAuFieldDef),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, movementJumpClipsFieldDef),
                new Instruction(OpCodes.Ldc_I4_0),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, movementJumpClipsFieldDef),
                new Instruction(OpCodes.Ldlen),
                new Instruction(OpCodes.Conv_I4),
                new Instruction(OpCodes.Ldc_I4_1),
                new Instruction(OpCodes.Sub),
                new Instruction(OpCodes.Ldc_I4_0),
                new Instruction(OpCodes.Call, maxMethodRefUser),
                new Instruction(OpCodes.Call, randomRangeMethodRefUser),
                new Instruction(OpCodes.Ldelem_Ref),
                new Instruction(OpCodes.Callvirt, playOneShotMethodRefUser),
                retInstruction
            };

            // Replace all instructions in the method with the new instructions
            movementJumpMethodDef.Body.Instructions.Clear();
            movementJumpInstructions.ForEach(movementJumpInstruction => movementJumpMethodDef.Body.Instructions.Add(movementJumpInstruction));
            movementJumpMethodDef.Body.UpdateInstructionOffsets();

            return(await Task.FromResult(0));
        }
示例#8
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));
        }
示例#9
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            // Fetch type defs
            var controllerTypeDef    = targetModule.Find("Controller", true);
            var fightingTypeDef      = targetModule.Find("Fighting", true);
            var networkPlayerTypeDef = targetModule.Find("NetworkPlayer", true);
            var chatManagerTypeDef   = targetModule.Find("ChatManager", true);

            if (controllerTypeDef == null)
            {
                return(await Task.FromResult(1));
            }

            if (fightingTypeDef == null)
            {
                return(await Task.FromResult(2));
            }

            if (networkPlayerTypeDef == null)
            {
                return(await Task.FromResult(3));
            }

            if (chatManagerTypeDef == null)
            {
                return(await Task.FromResult(4));
            }

            // Fetch field defs
            var isAiFieldDef           = controllerTypeDef.FindField("isAI");
            var fightingFieldDef       = controllerTypeDef.FindField("fighting");
            var mNetworkPlayerFieldDef = fightingTypeDef.FindField("mNetworkPlayer");
            var mChatManagerFieldDef   = networkPlayerTypeDef.FindField("mChatManager");

            if (isAiFieldDef == null)
            {
                return(await Task.FromResult(5));
            }

            if (fightingFieldDef == null)
            {
                return(await Task.FromResult(6));
            }

            if (mNetworkPlayerFieldDef == null)
            {
                return(await Task.FromResult(7));
            }

            if (mChatManagerFieldDef == null)
            {
                return(await Task.FromResult(8));
            }

            // Fetch method defs
            var onTakeDamageMethodDef = controllerTypeDef.FindMethod("OnTakeDamage");
            var talkMethodDef         = chatManagerTypeDef.FindMethod("Talk");

            if (onTakeDamageMethodDef == null)
            {
                return(await Task.FromResult(9));
            }

            if (talkMethodDef == null)
            {
                return(await Task.FromResult(10));
            }

            // Fetch reference assembly refs
            var unityEngineAssemblyRef = targetModule.GetAssemblyRef(new UTF8String("UnityEngine"));

            // Construct type ref users
            var unityEngineRandomTypeRefUser = new TypeRefUser(targetModule, new UTF8String("UnityEngine"), new UTF8String("Random"), unityEngineAssemblyRef);

            // Construct member ref users
            var randomRangeMethodRefUser = new MemberRefUser(targetModule, new UTF8String("Range"), MethodSig.CreateStatic(targetModule.CorLibTypes.Int32, targetModule.CorLibTypes.Int32, targetModule.CorLibTypes.Int32), unityEngineRandomTypeRefUser);

            /*
             *
             *  // Instructions to inject
             *
             *  0	0000	ldarg.0
             *  1	0001	ldfld	bool Controller::isAI
             *  2	0006	brfalse.s	40 (0085) ldarg.0
             *  3	0008	ldarg.0
             *  4	0009	ldfld	class Fighting Controller::fighting
             *  5	000E	ldfld	class NetworkPlayer Fighting::mNetworkPlayer
             *  6	0013	brfalse.s	40 (0085) ldarg.0
             *  7	0015	ldc.i4.0
             *  8	0016	ldc.i4	10
             *  9	001B	call	int32 [UnityEngine]UnityEngine.Random::Range(int32, int32)
             *  10	0020	stloc.0
             *  11	0021	ldloc.0
             *  12	0022	ldc.i4.s	1
             *  13	0024	bne.un.s	21 (0042) ldloc.0
             *  14	0026	ldarg.0
             *  15	0027	ldfld	class Fighting Controller::fighting
             *  16	002C	ldfld	class NetworkPlayer Fighting::mNetworkPlayer
             *  17	0031	ldfld	class ChatManager NetworkPlayer::mChatManager
             *  18	0036	ldstr	"Ouch!"
             *  19	003B	callvirt	instance void ChatManager::Talk(string)
             *  20	0040	br.s	40 (0085) ldarg.0
             *  21	0042	ldloc.0
             *  22	0043	ldc.i4	0x1D1
             *  23	0048	bne.un.s	31 (0066) ldloc.0
             *  24	004A	ldarg.0
             *  25	004B	ldfld	class Fighting Controller::fighting
             *  26	0050	ldfld	class NetworkPlayer Fighting::mNetworkPlayer
             *  27	0055	ldfld	class ChatManager NetworkPlayer::mChatManager
             *  28	005A	ldstr	"Ow!"
             *  29	005F	callvirt	instance void ChatManager::Talk(string)
             *  30	0064	br.s	40 (0085) ldarg.0
             *  31	0066	ldloc.0
             *  32	0067	ldc.i4.s	10
             *  33	0069	bne.un.s	40 (0085) ldarg.0
             *  34	006B	ldarg.0
             *  35	006C	ldfld	class Fighting Controller::fighting
             *  36	0071	ldfld	class NetworkPlayer Fighting::mNetworkPlayer
             *  37	0076	ldfld	class ChatManager NetworkPlayer::mChatManager
             *  38	007B	ldstr	"That's monk-y business!"
             *  39	0080	callvirt	instance void ChatManager::Talk(string)
             *
             */

            var firstInstruction = onTakeDamageMethodDef.Body.Instructions.First();

            var branches = new List <Instruction>()
            {
                new Instruction(OpCodes.Ldloc_0),
                new Instruction(OpCodes.Ldloc_0)
            };

            var condition1 = new List <Instruction>()
            {
                new Instruction(OpCodes.Ldloc_0),
                new Instruction(OpCodes.Ldc_I4_S, Convert.ToByte(10)),
                new Instruction(OpCodes.Bne_Un_S, branches[0]),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, fightingFieldDef),
                new Instruction(OpCodes.Ldfld, mNetworkPlayerFieldDef),
                new Instruction(OpCodes.Ldfld, mChatManagerFieldDef),
                new Instruction(OpCodes.Ldstr, "Ouch!"),
                new Instruction(OpCodes.Callvirt, talkMethodDef),
                new Instruction(OpCodes.Br_S, firstInstruction)
            };

            var condition2 = new List <Instruction>()
            {
                branches[0],
                new Instruction(OpCodes.Ldc_I4, 500),
                new Instruction(OpCodes.Bne_Un_S, branches[1]),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, fightingFieldDef),
                new Instruction(OpCodes.Ldfld, mNetworkPlayerFieldDef),
                new Instruction(OpCodes.Ldfld, mChatManagerFieldDef),
                new Instruction(OpCodes.Ldstr, "Existence is pain!"),
                new Instruction(OpCodes.Callvirt, talkMethodDef),
                new Instruction(OpCodes.Br_S, firstInstruction)
            };

            var condition3 = new List <Instruction>()
            {
                branches[1],
                new Instruction(OpCodes.Ldc_I4_S, Convert.ToByte(100)),
                new Instruction(OpCodes.Bne_Un_S, firstInstruction),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, fightingFieldDef),
                new Instruction(OpCodes.Ldfld, mNetworkPlayerFieldDef),
                new Instruction(OpCodes.Ldfld, mChatManagerFieldDef),
                new Instruction(OpCodes.Ldstr, "That's monk-y business!"),
                new Instruction(OpCodes.Callvirt, talkMethodDef)
            };

            var instructionsToInject = new List <Instruction>()
            {
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, isAiFieldDef),
                new Instruction(OpCodes.Brfalse_S, firstInstruction),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, fightingFieldDef),
                new Instruction(OpCodes.Ldfld, mNetworkPlayerFieldDef),
                new Instruction(OpCodes.Brfalse_S, firstInstruction),
                new Instruction(OpCodes.Ldc_I4_0),
                new Instruction(OpCodes.Ldc_I4, 800),
                new Instruction(OpCodes.Call, randomRangeMethodRefUser),
                new Instruction(OpCodes.Stloc_0)
            }
            .Concat(condition1)
            .Concat(condition2)
            .Concat(condition3)
            .ToList();

            for (var i = 0; i < instructionsToInject.Count; i++)
            {
                onTakeDamageMethodDef.Body.Instructions.Insert(i, instructionsToInject[i]);
            }

            onTakeDamageMethodDef.Body.Variables.Add(new Local(targetModule.CorLibTypes.Int32, "num"));

            onTakeDamageMethodDef.Body.OptimizeBranches();
            onTakeDamageMethodDef.Body.UpdateInstructionOffsets();

            return(await Task.FromResult(0));
        }
示例#10
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));
        }