diff --git a/src/CSharpExtension.cs b/src/CSharpExtension.cs
index 171c29c..e63e57c 100644
--- a/src/CSharpExtension.cs
+++ b/src/CSharpExtension.cs
@@ -43,9 +43,6 @@ public class CSharpExtension : Extension
// The .cs plugin loader
private CSharpPluginLoader loader;
- // Is the sandbox enabled? (always default to true)
- public static bool SandboxEnabled { get; private set; } = true;
-
///
/// Initializes a new instance of the CSharpExtension class
///
@@ -75,12 +72,6 @@ public override void Load()
// Register engine frame callback
Interface.Oxide.OnFrame(OnFrame);
-
- if (File.Exists(Path.Combine(Interface.Oxide.ExtensionDirectory, "oxide.disable-sandbox")))
- {
- Interface.Oxide.LogWarning($"{Path.Combine(Interface.Oxide.ExtensionDirectory, "oxide.disable-sandbox")} found, disabling security sandbox. Potentially dangerous APIs and methods are now allowed inside plugins.");
- CSharpExtension.SandboxEnabled = false;
- }
}
///
diff --git a/src/CSharpPlugin.cs b/src/CSharpPlugin.cs
index da9d559..df23e19 100644
--- a/src/CSharpPlugin.cs
+++ b/src/CSharpPlugin.cs
@@ -385,7 +385,7 @@ protected override object InvokeMethod(HookMethod method, object[] args)
CompilablePlugin compilablePlugin = CSharpPluginLoader.GetCompilablePlugin(Interface.Oxide.PluginDirectory, Name);
if (compilablePlugin?.CompiledAssembly != null)
{
- File.WriteAllBytes(Interface.Oxide.PluginDirectory + "\\" + Name + ".dump", compilablePlugin.CompiledAssembly.PatchedAssembly);
+ File.WriteAllBytes(Interface.Oxide.PluginDirectory + "\\" + Name + ".dump", compilablePlugin.CompiledAssembly.RawAssembly);
Interface.Oxide.LogWarning($"The invalid raw assembly has been dumped to Plugins/{Name}.dump");
}
hookDispatchFallback = true;
@@ -475,9 +475,9 @@ protected void LogToFile(string filename, string text, Plugin plugin, bool dated
lock (_logFileLock)
{
using (FileStream file = new FileStream(Path.Combine(path, Utility.CleanPath(filename)), FileMode.Append, FileAccess.Write, FileShare.Read))
- using (StreamWriter writer = new StreamWriter(file, Encoding.Unicode))
+ using (StreamWriter writer = new StreamWriter(file, Encoding.UTF8))
{
- writer.Write(timestampPrefix ? $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {text}" : text);
+ writer.WriteLine(timestampPrefix ? $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {text}" : text);
}
}
}
diff --git a/src/Compilation.cs b/src/Compilation.cs
index a53637b..2a95b50 100644
--- a/src/Compilation.cs
+++ b/src/Compilation.cs
@@ -272,8 +272,7 @@ private void PreparseScript(CompilablePlugin plugin)
if (match.Success)
{
string result = match.Groups[1].Value;
- if (!result.StartsWith("Oxide.") && !result.Contains("Newtonsoft.Json")&& !result.Contains("protobuf-net")
- || !CSharpExtension.SandboxEnabled && !result.Contains("Harmony"))
+ if (!result.StartsWith("Oxide.") && !result.Contains("Newtonsoft.Json") && !result.Contains("protobuf-net"))
{
AddReference(plugin, result);
Interface.Oxide.LogInfo("Added '// Reference: {0}' in plugin '{1}'", result, plugin.Name);
diff --git a/src/CompiledAssembly.cs b/src/CompiledAssembly.cs
index 3bf5588..ab1cf91 100644
--- a/src/CompiledAssembly.cs
+++ b/src/CompiledAssembly.cs
@@ -3,8 +3,6 @@
using Oxide.Core;
using Oxide.Core.CSharp;
using References::Mono.Cecil;
-using References::Mono.Cecil.Cil;
-using References::Mono.Cecil.Rocks;
using System;
using System.Collections.Generic;
using System.IO;
@@ -12,9 +10,6 @@
using System.Reflection;
using System.Threading;
-using MethodAttributes = References::Mono.Cecil.MethodAttributes;
-using MethodBody = References::Mono.Cecil.Cil.MethodBody;
-
namespace Oxide.Plugins
{
public class CompiledAssembly
@@ -34,17 +29,6 @@ public class CompiledAssembly
private bool isPatching;
private bool isLoaded;
- private static IEnumerable BlacklistedNamespaces => new[] {
- "Harmony", "Mono.CSharp", "Mono.Cecil", "Oxide.Core.ServerConsole", "ServerFileSystem", "System.IO", "System.Net", "System.Xml", "System.Reflection.Assembly",
- "System.Reflection.Emit", "System.Threading", "System.Runtime.InteropServices", "System.Diagnostics", "System.Security", "System.Timers"
- };
-
- private static IEnumerable WhitelistedNamespaces => new[] {
- "System.Diagnostics.Stopwatch", "System.IO.MemoryStream", "System.IO.Stream", "System.IO.BinaryReader", "System.IO.BinaryWriter", "System.IO.StringReader",
- "System.IO.StringWriter", "System.Net.Dns", "System.Net.Dns.GetHostEntry", "System.Net.IPAddress", "System.Net.IPEndPoint", "System.Net.NetworkInformation",
- "System.Net.Sockets.SocketFlags", "System.Security.Cryptography", "System.Threading.Interlocked", "System.Threading.Monitor"
- };
-
public CompiledAssembly(string name, CompilablePlugin[] plugins, byte[] rawAssembly, float duration)
{
Name = name;
@@ -69,7 +53,7 @@ public void LoadAssembly(Action callback)
return;
}
- PatchAssembly(rawAssembly =>
+ ValidateAssembly(rawAssembly =>
{
if (rawAssembly == null)
{
@@ -97,17 +81,14 @@ public void LoadAssembly(Action callback)
});
}
- private void PatchAssembly(Action callback)
+ private void ValidateAssembly(Action 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(_ =>
{
@@ -119,129 +100,8 @@ private void PatchAssembly(Action callback)
definition = AssemblyDefinition.ReadAssembly(stream);
}
- ConstructorInfo exceptionConstructor = typeof(UnauthorizedAccessException).GetConstructor(new[] { typeof(string) });
- MethodReference securityException = definition.MainModule.Import(exceptionConstructor);
-
- Action patchModuleType = null;
- patchModuleType = type =>
- {
- foreach (MethodDefinition method in type.Methods)
- {
- bool changedMethod = false;
-
- if (method.Body == null)
- {
- if (method.HasPInvokeInfo)
- {
- 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 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)
{
- if (CSharpExtension.SandboxEnabled)
- {
- patchModuleType(type);
- }
-
if (IsCompilerGenerated(type))
{
continue;
@@ -270,9 +130,8 @@ private void PatchAssembly(Action callback)
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()}");
+ ? $"{PluginNames[0]} has polluted the global namespace by defining {type.Name}"
+ : $"A plugin has polluted the global namespace by defining {type.Name}");
}
}
else if (type.FullName != "")
@@ -280,28 +139,8 @@ private void PatchAssembly(Action callback)
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}");
- }
+ ? $"{PluginNames[0]} has polluted the global namespace by defining {type.FullName}"
+ : $"A plugin has polluted the global namespace by defining {type.FullName}");
}
}
}
@@ -315,7 +154,6 @@ private void PatchAssembly(Action callback)
Interface.Oxide.NextTick(() =>
{
isPatching = false;
- //Interface.Oxide.LogDebug("Patching {0} assembly took {1:0.00} ms", ScriptName, Interface.Oxide.Now - startedAt);
callback(PatchedAssembly);
});
}
@@ -325,7 +163,6 @@ private void PatchAssembly(Action callback)
{
isPatching = false;
Interface.Oxide.LogException($"Exception while patching: {PluginNames.ToSentence()}", ex);
- //RemoteLogger.Exception($"Exception while patching: {PluginNames.ToSentence()}", ex);
callback(null);
});
}
@@ -335,24 +172,5 @@ private void PatchAssembly(Action callback)
public bool IsOutdated() => CompilablePlugins.Any(pl => pl.GetLastModificationTime() != CompiledAt);
private bool IsCompilerGenerated(TypeDefinition type) => type.CustomAttributes.Any(attr => attr.Constructor.DeclaringType.ToString().Contains("CompilerGeneratedAttribute"));
-
- private static bool IsNamespaceBlacklisted(string fullNamespace)
- {
- foreach (string namespaceName in BlacklistedNamespaces)
- {
- if (!fullNamespace.StartsWith(namespaceName))
- {
- continue;
- }
-
- if (WhitelistedNamespaces.Any(fullNamespace.StartsWith))
- {
- continue;
- }
-
- return true;
- }
- return false;
- }
}
}