在两个进程之间共享内存(C,Windows)

时间:2009-07-29 15:10:26

标签: c windows memory share code-injection

由于我没有找到答案to the question asked previously here我正在尝试不同的方法。

有没有办法在两个进程之间共享内存?

第二个进程从注入中获取信息,因为它是一个不再受支持的遗留程序。

我的想法是在那里注入一些代码,在我传递到注入程序的结构中将地址(或其他)传递给我需要运行的数据所在的共享内存。一旦我得到数据,我将在注入的线程中填充我自己的变量。

这可能吗? 怎么样?

感谢代码。

编辑:

我认为现在还不清楚所以我会澄清一下。我知道如何注射。我已经这样做了。这里的问题是将动态数据传递给注入。

7 个答案:

答案 0 :(得分:25)

尽管windows通过其file mapping API支持共享内存,但您无法直接将共享内存映射注入另一个进程,因为MapViewOfFileEx不会接受进程参数。

但是,您可以使用VirtualAllocExWriteProcessMemory在另一个进程中分配内存来注入一些数据。如果要使用DuplicateHandle复制句柄,然后注入调用MapViewOfFileEx的存根,则可以在另一个进程中建立共享内存映射。因为听起来你无论如何都要注入代码,这应该对你有用。

总结一下,您需要:

  • 通过调用CreateFileMapping创建一个匿名共享内存段句柄,其中hFile为INVALID_HANDLE_VALUE,lpName为NULL。
  • 使用DuplicateHandle
  • 将此句柄复制到目标流程中
  • 使用VirtualAllocEx为代码分配一些内存,flAllocationType = MEM_COMMIT | MEM_RESERVE和flProtect = PAGE_EXECUTE_READWRITE
  • 使用WriteProcessMemory将存根代码写入此内存。这个存根可能需要用汇编语言编写。将HANDLE从DuplicateHandle传递到这里的某处。
  • 使用CreateRemoteThread执行存根。然后,存根必须使用它获得的HANDLE来调用MapViewOfFileEx。然后,这些进程将具有共同的共享内存段。

如果您的存根加载外部库,您可能会发现它更容易一点 - 也就是说,只需调用LoadLibrary(将LoadLibrary的地址作为练习留给读者)并从库的dllmain条目开始工作点。在这种情况下,使用命名共享内存可能比使用DuplicateHandle更简单。有关更多详细信息,请参阅CreateFileMapping上的MSDN文章,但实质上,为hFile传递INVALID_HANDLE_VALUE,为lpName传递名称。

编辑:由于您的问题是传递数据而非实际代码注入,因此以下是一些选项。

  1. 使用可变大小的共享内存。您的存根获取大小以及共享内存的名称或句柄。如果您只需要交换一次数据,这是合适的。 请注意,创建后无法轻松更改共享内存段的大小。
  2. 使用named pipe。您的存根获取管道的名称或句柄。然后,您可以使用适当的协议来交换可变大小的块 - 例如,写入size_t作为长度,然后写入实际消息。或者使用PIPE_TYPE_MESSAGE和PIPE_READMODE_MESSAGE,并注意ERROR_MORE_DATA以确定消息的结束位置。如果您需要多次交换数据,这是合适的。
  3. 编辑2 :以下是如何为存根实现句柄或指针存储的草图:

    .db B8            ;; mov eax, imm32
    .dl handle_value  ;; fill this in (located at the start of the image + one byte)
    ;; handle value is now in eax, do with it as you will
    ;; more code follows...
    

    您也可以使用固定名称,这可能更简单。

答案 1 :(得分:10)

您可以尝试memory-mapped file

This提供了更多详细步骤。

答案 2 :(得分:3)

答案 3 :(得分:1)

您是否尝试使用管道(用于内存)甚至序列化(用于对象)?您可以使用文件来管理进程之间的内存。套接字也很适合在进程之间进行通信。

答案 4 :(得分:1)

内存映射是要走的路,你甚至不需要创建一个永久的内存空间,当共享它的所有进程都关闭时,内存扇区会超出范围。还有其他方法。将数据从一个C应用程序传递到另一个应用程序的快速而肮脏的方法就是使用操作系统。在命令行类型app1 | app2。这会导致app2成为app1的输出目标,或者来自app1的printf命令会将其发送到app2(这称为管道)。

答案 5 :(得分:0)

如果您正在谈论Windows,那么主要障碍就是将每个流程都存储在自己的虚拟地址空间中。遗憾的是,您无法从进程到进程传递正常的内存地址并获得您期望的结果。 (另一方面,线程都存在于相同的地址空间中,这就是线程可以以相同的方式查看内存的原因。)

但是,Windows确实有共享内存空间,您必须非常小心才能正确管理。在共享内存空间中分配空间的任何进程都负责显式释放该内存。这与本地存储器形成对比,本地存储器在处理过程中或多或少地消失。

有关如何使用共享内存空间来接管世界的一些想法,请参阅this MSDN sample article。呃,与传统软件的接口。或者其他:)祝你好运,无论你最终做什么!

答案 6 :(得分:0)

您可以尝试使用Boost.Interprocess在两个进程之间进行通信。但是要将代码注入以前存在的,不受支持的软件中,您可能必须使用@ bdonlan的方式使用WriteProcessMemory