Exemple #1
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            var bodyPartTypeDef   = targetModule.Find("BodyPart", true);
            var controllerTypeDef = targetModule.Find("Controller", true);

            var onCollisionEnterMethod = bodyPartTypeDef.FindMethod("OnCollisionEnter");
            var canFlyFieldDef         = controllerTypeDef.FindField("canFly");

            var bodyPartControllerFieldDef = bodyPartTypeDef.FindField("controller");

            var instructionSignature = new List <Instruction> {
                new Instruction(OpCodes.Ldfld, bodyPartControllerFieldDef),
                new Instruction(OpCodes.Ldfld, canFlyFieldDef),
                new Instruction(OpCodes.Brtrue, new Instruction(OpCodes.Ldarg_1, null)),
                new Instruction(OpCodes.Ldarg_0, null)
            };

            var matchedInstructions = InjectionHelpers.FetchInstructionsBySignature(onCollisionEnterMethod.Body.Instructions, instructionSignature, false);

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

            return(await Task.FromResult(0));
        }
Exemple #2
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            // Fetch target type defs
            var controllerTypeDef = targetModule.Find("Controller", true);

            // Fetch target method defs
            var controllerSetCollisionMethodDef = controllerTypeDef.FindMethod("SetCollision");

            // Fetch target field defs
            var controllerIsAiFieldDef     = controllerTypeDef.FindField("isAI");
            var controllerPlayerIdFieldDef = controllerTypeDef.FindField("playerID");

            /*
             *
             *  32	004C	ldarg.0
             *  33	004D	ldfld	    bool Controller::isAI
             *  34	0052	brfalse.s	40 (0063) ldloc.2
             *
             */

            // Signature of the condition to which the check will be added
            var controllerSetCollisionAiCheckInstructionSignature = new List <Instruction> {
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, controllerIsAiFieldDef),
                new Instruction(OpCodes.Brfalse, null)
            };

            var matchedControllerSetCollisionAiCheckMethodInstructions = InjectionHelpers.FetchInstructionsBySignature(controllerSetCollisionMethodDef.Body.Instructions, controllerSetCollisionAiCheckInstructionSignature, false);

            if (matchedControllerSetCollisionAiCheckMethodInstructions != null)
            {
                var branchInstruction = matchedControllerSetCollisionAiCheckMethodInstructions.Last();
                var injectionIndex    = controllerSetCollisionMethodDef.Body.Instructions.IndexOf(branchInstruction) + 1;

                // Set unique gameObject layer in Controller.SetCollision for AIs with Player IDs.
                var controllerSetCollisionAiCheckInstructionsToInject = new List <Instruction>
                {
                    new Instruction(OpCodes.Ldarg_0),
                    new Instruction(OpCodes.Ldfld, controllerPlayerIdFieldDef),
                    new Instruction(OpCodes.Ldc_I4_0),
                    new Instruction(OpCodes.Bge_S, branchInstruction.Operand),
                };

                // Add new instructions after the matched signature
                for (var i = 0; i < controllerSetCollisionAiCheckInstructionsToInject.Count; i++)
                {
                    controllerSetCollisionMethodDef.Body.Instructions.Insert(injectionIndex + i, controllerSetCollisionAiCheckInstructionsToInject[i]);
                }

                controllerSetCollisionMethodDef.Body.UpdateInstructionOffsets();
            }
            else
            {
                return(await Task.FromResult(1));
            }

            return(await Task.FromResult(0));
        }
Exemple #3
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            if (InjectionHelpers.AddField(targetModule, "Fighting", "TrainerWeaponIndex", targetModule.CorLibTypes.Int32, FieldAttributes.Public) == null)
            {
                return(await Task.FromResult(1));
            }

            return(await Task.FromResult(0));
        }
Exemple #4
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            if (InjectionHelpers.ClearMethodBody(targetModule, "ChatManager", "Awake") == false)
            {
                return(await Task.FromResult(1));
            }

            return(await Task.FromResult(0));
        }
Exemple #5
0
        private bool InjectTrainerLogicModuleTypes()
        {
            var trainerOptionsTypeDef = _logicModule.Find("TrainerOptions", false);
            var trainerManagerTypeDef = _logicModule.Find("TrainerManager", false);
            var singletonTypeDef      = _logicModule.Find("Singleton`1", true);

            var singletonSucceeded      = InjectionHelpers.AddTypeToModule(singletonTypeDef, _targetModule);
            var trainerOptionsSucceeded = InjectionHelpers.AddTypeToModule(trainerOptionsTypeDef, _targetModule);
            var trainerManagerSucceeded = InjectionHelpers.AddTypeToModule(trainerManagerTypeDef, _targetModule);

            return(singletonSucceeded && trainerOptionsSucceeded && trainerManagerSucceeded);
        }
