- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
于是想着写在线c#编译器和执行环境。当然,问题 #1 是安全性。我最终为用户代码创建了一个小特权应用程序域,并在一个新进程中启动它,该进程受到 cpu 和内存消耗的严格监控。提供标准控制台应用程序命名空间。所以我的问题是:你能想出以某种方式破坏某些东西的方法吗?可以现场试一下rundotnet .
Edit2 如果有人关心代码,现在有这个项目的开源分支:rextester at github
Edit1 作为对此处评论之一的回应,提供了一些代码示例。
所以基本上您创建了一个控制台应用程序。我只会发布其中的一大块:
class Sandboxer : MarshalByRefObject
{
private static object[] parameters = { new string[] { "parameter for the curious" } };
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
string pathToUntrusted = args[0].Replace("|_|", " ");
string untrustedAssembly = args[1];
string entryPointString = args[2];
string[] parts = entryPointString.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
string name_space = parts[0];
string class_name = parts[1];
string method_name = parts[2];
//Setting the AppDomainSetup. It is very important to set the ApplicationBase to a folder
//other than the one in which the sandboxer resides.
AppDomainSetup adSetup = new AppDomainSetup();
adSetup.ApplicationBase = Path.GetFullPath(pathToUntrusted);
//Setting the permissions for the AppDomain. We give the permission to execute and to
//read/discover the location where the untrusted code is loaded.
PermissionSet permSet = new PermissionSet(PermissionState.None);
permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
//Now we have everything we need to create the AppDomain, so let's create it.
AppDomain newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, null);
//Use CreateInstanceFrom to load an instance of the Sandboxer class into the
//new AppDomain.
ObjectHandle handle = Activator.CreateInstanceFrom(
newDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,
typeof(Sandboxer).FullName
);
//Unwrap the new domain instance into a reference in this domain and use it to execute the
//untrusted code.
Sandboxer newDomainInstance = (Sandboxer)handle.Unwrap();
Job job = new Job(newDomainInstance, untrustedAssembly, name_space, class_name, method_name, parameters);
Thread thread = new Thread(new ThreadStart(job.DoJob));
thread.Start();
thread.Join(10000);
if (thread.ThreadState != ThreadState.Stopped)
{
thread.Abort();
Console.Error.WriteLine("Job taking too long. Aborted.");
}
AppDomain.Unload(newDomain);
}
public void ExecuteUntrustedCode(string assemblyName, string name_space, string class_name, string method_name, object[] parameters)
{
MethodInfo target = null;
try
{
target = Assembly.Load(assemblyName).GetType(name_space+"."+class_name).GetMethod(method_name);
if (target == null)
throw new Exception();
}
catch (Exception)
{
Console.Error.WriteLine("Entry method '{0}' in class '{1}' in namespace '{2}' not found.", method_name, class_name, name_space);
return;
}
...
//Now invoke the method.
try
{
target.Invoke(null, parameters);
}
catch (Exception e)
{
...
}
}
}
class Job
{
Sandboxer sandboxer = null;
string assemblyName;
string name_space;
string class_name;
string method_name;
object[] parameters;
public Job(Sandboxer sandboxer, string assemblyName, string name_space, string class_name, string method_name, object[] parameters)
{
this.sandboxer = sandboxer;
this.assemblyName = assemblyName;
this.name_space = name_space;
this.class_name = class_name;
this.method_name = method_name;
this.parameters = parameters;
}
public void DoJob()
{
try
{
sandboxer.ExecuteUntrustedCode(assemblyName, name_space, class_name, method_name, parameters);
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
}
}
}
您编译上面的代码并在新进程中启动和监视可执行文件:
using (Process process = new Process())
{
try
{
double TotalMemoryInBytes = 0;
double TotalThreadCount = 0;
int samplesCount = 0;
process.StartInfo.FileName = /*path to sandboxer*/;
process.StartInfo.Arguments = folder.Replace(" ", "|_|") + " " + assemblyName + " Rextester|Program|Main"; //assemblyName - assembly that contains compiled user code
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
DateTime start = DateTime.Now;
process.Start();
OutputReader output = new OutputReader(process.StandardOutput);
Thread outputReader = new Thread(new ThreadStart(output.ReadOutput));
outputReader.Start();
OutputReader error = new OutputReader(process.StandardError);
Thread errorReader = new Thread(new ThreadStart(error.ReadOutput));
errorReader.Start();
do
{
// Refresh the current process property values.
process.Refresh();
if (!process.HasExited)
{
try
{
var proc = process.TotalProcessorTime;
// Update the values for the overall peak memory statistics.
var mem1 = process.PagedMemorySize64;
var mem2 = process.PrivateMemorySize64;
//update stats
TotalMemoryInBytes += (mem1 + mem2);
TotalThreadCount += (process.Threads.Count);
samplesCount++;
if (proc.TotalSeconds > 5 || mem1 + mem2 > 100000000 || process.Threads.Count > 100 || start + TimeSpan.FromSeconds(10) < DateTime.Now)
{
var time = proc.TotalSeconds;
var mem = mem1 + mem2;
process.Kill();
...
}
}
catch (InvalidOperationException)
{
break;
}
}
}
while (!process.WaitForExit(10)); //check process every 10 milliseconds
process.WaitForExit();
...
}
...
class OutputReader
{
StreamReader reader;
public string Output
{
get;
set;
}
StringBuilder sb = new StringBuilder();
public StringBuilder Builder
{
get
{
return sb;
}
}
public OutputReader(StreamReader reader)
{
this.reader = reader;
}
public void ReadOutput()
{
try
{
int bufferSize = 40000;
byte[] buffer = new byte[bufferSize];
int outputLimit = 200000;
int count;
bool addMore = true;
while (true)
{
Thread.Sleep(10);
count = reader.BaseStream.Read(buffer, 0, bufferSize);
if (count != 0)
{
if (addMore)
{
sb.Append(Encoding.UTF8.GetString(buffer, 0, count));
if (sb.Length > outputLimit)
{
sb.Append("\n\n...");
addMore = false;
}
}
}
else
break;
}
Output = sb.ToString();
}
catch (Exception e)
{
...
}
}
}
用户代码可以使用的程序集是在编译时添加的:
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
cp.OutputAssembly = ...
cp.GenerateInMemory = false;
cp.TreatWarningsAsErrors = false;
cp.WarningLevel = 4;
cp.IncludeDebugInformation = false;
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("System.Core.dll");
cp.ReferencedAssemblies.Add("System.Data.dll");
cp.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");
cp.ReferencedAssemblies.Add("System.Xml.dll");
cp.ReferencedAssemblies.Add("System.Xml.Linq.dll");
using (CodeDomProvider provider = CodeDomProvider.CreateProvider(/*language*/))
{
cr = provider.CompileAssemblyFromSource(cp, new string[] { data.Program });
}
最佳答案
你看过Mono's Compiler as a service了吗? ?我认为他们正在做的事情非常酷,也许对您的这个项目有用。
关于c#在线编译执行安全问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6312452/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!