首页 > 解决方案 > 如何获取另一个 C# 应用程序读取的内存地址?

问题描述

我想使用 2 个 C# 应用程序通过内存相互通信。对于我使用的主机端:

int* ptr = &level;

对于我想使用的客户端:

ReadProcessMemory((int)_handle, <returned result of int* ptr>, _buffer, 2, ref bytesRead);

但是 ReadProcessMemory 不起作用。例如:级别设置为 3,但 ReadProcessMemory 返回 0。这到底是怎么回事?(注意:“级别”字段不会从内存中清除)

我尝试了 int* ptr 很多次,因为很多网站都告诉我这样做,但对于 ReadProcessMemory 来说效果不佳。

我设置了 level = 3 但 ReadProcessMemory 的结果 level = 0

标签: c#

解决方案


你问的问题,你问的方式非常危险,因为该过程完全由 CLR 管理。根据您想要共享的内容和方式,您可以考虑使用套接字或管道。或者,您可以使用互操作,但在我看来,它需要一定的专业知识和修补。

两个 C# 应用程序通过内存进行通信的最简洁方式是使用内存映射文件。在托管进程中弄乱内存可能会产生微妙的问题。内存映射文件是一种共享信息的方式。

请记住,每个内存映射文件都加载到不同的内存地址,因此您需要在不使用绝对指针的情况下对其进行结构化。

编辑:直接原始内存访问需要知道要访问的确切物理地址,因为在目标进程中分配的虚拟地址不同并且可能与源进程的虚拟地址重叠。C# 应用程序由公共语言运行时托管,该运行时控制一切,包括内存分配。特别是,一个标准的 c# 应用程序并不管理自己的一点内存:当运行时移动对象作为正常应用程序生命周期的一部分时,这些地址会随着时间而改变。

如果您控制目标应用程序,则可以通过GC类锁定对象以禁止移动,然后您必须获取对象的地址,并将其传递给其他进程。然后其他进程必须打开目标进程进行读取,映射内存段,通过翻译虚拟地址计算出要读取的内存位置。

您的要求需要协作流程和大量低级知识,最后,您也可能永远无法读取更新的内存更改,因为 CLR 可能不会将值写回内存(看看volatile这个) .

编写这样的软件确实令人兴奋,但是当您同时控制这两个应用程序时,就有更简洁、更可靠的方法来实现您的目标。

附带说明一下,这种技术被培训师、黑客工具和病毒使用,因此杀毒软件在看到这种行为时会发出危险信号。


推荐阅读