Exemple #6
0
        private async Task SaveAndReloadTargetModule(bool reload = true, bool reloadInMemory = true, bool writeToFile = false)
        {
            var data = await InjectionHelpers.Save(_targetModule, writeToFile);

            if (reload)
            {
                if (reloadInMemory == false)
                {
                    _targetModule = ModuleDefMD.Load(_targetModulePath);
                }
                else if (reloadInMemory)
                {
                    _targetModule          = ModuleDefMD.Load(data);
                    _targetModule.Location = _targetModulePath;
                }
            }
        }
Exemple #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));
        }
Exemple #8
0
        public async Task <bool> PatchTargetModule(bool takeBackup)
        {
            int patchingStatus = 0;

            if (_targetModule == null)
            {
                await _logger.Log("Target module is not loaded. Patching aborted.");

                return(await Task.FromResult(false));
            }

            if (takeBackup)
            {
                await CreateBackup();
            }

            await _logger.Log("Initiating patching");

            await _logger.Log($"Game version: {await GetGameVersion()}");

            await _logger.Log($"Patcher version: {Application.ProductVersion}");

            // Add a private field indicating that the module has been modified.
            await _logger.Log("Adding trainer patch indicator");

            patchingStatus = await AddTrainerPatchIndicator.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not add trainer patch indicator: {patchingStatus}", LogLevel.Error);

                return(await Task.FromResult(false));
            }

            await SaveAndReloadTargetModule();

            // Set target fields and methods as public in order to allow TrainerLogic.dll's code to reference them and compile.
            // Note: While it would have been convenient to simply set *every* field and method as public/internal, it causes in-game glitches (e.g. ambiguous references and null reference exceptions)
            await _logger.Log("Setting fields as public");

            _targetFields.ForEach(targetField => InjectionHelpers.SetFieldAccessModifier(_targetModule, targetField.Key, targetField.Value, FieldAttributes.Public));

            await _logger.Log("Setting methods as public");

            _targetMethods.ForEach(targetMethod => InjectionHelpers.SetMethodAccessModifier(_targetModule, targetMethod.Key, targetMethod.Value, MethodAttributes.Public));

            await _logger.Log("Adding TrainerWeaponIndex field to fighting class");

            patchingStatus = await AddTrainerWeaponIndex.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not add TrainerWeaponIndex field to fighting class: {patchingStatus}");

                return(await Task.FromResult(false));
            }

            await SaveAndReloadTargetModule(true, true, true);

            // Compile and load TrainerLogic module
            await _logger.Log("Compiling Trainer Logic module");

            if (!await CompileTrainerLogicModule())
            {
                await _logger.Log("Could not compile Trainer Logic module", LogLevel.Error);

                return(await Task.FromResult(false));
            }

            await SaveAndReloadTargetModule();

            // Keeping the fields as public causes exceptions due to reference ambiguity, so they need to be made internal following successful compilation.
            await _logger.Log("Setting fields as internal");

            _targetFields.ForEach(targetField => InjectionHelpers.SetFieldAccessModifier(_targetModule, targetField.Key, targetField.Value, FieldAttributes.Assembly));

            await _logger.Log("Setting methods as internal");

            _targetMethods.ForEach(targetMethod => InjectionHelpers.SetMethodAccessModifier(_targetModule, targetMethod.Key, targetMethod.Value, MethodAttributes.Assembly));

            await SaveAndReloadTargetModule();

            // Inject TrainerOptions class
            await _logger.Log("Injecting trainer logic modules");

            if (InjectTrainerLogicModuleTypes() == false)
            {
                await _logger.Log("Could not inject trainer logic modules", LogLevel.Error);

                return(await Task.FromResult(false));
            }

            await _logger.Log("Injecting custom AI logic");

            if (InjectCustomAILogic() == false)
            {
                await _logger.Log("Could not inject AI logic module", LogLevel.Error);

                return(await Task.FromResult(false));
            }

            await SaveAndReloadTargetModule();

            // Inject declaration of TrainerManager class into GameManager class and inject its instantiation code into GameManager's Start() method
            await _logger.Log("Adding TrainerManager to GameManager");

            patchingStatus = await AddTrainerManagerToGameManager.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not add TrainerManager to GameManager: {patchingStatus}", LogLevel.Error);

                return(await Task.FromResult(false));
            }

            await SaveAndReloadTargetModule();

            await _logger.Log("Add trainer game version constant");

            patchingStatus = await AddTrainerVersionConstant.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not add trainer game version constant: {patchingStatus}", LogLevel.Error);

                return(await Task.FromResult(false));
            }

            await _logger.Log("Enabling chat bubble in all lobbies");

            patchingStatus = await EnableChatBubbleInAllLobbies.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not enable chat bubble in all lobies: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Enabling flying mode weapon pickup");

            patchingStatus = await EnableFlyingModeWeaponPickup.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not enable flying mode weapon pickup: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Enabling flying mode weapon throw");

            patchingStatus = await EnableFlyingModeWeaponThrow.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not enable flying mode weapon throw: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Enabling unlimited health option");

            patchingStatus = await EnableNoPlayerDamage.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not enable unlimited health option: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Adding win counter");

            patchingStatus = await AddWinCounter.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not add win counter: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Applying bot jump fix");

            patchingStatus = await ApplyBotJumpFix.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not apply bot jump fix: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Applying bot death fix");

            patchingStatus = await ApplyBotDeathFix.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not apply bot death fix: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Applying bot collision fix");

            patchingStatus = await ApplyBotCollisionFix.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not apply bot collision fix: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Applying bot HasControl fix");

            patchingStatus = await ApplyBotHasControlFix.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not apply bot HasControl fix: {patchingStatus}", LogLevel.Warning);
            }

            await _logger.Log("Adding bot chat messages");

            patchingStatus = await AddBotChatMessages.Execute(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not add bot chat messages: {patchingStatus}", LogLevel.Warning);
            }

            await SaveAndReloadTargetModule();

