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

由于我没有find一个问题的答案在这里以前问我在尝试一种不同的方法。

有什么办法可以在两个进程之间共享内存?

第二个过程从注入中获取信息,因为它是一个传统程序,它不再被支持。

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

这可能吗? 怎么样?

代码表示赞赏。

编辑:

我认为这不清楚,所以我会澄清。 我知道如何注入。 我已经在做了。 这里的问题是将dynamic数据传递给注入。

你可以尝试一个内存映射文件 。

这给了更多的一步一步的细节。

虽然Windows通过其文件映射API支持共享内存,但是您不能直接将共享内存映射注入另一个进程,因为MapViewOfFileEx没有使用进程参数。

但是,可以通过使用VirtualAllocEx和WriteProcessMemory在另一个进程中分配内存来注入一些数据。 如果要使用DuplicateHandle复制句柄,然后注入调用MapViewOfFileEx的存根,则可以在另一个进程中build立共享内存映射。 既然听起来好像你会注入代码,这应该适合你。

总而言之,您需要:

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

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

编辑 :由于你的问题是传递数据而不是实际的代码注入,这里有几个选项。

  1. 使用可变大小的共享内存。 您的存根(stub)获取共享内存的大小和名称或者句柄。 如果您只需要交换一次数据,这是适当的。 请注意,共享内存段的大小在创build后不能轻易更改。
  2. 使用命名pipe道 。 您的存根(stub)获取pipe道的名称或句柄。 然后,您可以使用适当的协议交换可变大小的块 – 例如,写一个size_t长度,然后是实际的消息。 或者使用PIPE_TYPE_MESSAGE和PIPE_READMODE_MESSAGE,并观察ERROR_MORE_DATA来确定消息的结束位置。 如果您需要多次交换数据,这是适当的。

编辑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... 

你也可以使用一个固定的名字,这可能更简单。

你尝试使用pipe道(内存),甚至是序列化(为你的对象)? 您可以使用文件来pipe理进程之间的内存。 套接字也是很好的进程之间的沟通。

如果你在谈论Windows,主要的障碍是每个进程都在自己的虚拟地址空间中。 不幸的是,你不能从正在处理的stream程中传递正常的内存地址,并得到你所期望的结果。 (线程,另一方面,都住在相同的地址空间,这就是为什么线程可以看到内存的方式。)

但是,Windows有一个共享内存空间,您必须非常小心才能正确pipe理。 在共享内存空间中分配空间的任何进程都负责明确地释放该内存。 这与本地内存不同,当进程死亡时,本地内存或多或less地消失。

有关如何使用共享内存空间来接pipe世界的一些想法,请参阅此MSDN示例文章 。 呃,与传统软件的接口。 或者任何:)祝你好运,无论你最终做什么!

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

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