我正在考虑编写一个涉及超快速汇编的程序,或者因为它不必是人类可读的,它可能是C ++或C#中的机器代码。但是我也有其他可能更麻烦的要求。
我需要能够:
将机器代码程序存储在普通变量/对象实例中,例如字符串“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
据维基链接,Michael Dorgan发布了“asm(std :: string);”将String作为汇编程序运行,并且很容易从程序的C ++部分中提取变量。编辑std :: String很简单,Alex已经注意到我可以通过不允许不安全的命令来确保代码是安全的。
答案 0 :(得分:3)
沙盒本地机器代码非常重要。如果您真的想要查看来自Google的NACL,它会为浏览器实现机器代码沙箱。
更实际的是使用.NET IL而不是机器代码并使用沙盒(或托管)AppDomain。由于动态jit编译到机器代码,因此更接近并且仍然很快。
您可以选择使用Windows内置权限管理并生成具有受限权限的新进程。从来没有这样做过,所以我不知道你是否可以根据需要减少目标进程权限。无论如何,这只是一个纯粹的win32进程,只是运行机器代码,所以你失去了在沙盒进程中使用.NET的能力。
答案 1 :(得分:2)
根据评论进行更新:
这远非一项微不足道的任务。您必须实现链接器,汇编器(扫描和沙箱)和加载器。
我想知道用例是什么 - 就我的例子而言,我假设你想参加一个装配比赛,让人们提交问题的解决方案,然后“测试”它们。
这是我能想到的最佳解决方案:
拥有一个托管程序作为输入汇编语言。
调用汇编程序来编译和链接汇编程序。
为要运行的程序(如何执行此操作取决于平台)创建受保护的虚拟环境,该环境以对系统无权限的用户身份运行。
捕获结果
此解决方案允许您利用现有的汇编程序,加载程序和安全性,而无需重新实现它们。
我知道的动态加载,运行和沙盒C#代码的最佳示例代码是http://terrarium2.codeplex.com/
上的饲养箱游戏但是,你可能会考虑更适合这项工作的东西,比如脚本系统。 Lua是一个受欢迎的人物。使用Lua用户只能执行您允许的操作。 http://www.lua.org/
答案 2 :(得分:2)
如果你想在你的C / C ++代码中包含汇编程序,可以考虑内联汇编程序,或者在汇编程序文件上单独编译并将它们重新链接。内联汇编程序语法有点奇怪,但我相信它可能是最好的从我读过的内容中为你选择。
维基百科拯救了一些样本:
答案 3 :(得分:1)
如果您限制支持的指令子集,您可以或多或少地执行您想要的操作。
首先,您必须解析并解码输入指令以查看它是否在受支持的子集中(大多数解析/解码只能执行一次)。然后你需要执行它。
但在执行之前,有一件重要的事情要照顾。根据指令的解码细节和CPU寄存器状态,您必须计算指令将作为数据(包括堆栈上位置)或传输控制来访问的存储器地址。如果其中任何一个超出既定限制,则发出火警。否则,如果它是一个控制转移指令(例如jmp,jz),你必须另外确保它控制的地址不仅在所有这些指令所在的存储器内,而且还是其中一个指令的地址和不是其中任何一个地址(例如,从3+字节长指令的开头起1或2个字节)。在其他地方传递控制权是禁忌。您不希望这些指令将控制权传递给任何标准库函数,因为您无法控制那里的执行,并且在提供虚假/恶意输入时它们并不总是安全的。此外,这些说明必须无法自行修改。
如果一切都清楚,你可以模拟指令或者或多或少直接执行它(控制传递指令可能必须总是被模拟,因为你想在每条指令后停止执行)。对于后者,您可以创建一个包含以下内容的可修改函数:
您可以尝试这种方法。