#if DEBUG
            await _logger.Log("Protecting assembly");

            patchingStatus = await TrainerProtectionUtilities.ObfuscateTrainer(_targetModule);

            if (patchingStatus > 0)
            {
                await _logger.Log($"Could not obfuscate trainer: {patchingStatus}", LogLevel.Error);

                return(await Task.FromResult(false));
            }

            await SaveAndReloadTargetModule();

            if (await _protectionUtilities.ConfuseAssembly(_targetModulePath, _targetModule) == false)
            {
                await _logger.Log("Could not confuse assembly", LogLevel.Error);

                return(await Task.FromResult(false));
            }
#endif

            await _logger.Log("Patching completed");

            return(await Task.FromResult(true));
        }
Exemple #9
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));
        }
Exemple #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));
        }
Exemple #11
0
        internal static async Task <int> Execute(ModuleDefMD targetModule)
        {
            // Fetch target type defs
            var controllerTypeDef    = targetModule.Find("Controller", true);
            var healthHandlerTypeDef = targetModule.Find("HealthHandler", true);

            // Fetch target method defs
            var healthHandlerDieMethodDef = healthHandlerTypeDef.FindMethod("Die");

            // Fetch target field defs
            var controllerIsAiFieldDef          = controllerTypeDef.FindField("isAI");
            var controllerPlayerIdFieldDef      = controllerTypeDef.FindField("playerID");
            var healthHandlerControllerFieldDef = healthHandlerTypeDef.FindField("controller");

            /*
             *
             *  55	009F	brfalse.s	69 (00CB) call bool MatchmakingHandler::get_IsNetworkMatch()
             *  56	00A1	ldarg.0
             *  57	00A2	ldfld	    class Controller HealthHandler::controller
             *  58	00A7	ldfld	    bool Controller::isAI
             *  59	00AC	brfalse.s	69 (00CB) call bool MatchmakingHandler::get_IsNetworkMatch()
             *
             */

            // Signature of the condition to which the check will be added
            var healthHandlerAiCheckInstructionSignature = new List <Instruction> {
                new Instruction(OpCodes.Brfalse, null),
                new Instruction(OpCodes.Ldarg_0),
                new Instruction(OpCodes.Ldfld, healthHandlerControllerFieldDef),
                new Instruction(OpCodes.Ldfld, controllerIsAiFieldDef),
                new Instruction(OpCodes.Brfalse, null)
            };

            var matchedHealthHandlerDieMethodInstructions = InjectionHelpers.FetchInstructionsBySignature(healthHandlerDieMethodDef.Body.Instructions, healthHandlerAiCheckInstructionSignature, false);

            if (matchedHealthHandlerDieMethodInstructions != null)
            {
                var branchInstruction = matchedHealthHandlerDieMethodInstructions.Last();
                var injectionIndex    = healthHandlerDieMethodDef.Body.Instructions.IndexOf(branchInstruction) + 1;

                // Add check for a valid playerID when checking that the controller is an AI
                var healtHandlerAiCheckInstructionsToInject = new List <Instruction>
                {
                    new Instruction(OpCodes.Ldarg_0),
                    new Instruction(OpCodes.Ldfld, healthHandlerControllerFieldDef),
                    new Instruction(OpCodes.Ldfld, controllerPlayerIdFieldDef),
                    new Instruction(OpCodes.Ldc_I4_M1),
                    new Instruction(OpCodes.Bgt_S, branchInstruction.Operand),
                };

                // Add new instructions after the matched signature
                for (var i = 0; i < healtHandlerAiCheckInstructionsToInject.Count; i++)
                {
                    healthHandlerDieMethodDef.Body.Instructions.Insert(injectionIndex + i, healtHandlerAiCheckInstructionsToInject[i]);
                }

                healthHandlerDieMethodDef.Body.UpdateInstructionOffsets();
            }
            else
            {
                return(await Task.FromResult(1));
            }

            return(await Task.FromResult(0));
        }