c# - 我如何通过扫描和仅替换字节数组来读/写处理内存?

标签 c#

这个问题可能看起来非常菜鸟,我道歉。在过去的三个月里,我一直在定期尝试弄清楚如何简单地通过字节数组读取/写入另一个进程内存或正在运行的应用程序的进程内存。据我所知,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 调用中,我不明白为什么需要 lpBaseAddressOpenHandle 我通常会放置应用程序的字符串,因为我正在直接编辑它。 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.是我最后的选择。

最佳答案

As far as I know, C# doesn't have the capability to read/write memory process, so it must call the win32 API dlls via P/Invoke.

正确,您已找到合适的 Win32 API 来执行此操作。

I would normally have two vars either separate or within an array:

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

对于 ReadProcessMemoryWriteProcessMemory,您不会使用字符串,您将使用实际的字节数组 (byte[]) 作为在您列出的 P/Invoke 函数签名中看到。您的 UI 或命令行工具可以使用字符串,但您需要将它们转换为字节数组。

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

In the ReadProcessMemory call, I'm not understanding why lpBaseAddress is necessary. The OpenHandle I would normally place the string of the application, since I am directly editing it.

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

lpBuffer I assume is the actual array of bytes to read/write. The size I am not so sure about, and the lpNumberOfBytesRead is the number to read? Reciprocal questioning for WriteProcessMemory as well.

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

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


更重要的是如何实现您正在尝试做的事情:您正在尝试进行搜索和替换操作。搜索部分将是最困难的。我可以想到两种主要方法:

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

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

关于c# - 我如何通过扫描和仅替换字节数组来读/写处理内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3553778/

相关文章:

c# - 使用 Jenkins 通过 SVN 构建 C# 项目 - 构建成功,但输出在哪里?

c# - 鼠标点击事件坐标与找到的棋盘角坐标不匹配或对齐 - EmguCV/WPF

c# - 在 Xamarin Forms PCL 中从 Javascript 调用 C# 函数

c# - 实现个人用户帐户和 Azure AD 身份验证

c# - 获取编译时错误 CS0579 : Duplicate 'AssemblyFileVersionAttribute' attribute

c# - 寻找一些有趣的 C# 编程问题

c# - .Net 支票打印的 POS

c# - .NET配置系统中的拼写错误是设计缺陷吗?

c# - LINQ 序列 - 它们如何链接到 IL 中?

c# - 如何自动打印tiff文件?