【问题标题】:How do I r/w process memory via scanning and replacing solely arrays of bytes?如何通过扫描和仅替换字节数组来读取/写入内存?
【发布时间】:2011-04-02 23:57:56
【问题描述】:

这个问题可能看起来非常菜鸟,我很抱歉。在过去的三个月里,我一直在定期尝试弄清楚如何通过字节数组来读取/写入另一个进程内存或运行应用程序的进程内存。据我所知,C#没有读写内存进程的能力,所以必须通过P/Invoke调用win32 API dll。

[DllImport("kernel32.dll")]  
static extern Int32 ReadProcessMemory(IntPtr OpenedHandle, IntPtr lpBaseAddress, byte[] lpBuffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

我的目标是像在 Cheat Engine 中一样简单有效地搜索和替换几个字节数组。我通常会有两个单独的变量或在一个数组中:

private string original = "d0 d0 66 ae 0b 68 b9 0a";
private string replace = "d0 02 02 24 00 68 b9 0a";

在ReadProcessMemory 通话中,我不明白为什么需要lpBaseAddress。 OpenHandle 我通常会放置应用程序的字符串,因为我直接编辑它。 lpBuffer 我假设是要读取/写入的实际字节数组。 size 我不太确定,lpNumberOfBytesRead 是要读的数字吗?对WriteProcessMemory的相互提问也是如此。

[DllImport("kernel32.dll")]
private static unsafe extern Boolean WriteProcessMemory(IntPtr hProcess, uint lpBaseAddress, byte[] lpBuffer, int nSize, void* lpNumberOfBytesWritten);

我想引用一些我读过的教程,但它们似乎不再存在或已被替换。再次,我真诚地为提出这样一个看似业余的问题道歉,但是 S.O.是我最后的选择。

【问题讨论】:

    标签: c#


    【解决方案1】:

    据我所知,C# 没有 读/写内存的能力 进程,所以它必须调用win32 API 通过 P/Invoke 加载 dll。

    正确,您已经找到了正确的 Win32 API。

    我通常会有两个变量 单独或在数组中:

    private string original = "d0 d0 66 ae 0b 68 b9 0a";
    private string replace = "d0 02 02 24 00 68 b9 0a";
    

    对于ReadProcessMemory 和WriteProcessMemory,您不会使用字符串,而是使用实际的字节数组 (byte[]),如您列出的 P/Invoke 函数签名中所示。您的 UI 或命令行工具可以接受字符串,但您需要将它们转换为字节数组。

    如果您还没有,您应该阅读 ReadProcessMemory 和 WriteProcessMemory 的 MSDN 文档。它们很好地描述了每个参数的预期、发生的情况以及返回的内容。

    在 ReadProcessMemory 调用中,我不是 了解为什么 lpBaseAddress 是 必要的。我想要的 OpenHandle 通常放置的字符串 申请,因为我是直接 编辑它。

    首先,OpenHandle 参数需要一个进程句柄,而不是文件名,我认为你指的是文件名。您可以使用 Win32 OpenProcess API 获取正在运行的进程的句柄(P/Invoke 签名可以在 here 中找到)。要在进程中读写内存,您至少需要PROCESS_VM_READ 和PROCESS_VM_WRITE 访问权限。

    lpBuffer 我假设是 要读/写的实际字节数组。 我不太确定的尺寸,以及 lpNumberOfBytesRead 是数字 阅读?相互提问 WriteProcessMemory 也是如此。

    对于ReadProcessMemory,lpBaseAddress 指定要从目标进程的内存中读取的位置。 lpBuffer 被目标进程的内存内容填满。 size 指定要读取的字节数。 lpNumberOfBytesRead 是一个输出参数告诉您作为操作的一部分实际读取了多少字节。在成功的情况下,这应该与您指定的缓冲区的size 匹配。

    鉴于此,您应该能够弄清楚WriteProcessMemory 的所有参数的作用。


    更多关于如何实现您想要做的事情:您正在尝试执行搜索和替换操作。搜索部分将是最艰难的。我能想到的主要方法有两种:

    1. 您可以对进程的内存进行全面扫描(字面意思是从地址零到 2/3GB 限制(对于 32 位进程))以查找您的字节。这是最慢但最简单的方法。

    2. 使用堆信息,您可以将扫描限制在已知的分配地址。这是一种更快但更复杂的方法。由于您在 Windows 上运行,因此您的目标进程可能会使用 Windows 堆进行内存管理。 Windows 提供了一个 API,HeapWalk,用于遍历进程中分配的堆(和对象)。不幸的是,这需要堆的句柄,而GetProcessHeap/GetProcessHeaps 方法只返回调用进程的堆的句柄(它们不适用于远程进程)。因此,如果您想要远程进程的堆信息,则需要向远程进程注入一个线程来为您收集这些信息(即使用CreateRemoteThread)。一旦你有了有效的堆地址,你就可以从你的搜索和替换应用程序中扫描它们。

    【讨论】:

    • 非常感谢克里斯的帮助。我再试一次。
    猜你喜欢
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    相关资源
    最近更新 更多