protected static string _Format(string message, IMetadataTokenProvider mtp, IMetadataTokenProvider context) { if (mtp == null && context == null) { return(message); } StringBuilder builder = new StringBuilder(message); builder.Append(" "); if (mtp != null) { builder.Append(mtp.ToString()); } if (context != null) { builder.Append(" "); } if (context != null) { builder.Append("(context: ").Append(context.ToString()).Append(")"); } return(builder.ToString()); }
void CreateTargetDetails(IMetadataTokenProvider target) { AssemblyDefinition assembly = target.GetAssembly(); writer.WriteAttributeString("Name", target.ToString()); writer.WriteAttributeString("Assembly", assembly == null ? AssemblySet : assembly.Name.FullName); }
static string GetKey(MethodDefinition caller, MethodDefinition callee, Instruction ins) { if (callee.IsStatic) { return(callee.GetFullName()); } IMetadataTokenProvider chain = callee; Instruction instance = ins.TraceBack(caller); StringBuilder sb = new StringBuilder(); while (instance != null) { MemberReference mr = (chain as MemberReference); if (mr == null) { sb.Append(chain.ToString()); // ?? "null") } else { sb.Append(mr.GetFullName()); } sb.Append('.'); chain = (instance.Operand as IMetadataTokenProvider); if (chain == null) { sb.Append(instance.GetOperand(caller)); break; } instance = instance.TraceBack(caller); } if (chain != null) { sb.Append(chain.ToString()); } return(sb.ToString()); }
/// <summary> /// Creates the suitable importer for the givem member /// </summary> /// <param name="member"></param> /// <returns></returns> public MemberImporter CreateImporter(IMetadataTokenProvider member) { //Switches the token type switch (member.MetadataToken.TokenType) { case TokenType.TypeDef: return(new TypeImporter(member, Destination, this)); case TokenType.Field: return(new FieldImporter(member, Destination, this)); case TokenType.Method: return(new MethodImporter(member, Destination, this)); case TokenType.Property: return(new PropertyImporter(member, Destination, this)); case TokenType.Event: return(new EventImporter(member, Destination, this)); default: throw new ArgumentException("Cannot create an importer for " + member.ToString()); } }
private void PatchAssembly(Action <byte[]> callback) { if (isPatching) { Interface.Oxide.LogWarning("Already patching plugin assembly: {0} (ignoring)", PluginNames.ToSentence()); //RemoteLogger.Warning($"Already patching plugin assembly: {PluginNames.ToSentence()}"); return; } float startedAt = Interface.Oxide.Now; isPatching = true; ThreadPool.QueueUserWorkItem(_ => { try { AssemblyDefinition definition; using (MemoryStream stream = new MemoryStream(RawAssembly)) { definition = AssemblyDefinition.ReadAssembly(stream); } ConstructorInfo exceptionConstructor = typeof(UnauthorizedAccessException).GetConstructor(new[] { typeof(string) }); MethodReference securityException = definition.MainModule.Import(exceptionConstructor); Action <TypeDefinition> patchModuleType = null; patchModuleType = type => { foreach (MethodDefinition method in type.Methods) { bool changedMethod = false; if (method.Body == null) { if (method.HasPInvokeInfo && CSharpExtension.SandboxEnabled) { method.Attributes &= ~MethodAttributes.PInvokeImpl; MethodBody body = new MethodBody(method); body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, "PInvoke access is restricted, you are not allowed to use PInvoke")); body.Instructions.Add(Instruction.Create(OpCodes.Newobj, securityException)); body.Instructions.Add(Instruction.Create(OpCodes.Throw)); method.Body = body; } } else { bool replacedMethod = false; foreach (VariableDefinition variable in method.Body.Variables) { if (!IsNamespaceBlacklisted(variable.VariableType.FullName)) { continue; } MethodBody body = new MethodBody(method); body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {variable.VariableType.FullName}")); body.Instructions.Add(Instruction.Create(OpCodes.Newobj, securityException)); body.Instructions.Add(Instruction.Create(OpCodes.Throw)); method.Body = body; replacedMethod = true; break; } if (replacedMethod) { continue; } References::Mono.Collections.Generic.Collection <Instruction> instructions = method.Body.Instructions; ILProcessor ilProcessor = method.Body.GetILProcessor(); Instruction first = instructions.First(); int i = 0; while (i < instructions.Count && !changedMethod) { Instruction instruction = instructions[i]; if (instruction.OpCode == OpCodes.Ldtoken) { IMetadataTokenProvider operand = instruction.Operand as IMetadataTokenProvider; string token = operand?.ToString(); if (IsNamespaceBlacklisted(token)) { ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {token}")); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw)); changedMethod = true; } } else if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Calli || instruction.OpCode == OpCodes.Callvirt || instruction.OpCode == OpCodes.Ldftn || instruction.OpCode == OpCodes.Newobj) { MethodReference methodCall = instruction.Operand as MethodReference; string fullNamespace = methodCall?.DeclaringType.FullName; if ((fullNamespace == "System.Type" && methodCall.Name == "GetType") || IsNamespaceBlacklisted(fullNamespace)) { ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {fullNamespace}")); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw)); changedMethod = true; } } else if (instruction.OpCode == OpCodes.Ldfld) { FieldReference fieldType = instruction.Operand as FieldReference; string fullNamespace = fieldType?.FieldType.FullName; if (IsNamespaceBlacklisted(fullNamespace)) { ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {fullNamespace}")); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException)); ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw)); changedMethod = true; } } i++; } } if (changedMethod) { method.Body?.OptimizeMacros(); /*//Interface.Oxide.LogDebug("Updating {0} instruction offsets: {1}", instructions.Count, method.FullName); * int curoffset = 0; * for (var i = 0; i < instructions.Count; i++) * { * var instruction = instructions[i]; * instruction.Previous = (i == 0) ? null : instructions[i - 1]; * instruction.Next = (i == instructions.Count - 1) ? null : instructions[i + 1]; * instruction.Offset = curoffset; * curoffset += instruction.GetSize(); * //Interface.Oxide.LogDebug(" {0}", instruction.ToString()); * }*/ } } foreach (TypeDefinition nestedType in type.NestedTypes) { patchModuleType(nestedType); } }; foreach (TypeDefinition type in definition.MainModule.Types) { patchModuleType(type); if (IsCompilerGenerated(type)) { continue; } if (type.Namespace == "Oxide.Plugins") { if (PluginNames.Contains(type.Name)) { MethodDefinition constructor = type.Methods.FirstOrDefault( m => !m.IsStatic && m.IsConstructor && !m.HasParameters && !m.IsPublic); if (constructor != null) { CompilablePlugin plugin = CompilablePlugins.SingleOrDefault(p => p.Name == type.Name); if (plugin != null) { plugin.CompilerErrors = "Primary constructor in main class must be public"; } } else { new DirectCallMethod(definition.MainModule, type); } } else { Interface.Oxide.LogWarning(PluginNames.Length == 1 ? $"{PluginNames[0]} has polluted the global namespace by defining {type.Name}" : $"A plugin has polluted the global namespace by defining {type.Name}"); //RemoteLogger.Info($"A plugin has polluted the global namespace by defining {type.Name}: {PluginNames.ToSentence()}"); } } else if (type.FullName != "<Module>") { if (!PluginNames.Any(plugin => type.FullName.StartsWith($"Oxide.Plugins.{plugin}"))) { Interface.Oxide.LogWarning(PluginNames.Length == 1 ? $"{PluginNames[0]} has polluted the global namespace by defining {type.FullName}" : $"A plugin has polluted the global namespace by defining {type.FullName}"); } } } // TODO: Why is there no error on boot using this? foreach (TypeDefinition type in definition.MainModule.Types) { if (type.Namespace != "Oxide.Plugins" || !PluginNames.Contains(type.Name)) { continue; } foreach (MethodDefinition m in type.Methods.Where(m => !m.IsStatic && !m.HasGenericParameters && !m.ReturnType.IsGenericParameter && !m.IsSetter && !m.IsGetter)) { foreach (ParameterDefinition parameter in m.Parameters) { foreach (CustomAttribute attribute in parameter.CustomAttributes) { //Interface.Oxide.LogInfo($"{m.FullName} - {parameter.Name} - {attribute.Constructor.FullName}"); } } } } using (MemoryStream stream = new MemoryStream()) { definition.Write(stream); PatchedAssembly = stream.ToArray(); } Interface.Oxide.NextTick(() => { isPatching = false; //Interface.Oxide.LogDebug("Patching {0} assembly took {1:0.00} ms", ScriptName, Interface.Oxide.Now - startedAt); callback(PatchedAssembly); }); } catch (Exception ex) { Interface.Oxide.NextTick(() => { isPatching = false; Interface.Oxide.LogException($"Exception while patching: {PluginNames.ToSentence()}", ex); //RemoteLogger.Exception($"Exception while patching: {PluginNames.ToSentence()}", ex); callback(null); }); } }); }
void CreateTargetDetails (IMetadataTokenProvider target) { AssemblyDefinition assembly = target.GetAssembly (); writer.WriteAttributeString ("Name", target.ToString ()); writer.WriteAttributeString ("Assembly", assembly == null ? AssemblySet : assembly.Name.FullName); }
private void ResolveMethod (IMetadataTokenProvider method) { HashSet<string> rules; string m = method.ToString (); m = m.Substring (m.IndexOf (' ') + 1); if (targets.TryGetValue (m, out rules)) Add (method, rules); }
/// <summary> /// Creates the suitable importer for the givem member /// </summary> /// <param name="member"></param> /// <returns></returns> public MemberImporter CreateImporter(IMetadataTokenProvider member) { //Switches the token type switch (member.MetadataToken.TokenType) { case TokenType.TypeDef: return new TypeImporter(member, Destination, this); case TokenType.Field: return new FieldImporter(member, Destination, this); case TokenType.Method: return new MethodImporter(member, Destination, this); case TokenType.Property: return new PropertyImporter(member, Destination, this); case TokenType.Event: return new EventImporter(member, Destination, this); default: throw new ArgumentException("Cannot create an importer for " + member.ToString()); } }
private void PatchAssembly(Action <byte[]> callback) { Action action1 = null; if (this.isPatching) { Interface.Oxide.LogWarning("Already patching plugin assembly: {0} (ignoring)", new object[] { this.PluginNames.ToSentence <string>() }); return; } float now = Interface.Oxide.Now; this.isPatching = true; ThreadPool.QueueUserWorkItem((object _) => { AssemblyDefinition assemblyDefinition; try { using (MemoryStream memoryStream = new MemoryStream(this.RawAssembly)) { assemblyDefinition = AssemblyDefinition.ReadAssembly(memoryStream); } ConstructorInfo constructor = typeof(UnauthorizedAccessException).GetConstructor(new Type[] { typeof(string) }); MethodReference methodReference1 = assemblyDefinition.MainModule.Import(constructor); Action <TypeDefinition> methods = null; methods = (TypeDefinition type) => { string fullName; string str; foreach (MethodDefinition method in type.Methods) { bool flag = false; if (method.Body != null) { bool flag1 = false; foreach (VariableDefinition variable in method.Body.Variables) { if (!CompiledAssembly.IsNamespaceBlacklisted(variable.VariableType.FullName)) { continue; } Mono.Cecil.Cil.MethodBody methodBody = new Mono.Cecil.Cil.MethodBody(method); methodBody.Instructions.Add(Instruction.Create(OpCodes.Ldstr, string.Concat("System access is restricted, you are not allowed to use ", variable.VariableType.FullName))); methodBody.Instructions.Add(Instruction.Create(OpCodes.Newobj, methodReference1)); methodBody.Instructions.Add(Instruction.Create(OpCodes.Throw)); method.Body = methodBody; flag1 = true; break; } if (flag1) { continue; } Collection <Instruction> instructions = method.Body.Instructions; ILProcessor lProcessor = method.Body.GetILProcessor(); Instruction instruction = instructions.First <Instruction>(); for (int i = 0; i < instructions.Count && !flag; i++) { Instruction item = instructions[i]; if (item.OpCode == OpCodes.Ldtoken) { IMetadataTokenProvider operand = item.Operand as IMetadataTokenProvider; str = (operand != null ? operand.ToString() : null); string str1 = str; if (CompiledAssembly.IsNamespaceBlacklisted(str1)) { lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Ldstr, string.Concat("System access is restricted, you are not allowed to use ", str1))); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Newobj, methodReference1)); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Throw)); flag = true; } } else if (item.OpCode == OpCodes.Call || item.OpCode == OpCodes.Calli || item.OpCode == OpCodes.Callvirt || item.OpCode == OpCodes.Ldftn) { MethodReference methodReference = item.Operand as MethodReference; string str2 = (methodReference != null ? methodReference.DeclaringType.FullName : null); if (str2 == "System.Type" && methodReference.Name == "GetType" || CompiledAssembly.IsNamespaceBlacklisted(str2)) { lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Ldstr, string.Concat("System access is restricted, you are not allowed to use ", str2))); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Newobj, methodReference1)); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Throw)); flag = true; } } else if (item.OpCode == OpCodes.Ldfld) { FieldReference fieldReference = item.Operand as FieldReference; fullName = (fieldReference != null ? fieldReference.FieldType.FullName : null); string str3 = fullName; if (CompiledAssembly.IsNamespaceBlacklisted(str3)) { lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Ldstr, string.Concat("System access is restricted, you are not allowed to use ", str3))); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Newobj, methodReference1)); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Throw)); flag = true; } } } } else if (method.HasPInvokeInfo) { MethodDefinition attributes = method; attributes.Attributes = attributes.Attributes & (Mono.Cecil.MethodAttributes.MemberAccessMask | Mono.Cecil.MethodAttributes.Private | Mono.Cecil.MethodAttributes.FamANDAssem | Mono.Cecil.MethodAttributes.Assembly | Mono.Cecil.MethodAttributes.Family | Mono.Cecil.MethodAttributes.FamORAssem | Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.Static | Mono.Cecil.MethodAttributes.Final | Mono.Cecil.MethodAttributes.Virtual | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.VtableLayoutMask | Mono.Cecil.MethodAttributes.NewSlot | Mono.Cecil.MethodAttributes.CheckAccessOnOverride | Mono.Cecil.MethodAttributes.Abstract | Mono.Cecil.MethodAttributes.SpecialName | Mono.Cecil.MethodAttributes.UnmanagedExport | Mono.Cecil.MethodAttributes.RTSpecialName | Mono.Cecil.MethodAttributes.HasSecurity | Mono.Cecil.MethodAttributes.RequireSecObject); Mono.Cecil.Cil.MethodBody methodBody1 = new Mono.Cecil.Cil.MethodBody(method); methodBody1.Instructions.Add(Instruction.Create(OpCodes.Ldstr, "PInvoke access is restricted, you are not allowed to use PInvoke")); methodBody1.Instructions.Add(Instruction.Create(OpCodes.Newobj, methodReference1)); methodBody1.Instructions.Add(Instruction.Create(OpCodes.Throw)); method.Body = methodBody1; } if (!flag) { continue; } Mono.Cecil.Cil.MethodBody body = method.Body; if (body != null) { body.OptimizeMacros(); } else { } } foreach (TypeDefinition nestedType in type.NestedTypes) { methods(nestedType); } }; foreach (TypeDefinition typeDefinition in assemblyDefinition.MainModule.Types) { methods(typeDefinition); if (this.IsCompilerGenerated(typeDefinition)) { continue; } if (typeDefinition.Namespace != "Oxide.Plugins") { if (!(typeDefinition.FullName != "<Module>") || this.PluginNames.Any <string>((string plugin) => typeDefinition.FullName.StartsWith(string.Concat("Oxide.Plugins.", plugin)))) { continue; } Interface.Oxide.LogWarning(((int)this.PluginNames.Length == 1 ? string.Concat(this.PluginNames[0], " has polluted the global namespace by defining ", typeDefinition.FullName) : string.Concat("A plugin has polluted the global namespace by defining ", typeDefinition.FullName)), Array.Empty <object>()); } else if (!this.PluginNames.Contains <string>(typeDefinition.Name)) { Interface.Oxide.LogWarning(((int)this.PluginNames.Length == 1 ? string.Concat(this.PluginNames[0], " has polluted the global namespace by defining ", typeDefinition.Name) : string.Concat("A plugin has polluted the global namespace by defining ", typeDefinition.Name)), Array.Empty <object>()); } else { Collection <MethodDefinition> methodDefinitions = typeDefinition.Methods; Func <MethodDefinition, bool> u003cu003e9_204 = CompiledAssembly.< > c.< > 9__20_4; if (u003cu003e9_204 == null) { u003cu003e9_204 = (MethodDefinition m) => { if (m.IsStatic || !m.IsConstructor || m.HasParameters) { return(false); } return(!m.IsPublic); }; CompiledAssembly.< > c.< > 9__20_4 = u003cu003e9_204; } if (methodDefinitions.FirstOrDefault <MethodDefinition>(u003cu003e9_204) == null) { DirectCallMethod directCallMethod = new DirectCallMethod(assemblyDefinition.MainModule, typeDefinition); } else { CompilablePlugin compilablePlugin = this.CompilablePlugins.SingleOrDefault <CompilablePlugin>((CompilablePlugin p) => p.Name == typeDefinition.Name); if (compilablePlugin == null) { continue; } compilablePlugin.CompilerErrors = "Primary constructor in main class must be public"; } } } foreach (TypeDefinition typeDefinition1 in assemblyDefinition.MainModule.Types) { if (typeDefinition1.Namespace != "Oxide.Plugins" || !this.PluginNames.Contains <string>(typeDefinition1.Name)) { continue; } Collection <MethodDefinition> methods1 = typeDefinition1.Methods; Func <MethodDefinition, bool> u003cu003e9_206 = CompiledAssembly.< > c.< > 9__20_6; if (u003cu003e9_206 == null) { u003cu003e9_206 = (MethodDefinition m) => { if (m.IsStatic || m.HasGenericParameters || m.ReturnType.IsGenericParameter || m.IsSetter) { return(false); } return(!m.IsGetter); }; CompiledAssembly.< > c.< > 9__20_6 = u003cu003e9_206; } foreach (MethodDefinition methodDefinition in methods1.Where <MethodDefinition>(u003cu003e9_206)) { foreach (ParameterDefinition parameter in methodDefinition.Parameters) { foreach (CustomAttribute customAttribute in parameter.CustomAttributes) { } } } } using (MemoryStream memoryStream1 = new MemoryStream()) { assemblyDefinition.Write(memoryStream1); this.PatchedAssembly = memoryStream1.ToArray(); } OxideMod oxide = Interface.Oxide; Action u003cu003e9_2 = action1; if (u003cu003e9_2 == null) { Action u003cu003e4_this = () => { this.isPatching = false; callback(this.PatchedAssembly); }; Action action = u003cu003e4_this; action1 = u003cu003e4_this; u003cu003e9_2 = action; } oxide.NextTick(u003cu003e9_2); } catch (Exception exception1) { Exception exception = exception1; Interface.Oxide.NextTick(() => { this.isPatching = false; Interface.Oxide.LogException(string.Concat("Exception while patching: ", this.PluginNames.ToSentence <string>()), exception); callback(null); }); } }); }
public static string GetParamStr(IMetadataTokenProvider meth) => meth.ToString().Split(new[] { '(' }, 2).Last().TrimEnd(')');