是否可以作为资源执行项目中包含的exe文件?我可以将文件作为字节数组获取并在内存中执行吗?
我不想将文件写入临时位置并在那里执行。我正在寻找一种解决方案,我可以在内存中执行它。 (这不是.NET程序集。)
答案 0 :(得分:7)
这很有可能 - 我自己也做过 - 但是从托管代码来看,这是非常繁琐的。它没有.NET API,也没有可以PInvoke的原生API。因此,您必须手动处理负载,这需要了解用于DLL和EXE等模块的PE(可移植可执行文件)文件格式 - http://msdn.microsoft.com/en-us/magazine/cc301805.aspx。将会有很多指针操作(强制使用不安全的{}块)和PInvoke。
首先将PE文件加载到内存中(或使用MapViewOfFile)。 PE文件内部由包含代码,数据或资源的不同部分组成。文件中每个部分的偏移量并不总是与预期的内存偏移量匹配,因此需要进行一些小的调整。
每个PE文件都假定它将被加载到虚拟内存中的某个基址。除非你能确保这一点,否则你需要走PE文件的重定位表来相应地调整指针。
每个PE文件还有一个导入表,列出了它想要调用的其他DLL的功能。您需要遍历此表并调用LoadLibrary()/ GetProcAddress()来填充每个导入。
接下来,需要为每个部分正确设置内存保护。每个部分的标题都记录了它想要的保护,因此只需要为每个部分调用具有正确标志的VirtualProtect()。您至少需要使用PAGE_EXECUTE_READWRITE VirtualProtect加载的模块,否则您不太可能执行任何代码。
最后,对于DLL,您需要调用其入口点,其地址可以在PE头中找到;然后,您可以自由调用导出的函数。
由于您想要运行EXE,您会遇到一些额外的麻烦。您可以启动一个新线程并从中调用EXE的入口点,但是许多EXE可能会因为为您设置过程而感到不安,而不是EXE。当它试图退出时,它也可能会杀死你的进程。因此,您可能希望生成一个新进程 - 也许您的主EXE的另一个副本带有特殊参数,告诉它它将运行一些不同的代码 - 在这种情况下,您必须将EXE驱逐到其内存空间。您可能希望在新流程中完成上述大部分工作,而不是旧流程。您可以创建命名管道并将数据从一个EXE发送到另一个EXE,也可以使用MapViewOfFile分配命名的共享内存区域。当然,EXE可能仍然会因为它的运行过程而感到不安。
总而言之,只需写入临时文件然后使用Process.Start()即可。
如果您仍然想要这么做,请在非托管代码中查看此示例:http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/。这不包括可执行文件,只包括DLL,但如果其中的代码没有吓到你,你可以将这个过程扩展到可执行文件。
答案 1 :(得分:1)
更好的方法是使用FILE_FLAG_DELETE_ON_CLOSE属性创建临时DLL文件。这样,文件将在不再使用时自动删除。
我认为没有办法从内存(而不是文件)加载DLL。
答案 2 :(得分:0)
从内存映像创建新进程并不容易,所有内核函数都适合从磁盘加载映像。有关详细信息,请参阅Windows NT/2000 native API reference的流程部分 - 第161页有一个手动分支流程的示例。
如果可以在您自己的进程中运行代码,那么您可以创建一个小DLL,它将获取指向可执行数据的指针并运行它。