public void Patch() { HelperClass.SetLogger(logger); MethodDefinition setBlocksMethod = HelperClass.findMember <MethodDefinition>(module, "GameManager", false, HelperClass.MemberNameComparer <MethodDefinition>("SetBlocksRPC")); PropertyDefinition worldProperty = HelperClass.findMember <PropertyDefinition>(module, "GameManager", false, HelperClass.MemberNameComparer <PropertyDefinition>("World")); if (setBlocksMethod != null && worldProperty != null) { MethodBody body = setBlocksMethod.Body; ILProcessor proc = body.GetILProcessor(); List <Instruction> hook = HookHelper.Instance.prepareEventHook(setBlocksMethod, "SetBlocksEvent", new Instruction[][] { new Instruction[] { proc.Create(OpCodes.Ldc_I4_0), proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Boolean"))) }, new Instruction[] { proc.Create(OpCodes.Ldarg_1) }, new Instruction[] { proc.Create(OpCodes.Ldarg_0), proc.Create(OpCodes.Call, module.Import(worldProperty.GetMethod)) }, }); hook.Add(proc.Create(OpCodes.Dup)); hook.Add(proc.Create(OpCodes.Ldc_I4_0)); hook.Add(proc.Create(OpCodes.Ldelem_Ref)); hook.Add(proc.Create(OpCodes.Unbox_Any, module.Import(mscorlibModule.GetType("System.Boolean")))); int jmp1_sindex = hook.Count; hook.Add(null); //Brfalse hook.Add(proc.Create(OpCodes.Pop)); hook.Add(proc.Create(OpCodes.Ret)); int jmp1_tindex = hook.Count; hook.Add(proc.Create(OpCodes.Ldc_I4_1)); hook.Add(proc.Create(OpCodes.Ldelem_Ref)); hook.Add(proc.Create(OpCodes.Starg, 1)); hook.Insert(jmp1_sindex, proc.Create(OpCodes.Brfalse, hook[jmp1_tindex])); hook.RemoveAt(jmp1_sindex + 1); HookHelper.insertAt(body, 0, hook.ToArray()); } }
public void Patch() { HelperClass.SetLogger(logger); MethodDefinition initChunkCluster = HelperClass.findMember <MethodDefinition>(module, "ChunkCluster", false, HelperClass.MemberNameComparer <MethodDefinition>("Init"), HelperClass.MethodParametersComparer("EnumChunkProviderId")); if (initChunkCluster == null) { return; } { int[] jumpsToDefault = HelperClass.FindOPCodePattern(initChunkCluster, new OpCode[] { OpCodes.Switch, OpCodes.Br }, 1); if (jumpsToDefault.Length == 0) { logger.Error("ChunkCluster.Init has no switch (am I outdated?)!"); return; } if (jumpsToDefault.Length > 1) { logger.Error("ChunkCluster.Init has multiple switches (am I outdated?)!"); return; } MethodBody body = initChunkCluster.Body; int targetIndex = body.Instructions.IndexOf((Instruction)body.Instructions[jumpsToDefault[0]].Operand); if (!HelperClass.MethodOPCodeComparer(new int[] { targetIndex, targetIndex + 1, targetIndex + 2 }, new OpCode[] { OpCodes.Ldarg_0, OpCodes.Ldnull, OpCodes.Stfld }, null).Execute(initChunkCluster)) { logger.Error("ChunkCluster.Init's default case is unknown (I am outdated!)!"); return; } ILProcessor proc = body.GetILProcessor(); List <Instruction> hook = HookHelper.Instance.prepareEventHook(initChunkCluster, "UnknownChunkProviderEvent", new Instruction[][] { new Instruction[] { proc.Create(OpCodes.Ldarg_0) }, new Instruction[] { proc.Create(OpCodes.Ldc_I4_0), proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Boolean"))) }, new Instruction[] { proc.Create(OpCodes.Ldarg_1), proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Int32"))) }, new Instruction[] { proc.Create(OpCodes.Ldnull) }, }); hook.Insert(0, proc.Create(OpCodes.Ldarg_0)); hook.Add(proc.Create(OpCodes.Dup)); hook.Add(proc.Create(OpCodes.Ldc_I4_1)); hook.Add(proc.Create(OpCodes.Ldelem_Ref)); hook.Add(proc.Create(OpCodes.Unbox_Any, module.Import(mscorlibModule.GetType("System.Boolean")))); int jmp1_sindex = hook.Count; hook.Add(null); //brtrue hook.Add(proc.Create(OpCodes.Pop)); hook.Add(proc.Create(OpCodes.Br, body.Instructions[targetIndex + 1])); int jmp1_tindex = hook.Count; hook.Add(proc.Create(OpCodes.Ldc_I4_2)); hook.Add(proc.Create(OpCodes.Ldelem_Ref)); hook.Add(proc.Create(OpCodes.Br, body.Instructions[targetIndex + 2])); hook.RemoveAt(jmp1_sindex); hook.Insert(jmp1_sindex, proc.Create(OpCodes.Brtrue, hook[jmp1_tindex])); HookHelper.insertAt(body, targetIndex, hook.ToArray()); body.Instructions[jumpsToDefault[0]].Operand = hook[0]; } }
public void Patch() { HelperClass.SetLogger(logger); MethodDefinition onGameInit = HelperClass.findMember <MethodDefinition>(skModule, "SurvivalKit.SKMain", false, HelperClass.MemberNameComparer <MethodDefinition>("onGameInit")); MethodDefinition onGameEnable = HelperClass.findMember <MethodDefinition>(skModule, "SurvivalKit.SKMain", false, HelperClass.MemberNameComparer <MethodDefinition>("onGameEnable")); MethodDefinition onGameDisable = HelperClass.findMember <MethodDefinition>(skModule, "SurvivalKit.SKMain", false, HelperClass.MemberNameComparer <MethodDefinition>("onGameDisable")); if (onGameInit == null || onGameEnable == null || onGameDisable == null) { return; } MethodDefinition initMethod = HelperClass.findMember <MethodDefinition>(module, "ConnectionManager", false, HelperClass.MemberNameComparer <MethodDefinition>(".cctor")); MethodDefinition awakeMethod = HelperClass.findMember <MethodDefinition>(module, "GameManager", false, HelperClass.MemberNameComparer <MethodDefinition>("Awake")); MethodDefinition cleanupMethod = HelperClass.findMember <MethodDefinition>(module, "GameManager", false, HelperClass.MemberNameComparer <MethodDefinition>("Cleanup")); if (initMethod == null || awakeMethod == null || cleanupMethod == null) { return; } { ILProcessor proc = initMethod.Body.GetILProcessor(); proc.InsertBefore(initMethod.Body.Instructions[0], proc.Create(OpCodes.Call, module.Import(onGameInit))); } { ILProcessor proc = awakeMethod.Body.GetILProcessor(); Instruction lastInstr; proc.InsertBefore(awakeMethod.Body.Instructions[0], (lastInstr = proc.Create(OpCodes.Ldarg_0))); proc.InsertAfter(lastInstr, proc.Create(OpCodes.Call, module.Import(onGameEnable))); } { ILProcessor proc = cleanupMethod.Body.GetILProcessor(); Instruction lastInstr; proc.InsertBefore(cleanupMethod.Body.Instructions[0], (lastInstr = proc.Create(OpCodes.Ldarg_0))); proc.InsertAfter(lastInstr, proc.Create(OpCodes.Call, module.Import(onGameDisable))); } }
public void Patch() { HelperClass.SetLogger(null); //foreach RPC method in ConnectionManager foreach (MethodDefinition mdef in HelperClass.findMembers<MethodDefinition>(module, "ConnectionManager", HelperClass.MemberCustomAttributeComparer<MethodDefinition>("UnityEngine.RPC"))) { if (mdef.HasBody) { Mono.Collections.Generic.Collection<ParameterDefinition> _params = mdef.Parameters; if (_params.Count == 0 || !_params[_params.Count - 1].ParameterType.FullName.Equals("UnityEngine.NetworkMessageInfo")) { ParameterDefinition messageInfoPardef = new ParameterDefinition("_messageInfo", ParameterAttributes.None, mdef.DeclaringType.Module.Import(unityModule.GetType("UnityEngine.NetworkMessageInfo"))); mdef.Parameters.Add(messageInfoPardef); } ILProcessor proc = mdef.Body.GetILProcessor(); List<Instruction[]> argLoaders = new List<Instruction[]>(); argLoaders.Add(new Instruction[] { proc.Create(OpCodes.Ldc_I4_0), proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Boolean"))), }); argLoaders.Add(new Instruction[] { proc.Create(OpCodes.Ldstr, mdef.Name), }); List<Instruction> instrTmp = new List<Instruction>(); for (int i = 0; i < _params.Count; i++) { ParameterDefinition param = _params[i]; instrTmp.Clear(); instrTmp.Add(proc.Create(OpCodes.Ldarg, param)); if (param.ParameterType.IsValueType) { instrTmp.Add(proc.Create(OpCodes.Box, module.Import(param.ParameterType))); } argLoaders.Add(instrTmp.ToArray()); } List<Instruction> hook = HookHelper.Instance.prepareEventHook(mdef, "RPCEvent", argLoaders.ToArray()); for (int i = 0; i < _params.Count; i++) { ParameterDefinition param = _params[i]; hook.Add(proc.Create(OpCodes.Dup)); hook.Add(proc.Create(OpCodes.Ldc_I4, i + 2)); hook.Add(proc.Create(OpCodes.Ldelem_Ref)); if (param.ParameterType.IsValueType) { hook.Add(proc.Create(OpCodes.Unbox_Any, module.Import(param.ParameterType))); } else { hook.Add(proc.Create(OpCodes.Castclass, module.Import(param.ParameterType))); } hook.Add(proc.Create(OpCodes.Starg, param)); } hook.Add(proc.Create(OpCodes.Ldc_I4_0)); hook.Add(proc.Create(OpCodes.Ldelem_Ref)); hook.Add(proc.Create(OpCodes.Unbox_Any, module.Import(mscorlibModule.GetType("System.Boolean")))); hook.Add(proc.Create(OpCodes.Brfalse, mdef.Body.Instructions[0])); hook.Add(proc.Create(OpCodes.Ret)); HookHelper.insertAt(mdef.Body, 0, hook.ToArray()); } } }
private IInstructionGenerator ParseOpcode(XmlNode opNode) { XmlNode opcodeNode = opNode.Attributes["name"]; if (opcodeNode == null) { throw new ArgumentException("xmlpatchers.xml : An opcode node doesn't define a name attribute!"); } string opcodeName = opcodeNode.Value.ToLower(); if (!opCodeList.ContainsKey(opcodeName)) { throw new ArgumentException("xmlpatchers.xml : An invalid opcode was passed (" + opcodeNode.Value + ")!"); } string opType = opNode.Attributes.ValueOf("opType").ToLower(); string op = opNode.Attributes.ValueOf("op"); OpCode opcode = opCodeList[opcodeName]; switch (opType) { case "sbyte": return(new InstructionGenerator(opcode, SByte.Parse(op), (_p, _i, _opcode, _operand) => _p.Create(opcode, (SByte)_operand))); case "byte": return(new InstructionGenerator(opcode, Byte.Parse(op), (_p, _i, _opcode, _operand) => _p.Create(opcode, (Byte)_operand))); case "int32": case "int": return(new InstructionGenerator(opcode, Int32.Parse(op), (_p, _i, _opcode, _operand) => _p.Create(opcode, (Int32)_operand))); case "int64": case "long": return(new InstructionGenerator(opcode, Int64.Parse(op), (_p, _i, _opcode, _operand) => _p.Create(opcode, (Int64)_operand))); case "single": case "float": return(new InstructionGenerator(opcode, Single.Parse(op), (_p, _i, _opcode, _operand) => _p.Create(opcode, (Single)_operand))); case "double": return(new InstructionGenerator(opcode, Double.Parse(op), (_p, _i, _opcode, _operand) => _p.Create(opcode, (Double)_operand))); case "string": return(new InstructionGenerator(opcode, op, (_p, _i, _opcode, _operand) => _p.Create(opcode, (string)_operand))); case "tref": { TypeDefinition typeDef = findType(op); if (typeDef == null) { throw new ArgumentException("xmlpatchers.xml : Unable to find type \"" + op + "\"!"); } return(new InstructionGenerator(opcode, module.Import(typeDef), (_p, _i, _opcode, _operand) => _p.Create(opcode, (TypeReference)_operand))); } case "fref": { string[] opSplit = op.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); if (opSplit.Length != 2) { throw new ArgumentException("xmlpatchers.xml : A fref operand has an illegal count of semicolons!"); } TypeDefinition typeDef = findType(opSplit[0]); if (typeDef == null) { throw new ArgumentException("xmlpatchers.xml : Unable to find type \"" + opSplit[0] + "\"!"); } HelperClass.SetLogger(null); FieldDefinition fdef = HelperClass.findMember <FieldDefinition>(module, typeDef, false, HelperClass.MemberNameComparer <FieldDefinition>(opSplit[1])); HelperClass.SetLogger(logger); if (fdef == null) { throw new ArgumentException("xmlpatchers.xml : Unable to find field \"" + (opSplit[0] + "." + opSplit[1]) + "\"!"); } return(new InstructionGenerator(opcode, module.Import(fdef), (_p, _i, _opcode, _operand) => _p.Create(opcode, (FieldReference)_operand))); } case "mref": { string[] opSplit = op.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); if (opSplit.Length != 2 && opSplit.Length != 3) { throw new ArgumentException("xmlpatchers.xml : A fref operand has an illegal count of semicolons!"); } TypeDefinition typeDef = findType(opSplit[0]); if (typeDef == null) { throw new ArgumentException("xmlpatchers.xml : Unable to find type \"" + opSplit[0] + "\"!"); } string[] _params = (opSplit.Length == 2) ? null : opSplit[2].Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); //I don't always use 'var' but when I do, it would be odd not to. var methodComparers = new List <HelperClass.GenericFuncContainer <MethodDefinition, bool> >(opSplit.Length - 1); methodComparers.Add(HelperClass.MemberNameComparer <MethodDefinition>(opSplit[1])); if (_params != null) { methodComparers.Add(HelperClass.MethodParametersComparer(_params)); } HelperClass.SetLogger(null); MethodDefinition mdef = HelperClass.findMember <MethodDefinition>(module, typeDef, false, methodComparers.ToArray()); HelperClass.SetLogger(logger); if (mdef == null) { throw new ArgumentException("xmlpatchers.xml : Unable to find method \"" + (opSplit[0] + "." + opSplit[1]) + "\"!"); } return(new InstructionGenerator(opcode, module.Import(mdef), (_p, _i, _opcode, _operand) => _p.Create(opcode, (MethodReference)_operand))); } case "instref": return(new InstructionGenerator(opcode, Int32.Parse(op), (_p, _i, _opcode, _operand) => { int _targetIndex = (int)_operand; if (_targetIndex >= _i.Count) { return null; } return _p.Create(_opcode, _i[_targetIndex]); })); case "none": case "": return(new NoOPInstructionGenerator(opcode)); default: throw new ArgumentException("xmlpatchers.xml : Unknown operand type \"" + opType + "\"!"); } }
public void Patch() { HelperClass.SetLogger(null); //HelperClass.OnError would otherwise show errors if a NetPackage class doesn't override Process,Read or Write TypeDefinition[] netPackageTypes = HelperClass.findTypes(module, HelperClass.CombinedComparer <MethodDefinition>( HelperClass.MemberNameComparer <MethodDefinition>("GetPackageType"), HelperClass.MethodReturnTypeComparer("PackageType"), HelperClass.MethodNegAttributeComparer(MethodAttributes.Abstract)) ); if (netPackageTypes == null || netPackageTypes.Length == 0) { logger.Error("Unable to find any NetPackage classes!"); return; } foreach (TypeDefinition curPackageType in netPackageTypes) { MethodDefinition processMethod = HelperClass.findMember <MethodDefinition>(module, curPackageType, false, HelperClass.MemberNameComparer <MethodDefinition>("Process"), HelperClass.MethodReturnTypeComparer("System.Void"), HelperClass.MethodParametersComparer("World", "INetConnectionCallbacks")); if (processMethod != null) { MethodBody body = processMethod.Body; if (body != null) { ILProcessor proc = body.GetILProcessor(); List <Instruction> eventHook = HookHelper.Instance.prepareEventHook(processMethod, "ProcessPacketEvent", new Instruction[][] { new Instruction[] { proc.Create(OpCodes.Ldarg_0), }, new Instruction[] { proc.Create(OpCodes.Ldc_I4_0), proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Boolean"))), }, new Instruction[] { proc.Create(OpCodes.Ldarg_1), }, new Instruction[] { proc.Create(OpCodes.Ldarg_2), }, } ); eventHook.Add(proc.Create(OpCodes.Ldc_I4_1)); eventHook.Add(proc.Create(OpCodes.Ldelem_Ref)); eventHook.Add(proc.Create(OpCodes.Unbox_Any, module.Import(mscorlibModule.GetType("System.Boolean")))); eventHook.Add(proc.Create(OpCodes.Brfalse, body.Instructions[0])); eventHook.Add(proc.Create(OpCodes.Ret)); HookHelper.insertAt(body, 0, eventHook.ToArray()); } } MethodDefinition readMethod = HelperClass.findMember <MethodDefinition>(module, curPackageType, false, HelperClass.MemberNameComparer <MethodDefinition>("Read"), HelperClass.MethodReturnTypeComparer("System.Void"), HelperClass.MethodParametersComparer("System.IO.BinaryReader")); if (readMethod != null) { MethodBody body = readMethod.Body; if (body != null) { ILProcessor proc = body.GetILProcessor(); List <Instruction> eventHook = HookHelper.Instance.prepareEventHook(readMethod, "ReadPacketFromBufEvent", new Instruction[][] { new Instruction[] { proc.Create(OpCodes.Ldarg_0), }, } ); eventHook.Add(proc.Create(OpCodes.Pop)); HookHelper.insertAt(body, body.Instructions.Count - 1, eventHook.ToArray()); } } MethodDefinition writeMethod = HelperClass.findMember <MethodDefinition>(module, curPackageType, false, HelperClass.MemberNameComparer <MethodDefinition>("Write"), HelperClass.MethodReturnTypeComparer("System.Void"), HelperClass.MethodParametersComparer("System.IO.BinaryWriter")); if (writeMethod != null) { MethodBody body = writeMethod.Body; if (body != null) { ILProcessor proc = body.GetILProcessor(); List <Instruction> eventHook = HookHelper.Instance.prepareEventHook(writeMethod, "WritePacketToBufEvent", new Instruction[][] { new Instruction[] { proc.Create(OpCodes.Ldarg_0), }, new Instruction[] { proc.Create(OpCodes.Ldc_I4_0), proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Boolean"))), }, } ); eventHook.Add(proc.Create(OpCodes.Ldc_I4_1)); eventHook.Add(proc.Create(OpCodes.Ldelem_Ref)); eventHook.Add(proc.Create(OpCodes.Unbox_Any, module.Import(mscorlibModule.GetType("System.Boolean")))); eventHook.Add(proc.Create(OpCodes.Brfalse, body.Instructions[0])); eventHook.Add(proc.Create(OpCodes.Ret)); HookHelper.insertAt(body, 0, eventHook.ToArray()); } } } }