如何从运行内存非托管可执行,而不是光盘(How to run unmanaged executabl

2019-06-27 18:00发布

我想嵌入一个命令行实用程序在我的C#应用​​程序,这样我就可以抓住它的字节数组,没有它永远保存到磁盘作为一个单独的文件运行可执行(避免存储可执行文件作为单独的文件以及避免能力写入临时文件的任何地方)。

我无法找到刚刚从它的字节流运行的可执行的方法。 是否窗户要求它在磁盘上,或者是有没有办法从内存中运行呢? 如果Windows要求它在磁盘上,有没有在.NET框架的一个简单的方法来建立某种形式的虚拟驱动器/文件和地图文件的可执行的内存流?

Answer 1:

你问一个非常低的水平,在高级别来实现特定于平台的功能,可管理的环境。 一切皆有可能......但没有人说这会很容易...

(顺便说一句,我不知道为什么你认为临时文件管理是繁重的BCL会为你: http://msdn.microsoft.com/en-us/library/system.io.path.gettempfilename.aspx )


  1. 分配足够的内存来保存可执行文件。 它不能驻留在托管堆中,当然,所以像几乎所有在这个练习中,您需要的PInvoke。 (我建议C ++ / CLI,实际上,以免自己开车疯狂了)。 要特别注意你申请到分配的内存页属性位:让他们错了,你要么打开一个巨大的安全孔或有你的过程DEP(即,你会崩溃)关闭。 见http://msdn.microsoft.com/en-us/library/aa366553(VS.85).aspx

  2. 找到你的装配的资源库中的可执行文件,并获得了固定处理它。

  3. 的memcpy()从托管堆与天然块的钉扎区域的代码。

  4. 自由的GCHandle。

  5. 呼叫VirtualProtect的 ,以防止进一步写入可执行内存块。

  6. 计算你的进程的虚拟地址空间内的可执行文件的主要功能的基础上,从你拿到的VirtualAlloc和如图DUMPBIN或类似工具,该文件中的偏移手柄的地址。

  7. 放置所需的命令行参数的堆栈上。 ( 视窗STDCALL约定 )。 任何指针必须指向本地或固定区域,当然。

  8. 跳转到计算的地址。 也许最容易使用_call(内联汇编语言)。

  9. 祈祷上帝可执行图像不具有任何绝对的跳跃,这会已经通过调用LoadLibrary正常的方式固定起来。 (当然,除非,你觉得像步骤3中重新实现调用LoadLibrary的大脑)。

  10. 检索来自@eax寄存器中的返回值。

  11. 调用VirtualFree。

步骤#5和#11应以最后块和/或使用IDisposable模式来完成。


其他的主要选择是创建一个RAMDrive,写可执行那里,运行它,并清理。 (当代码甚至没有你这是在任何情况下艰难的,但尤其如此),这可能是一个小更安全,因为你是不是要写自修改代码。 但我敢肯定它会需要比动态代码注入选项更平台的API调用 - 他们都需要C ++或PInvoke的,自然。



Answer 2:

看看本文的“内存”部分。 要知道,这是从一个远程注入DLL的观点,但这个概念应该是相同的。

远程库注入



Answer 3:

创建一个ramdisk或倾倒代码到内存中,然后执行它都是可能的,但非常复杂的解决方案(可能更多的是在托管代码)。

它需要是一个可执行文件? 几个代码琐碎线 - 如果打包为一个组件,则可以从存储器流使用Assembly.Load()。

或者,如果它真的必须是可执行的,究竟是什么错写一个临时文件? 这需要的几行代码把它转储到一个临时文件,执行它,等待它退出,然后删除临时文件 - 甚至有可能不会离开磁盘缓存的你删除它之前! 有时简单的,显而易见的解决方案是最佳的解决方案。



Answer 4:

这是不明确在Vista +允许的。 你可以使用一些无证Win32 API调用在XP中要做到这一点,但它是在Vista +破,因为它是一个巨大的安全漏洞,并使用它的唯一的人是恶意软件编写者。



文章来源: How to run unmanaged executable from memory rather than disc