如何在C#中为外部进程创建沙盒?

17

如何在C#中为外部进程创建沙箱?所谓沙箱,我理解为一种环境,能够防止我从C#启动的进程与其他任何东西(内核、系统变量、系统配置、内存、注册表、磁盘、硬件、位置等)产生干扰。

我希望将可执行文件放在一个地方,并确保这个地方是唯一可以被该进程更改的地方。此外,可执行文件可以使用C、C++、C#等编写。

2个回答

5

如果您只想运行托管代码,使用带有受限权限集的AppDomain创建沙盒环境相对容易:

        PermissionSet ps = new PermissionSet(PermissionState.None);
        // ps.AddPermission(new System.Security.Permissions.*); // Add Whatever Permissions you want to grant here

        AppDomainSetup setup = new AppDomainSetup();
        Evidence ev = new Evidence();

        AppDomain sandbox = AppDomain.CreateDomain("Sandbox",
            ev,
            setup,
            ps);

        sandbox.ExecuteAssembly("ManagedAssembly.exe");

但是,一旦你打开了不受管理/不安全的代码,所有的赌注都取消了,保护第三方代码变得非常困难。正如已经提到的,你基本上必须在执行代码和操作系统之间创建一个壳来限制它能做什么,除非将其作为受限用户运行并依靠ACL/UAC保护自己足够。请注意:该代码示例不是一个工作示例,只是代码看起来的一个想法。可能需要对证据和AppDomainSetup进行调整,并且考虑到安全性问题,你应该进行充分的研究/测试。这里有一篇关于这个主题的好文章:http://msdn.microsoft.com/en-us/magazine/cc163701.aspx

2
说实话,我真的不知道从哪里开始处理非托管 / 不安全的代码,而弄清楚这个需要几个月的项目,需要深入了解Windows操作系统、内核/系统调用、内存分配和访问。甚至微软的工程师都有可能无法把这些东西做好。 - Paul Wheeler
2
我的建议是:更改您的要求,要么只接受托管代码,要么向用户明确表示他们应该只使用他们信任的第三方可执行文件。除非您只是想以不同的用户身份运行进程,在这种情况下,请查看ProcessStartInfo类的Domain/UserName/Password属性。 - Paul Wheeler
问题是,我不能只接受托管代码(性能不够好,大部分时间我需要纯C代码),而整个想法是使用第三方可执行文件。这是整个系统的主要用途。现在我该怎么办?重新提出一个问题还是怎样? - SuitUp

3
使用 Sandboxie 作为我认为您想要实现的部分内容的示例。在我看来,您将无法仅使用纯托管代码完成此操作。
如果您想限制应用程序的操作和影响,而不管它是托管、本机还是Java应用程序,则意味着您需要监视应用程序执行的每个操作,并采取适当的措施以确保它不会影响您的系统。适当的措施可能意味着将应用程序写入重定向到磁盘上的其他位置,编写虚拟化注册表以使真实注册表不受影响等等。所有这些都需要大量低级别的工作,而托管代码今天并不提供。
请注意,我说的是纯托管代码,您当然可以使用Interop Services等来利用某些代码领域的非托管实现,或者您可以使用托管C ++。但是,根据您想要沙箱执行的确切细节,您可能需要实现内核模式驱动程序,以确保您可以足够虚拟化沙箱用户模式应用程序的环境。

你提到了重定向到另一个注册表或磁盘位置。那么完全阻止使用注册表,不必进行重定向怎么样?这样会更简单吗?因为这些应用程序不需要任何这些功能。我只想阻止它们。 - SuitUp
1
@SuitUp,虽然这可能更容易,但仍需要相同或类似的机制来拦截调用并使其失败。简化的重点在于您不需要虚拟化注册表等,但是拦截的复杂性仍然存在。您可以使用像Detours这样的库进行拦截,但老实说,我怀疑这将为您提供强大而可靠的沙箱解决方案,当然我假设您需要完整的可靠和安全的解决方案,这将需要更多的基本调用拦截。 - Chris Taylor
你的假设是正确的。你能给我一些技术细节吗? - SuitUp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接