private void JumpToEdge(DirectCallMethod.Node node) { Instruction instruction = this.AddInstruction(OpCodes.Bne_Un, this.body.Instructions[1]); this.jumpToEdgePlaceholderTargets[instruction] = node; }
public DirectCallMethod(ModuleDefinition module, TypeDefinition type) { DirectCallMethod.Node node; Func <MethodDefinition, bool> func = null; DirectCallMethod directCallMethod = this; this.module = module; this.type = type; this.getLength = module.Import(typeof(string).GetMethod("get_Length", new Type[0])); this.getChars = module.Import(typeof(string).GetMethod("get_Chars", new Type[] { typeof(int) })); this.isNullOrEmpty = module.Import(typeof(string).GetMethod("IsNullOrEmpty", new Type[] { typeof(string) })); this.stringEquals = module.Import(typeof(string).GetMethod("Equals", new Type[] { typeof(string) })); AssemblyDefinition assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.Combine(Interface.Oxide.ExtensionDirectory, "Oxide.CSharp.dll")); ModuleDefinition mainModule = assemblyDefinition.MainModule; TypeDefinition typeDefinition = module.Import(assemblyDefinition.MainModule.GetType("Oxide.Plugins.CSharpPlugin")).Resolve(); MethodDefinition methodDefinition = module.Import(typeDefinition.Methods.First <MethodDefinition>((MethodDefinition method) => method.Name == "DirectCallHook")).Resolve(); this.method = new MethodDefinition(methodDefinition.Name, methodDefinition.Attributes, mainModule.Import(methodDefinition.ReturnType)) { DeclaringType = type }; foreach (ParameterDefinition parameter in methodDefinition.Parameters) { ParameterDefinition parameterDefinition = new ParameterDefinition(parameter.Name, parameter.Attributes, mainModule.Import(parameter.ParameterType)) { IsOut = parameter.IsOut, Constant = parameter.Constant, MarshalInfo = parameter.MarshalInfo, IsReturnValue = parameter.IsReturnValue }; foreach (CustomAttribute customAttribute in parameter.CustomAttributes) { parameterDefinition.CustomAttributes.Add(new CustomAttribute(module.Import(customAttribute.Constructor))); } this.method.Parameters.Add(parameterDefinition); } foreach (CustomAttribute customAttribute1 in methodDefinition.CustomAttributes) { this.method.CustomAttributes.Add(new CustomAttribute(module.Import(customAttribute1.Constructor))); } this.method.ImplAttributes = methodDefinition.ImplAttributes; this.method.SemanticsAttributes = methodDefinition.SemanticsAttributes; MethodDefinition attributes = this.method; attributes.Attributes = attributes.Attributes & (MethodAttributes.MemberAccessMask | MethodAttributes.Private | MethodAttributes.FamANDAssem | MethodAttributes.Assembly | MethodAttributes.Family | MethodAttributes.FamORAssem | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Abstract | MethodAttributes.SpecialName | MethodAttributes.PInvokeImpl | MethodAttributes.UnmanagedExport | MethodAttributes.RTSpecialName | MethodAttributes.HasSecurity | MethodAttributes.RequireSecObject); MethodDefinition attributes1 = this.method; attributes1.Attributes = attributes1.Attributes | MethodAttributes.CompilerControlled; this.body = new MethodBody(this.method); this.body.SimplifyMacros(); this.method.Body = this.body; type.Methods.Add(this.method); this.body.Variables.Add(new VariableDefinition("name_size", module.TypeSystem.Int32)); this.body.Variables.Add(new VariableDefinition("i", module.TypeSystem.Int32)); this.AddInstruction(OpCodes.Ldarg_2); this.AddInstruction(OpCodes.Ldnull); this.AddInstruction(OpCodes.Stind_Ref); this.AddInstruction(OpCodes.Ldarg_1); this.AddInstruction(OpCodes.Call, this.isNullOrEmpty); Instruction instruction = this.AddInstruction(OpCodes.Brfalse, this.body.Instructions[0]); this.Return(false); instruction.Operand = this.AddInstruction(OpCodes.Ldarg_1); this.AddInstruction(OpCodes.Callvirt, this.getLength); this.AddInstruction(OpCodes.Stloc_0); this.AddInstruction(OpCodes.Ldc_I4_0); this.AddInstruction(OpCodes.Stloc_1); Collection <MethodDefinition> methods = type.Methods; Func <MethodDefinition, bool> func1 = func; if (func1 == null) { Func <MethodDefinition, bool> isStatic = (MethodDefinition m) => { if (m.IsStatic || !m.IsPrivate && !directCallMethod.IsHookMethod(m) || m.HasGenericParameters || m.ReturnType.IsGenericParameter || m.DeclaringType != type || m.IsSetter) { return(false); } return(!m.IsGetter); }; Func <MethodDefinition, bool> func2 = isStatic; func = isStatic; func1 = func2; } foreach (MethodDefinition methodDefinition1 in methods.Where <MethodDefinition>(func1)) { if (methodDefinition1.Name.Contains("<")) { continue; } string name = methodDefinition1.Name; if (methodDefinition1.Parameters.Count > 0) { name = string.Concat(name, "(", string.Join(", ", ( from x in methodDefinition1.Parameters select x.ParameterType.ToString().Replace("/", "+").Replace("<", "[").Replace(">", "]")).ToArray <string>()), ")"); } if (this.hookMethods.ContainsKey(name)) { continue; } this.hookMethods[name] = methodDefinition1; } DirectCallMethod.Node node1 = new DirectCallMethod.Node(); foreach (string key in this.hookMethods.Keys) { DirectCallMethod.Node node2 = node1; for (int i = 1; i <= key.Length; i++) { char chr = key[i - 1]; if (!node2.Edges.TryGetValue(chr, out node)) { node = new DirectCallMethod.Node() { Parent = node2, Char = chr }; node2.Edges[chr] = node; } if (i == key.Length) { node.Name = key; } node2 = node; } } int num = 1; foreach (char key1 in node1.Edges.Keys) { int num1 = num; num = num1 + 1; this.BuildNode(node1.Edges[key1], num1); } this.endInstruction = this.Return(false); foreach (Instruction firstInstruction in this.jumpToEdgePlaceholderTargets.Keys) { firstInstruction.Operand = this.jumpToEdgePlaceholderTargets[firstInstruction].FirstInstruction; } foreach (Instruction jumpToEndPlaceholder in this.jumpToEndPlaceholders) { jumpToEndPlaceholder.Operand = this.endInstruction; } this.body.OptimizeMacros(); }
private void BuildNode(DirectCallMethod.Node node, int edge_number) { if (edge_number == 1) { node.FirstInstruction = this.AddInstruction(OpCodes.Ldloc_1); this.AddInstruction(OpCodes.Ldloc_0); this.jumpToEndPlaceholders.Add(this.AddInstruction(OpCodes.Bge, this.body.Instructions[0])); } if (edge_number != 1) { node.FirstInstruction = this.AddInstruction(OpCodes.Ldarg_1); } else { this.AddInstruction(OpCodes.Ldarg_1); } this.AddInstruction(OpCodes.Ldloc_1); this.AddInstruction(OpCodes.Callvirt, this.getChars); this.AddInstruction(this.Ldc_I4_n(node.Char)); if (node.Parent.Edges.Count <= edge_number) { this.JumpToEnd(); } else { this.JumpToEdge(node.Parent.Edges.Values.ElementAt <DirectCallMethod.Node>(edge_number)); } if (node.Edges.Count == 1 && node.Name == null) { DirectCallMethod.Node node1 = node; while (node1.Edges.Count == 1 && node1.Name == null) { node1 = node1.Edges.Values.First <DirectCallMethod.Node>(); } if (node1.Edges.Count == 0 && node1.Name != null) { this.AddInstruction(OpCodes.Ldarg_1); this.AddInstruction(Instruction.Create(OpCodes.Ldstr, node1.Name)); this.AddInstruction(OpCodes.Callvirt, this.stringEquals); this.jumpToEndPlaceholders.Add(this.AddInstruction(OpCodes.Brfalse, this.body.Instructions[0])); this.CallMethod(this.hookMethods[node1.Name]); this.Return(true); return; } } this.AddInstruction(OpCodes.Ldloc_1); this.AddInstruction(OpCodes.Ldc_I4_1); this.AddInstruction(OpCodes.Add); this.AddInstruction(OpCodes.Stloc_1); if (node.Name != null) { this.AddInstruction(OpCodes.Ldloc_1); this.AddInstruction(OpCodes.Ldloc_0); if (node.Edges.Count <= 0) { this.JumpToEnd(); } else { this.JumpToEdge(node.Edges.Values.First <DirectCallMethod.Node>()); } this.CallMethod(this.hookMethods[node.Name]); this.Return(true); } int num = 1; foreach (char key in node.Edges.Keys) { int num1 = num; num = num1 + 1; this.BuildNode(node.Edges[key], num1); } }