C#或C++;沙盒组件 我想编写一个程序,包括超快速汇编,或者它不必是人类可读的,它可以是C++或C语言中的机器代码。然而,我也有其他可能更麻烦的要求

C#或C++;沙盒组件 我想编写一个程序,包括超快速汇编,或者它不必是人类可读的,它可以是C++或C语言中的机器代码。然而,我也有其他可能更麻烦的要求,c#,c++,assembly,sandbox,C#,C++,Assembly,Sandbox,我需要能够: 将机器代码程序存储在普通变量/对象实例中,例如字符串“40 9B 7F 5F…”以编辑和运行它们 使程序能够输出数据。我看到一个例子,其中有一个指向可以使用的int的指针 使程序不能在任何其他地方输出数据。例如,不能执行删除文件的操作,查看系统规格或更改包含在其中的C++或C语言程序的内存状态。 例如,它可以是这样的: machine n; n = "40 9B 7F"; n[1] = "5F"; // 'n' is now "40 5F 7F" unsigned short

我需要能够:

  • 将机器代码程序存储在普通变量/对象实例中,例如字符串“40 9B 7F 5F…”以编辑和运行它们

  • 使程序能够输出数据。我看到一个例子,其中有一个指向可以使用的int的指针

  • 使程序不能在任何其他地方输出数据。例如,不能执行删除文件的操作,查看系统规格或更改包含在其中的C++或C语言程序的内存状态。

例如,它可以是这样的:

machine n;
n = "40 9B 7F";
n[1] = "5F";
// 'n' is now "40 5F 7F"
unsigned short s = 2;
n.run(&s);
// while 'n' was running it may have changed 's' but would not have been able to
// change anything else anywhere on the system including in this C++ / C# program
<>根据Wiki链接Michael Dorgan发布的“ASM(STD::String)”,将字符串作为汇编程序运行,也很容易从程序的C++部分引用变量。编辑std::String很容易,Alex指出,我可以通过不允许不安全的命令来确保代码的安全。

根据注释更新:

这绝不是一项微不足道的任务。您必须实现链接器、汇编器(用于扫描和沙箱)和加载程序

我想知道这个用例是什么——在我的示例中,我假设您想要举办一个组装竞赛,在竞赛中,人们提交问题的解决方案,然后您“测试”它们

这是我能想到的最好的解决方案:

  • 有一个以汇编语言作为输入的宿主程序

  • 调用汇编程序来编译和链接汇编程序

  • 创建一个受保护的虚拟环境,让程序以没有系统权限的用户身份运行(如何执行此操作取决于平台)

  • 捕捉结果

此解决方案允许您利用现有的汇编程序、加载程序和安全性,而无需重新实现它们


我所知道的动态加载、运行和沙箱C代码的最佳示例代码是


<>但是,你可以考虑更适合这个工作的东西,比如脚本系统。Lua作为一个受欢迎的人出现在我的脑海中。使用Lua的用户只能执行您允许的操作 Wikipedia提供了一些样本:


沙箱本机代码是非常重要的。如果你真的想这么做的话,看看谷歌吧,它为浏览器实现了一个机器代码沙盒

更实际的是使用.NETIL而不是机器代码,并使用沙盒(或托管)AppDomain。由于对机器代码的动态jit编译,这一点更加接近,而且速度仍然很快


另一种方法是使用Windows内置权限管理并生成具有受限权限的新进程。从未这样做过,因此我不知道您是否可以尽可能减少目标进程的权限。无论如何,这将是一个纯win32进程,只运行机器代码,因此您将失去在沙盒进程中使用.NET的任何能力。

如果您限制受支持指令的子集,您可以或多或少轻松地执行您想要的操作

首先,您必须对输入指令进行解析和解码,以查看它是否在支持的子集中(大多数解析/解码只需执行一次)。然后你需要执行它

但在执行之前,有一件重要的事情要注意。根据指令的解码细节和CPU寄存器状态,您必须计算指令将作为数据访问的内存地址(包括堆栈上的位置)或将控制转移到的内存地址。如果其中任何一个超出规定的范围,则应发出火灾警报。否则,如果它是一条控制传输指令(例如jmp、jz),您还必须确保它将控制传递到的地址不仅在所有这些指令所在的内存中,而且是其中一条指令的地址,而不是其中任何一条指令的地址(例如,从3+字节长的指令开始算起1或2个字节)。将控制权传递到其他任何地方都是不允许的。您不希望这些指令将控制权传递给任何标准库函数,因为您将无法控制那里的执行,并且当提供虚假/恶意输入时,它们并不总是安全的。此外,这些指令也不能修改自身

如果一切都清楚,您可以模拟该指令,也可以或多或少直接执行该指令(可能必须始终模拟控制传递指令,因为您希望在每条指令后停止执行)。对于后者,您可以创建包含以下内容的可修改函数:

  • 保存调用者的CPU寄存器并用正在执行的指令的状态加载它们的代码
  • 指令
  • 与步骤1相反:保存执行后寄存器状态和恢复调用方寄存器状态的代码

  • 你可以试试这种方法。

    你想把沙盒中的机器代码只输出到你的程序中吗?是的,这是对的,而且只输出到我指定的地方,所以不管运行什么机器代码块,它都不能写任何它喜欢的变量。我也可以存储和编辑机器代码。我不知道如何处理这些事情,但我似乎这可能是一个复杂的解决方案,输入为tyvm。我将首先尝试其他解决方案。另一个选项是dynamic.NET IL a la terrarium。如果您需要在运行时对其进行编辑,内联asm将无法帮助您。根据wiki,有一个asm运行程序