You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ReadProcessMemory无法读取Notepad.exe输入文本,求问题排查

问题描述

我编写了如下C#代码尝试读取Notepad.exe的内存,虽然成功读取了内存内容,但无法找到我在记事本中输入的“Hello World!”文本。请问问题出在哪里?

操作步骤:在Win11Pro系统中打开Notepad.exe,输入“Hello World!”后运行上述代码。我不确定问题出在UTF8编码转换错误,还是读取了错误的模块?

using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace MemoryAcessor;

public partial class MemoryRead
{
    const int PROCESS_WM_READ = 0x0010;

    [LibraryImport("kernel32.dll")]
    public static partial IntPtr OpenProcess(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);

    [LibraryImport("kernel32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static partial bool ReadProcessMemory(IntPtr hProcess, Int64 lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);  

    public static void Main()
    {
        Process process = Process.GetProcessesByName("Notepad")[0];
        IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false, (uint)process.Id);       
        
        byte[] buffer = new byte[1<<25];
        var result = ReadProcessMemory(processHandle, process.MainModule!.BaseAddress, buffer, buffer.Length, out var bytesRead);

        Console.WriteLine($"Result: {result} ({bytesRead} bytes)");
        Console.WriteLine("=======================");
        Console.WriteLine(buffer[0..(int)bytesRead]);
        Console.WriteLine("=======================");
        Console.WriteLine(Encoding.UTF8.GetString(buffer[0..(int)bytesRead]));
        Console.ReadLine();
    }
}
问题原因及解决思路

1. 读取了错误的内存区域

你当前读取的是process.MainModule.BaseAddress,也就是Notepad.exe程序本身的代码段(可执行文件加载到内存的基地址),而记事本中输入的文本存储在进程的堆内存或私有内存区域,并非主模块的代码区域。主模块仅包含程序指令和静态资源,不会存放用户输入的动态内容。

2. 编码方式错误

Windows记事本默认使用**UTF-16LE(Unicode)**编码存储用户输入的文本,而非UTF-8。即便找到了正确的内存区域,用UTF-8解码也会得到乱码,无法识别目标文本。

3. 内存地址参数类型不匹配

ReadProcessMemory的lpBaseAddress原生参数是LPCVOID(即void*),对应C#的IntPtr,但你的代码中声明为Int64。在64位系统中虽然能隐式转换,但这种声明不符合规范,可能导致地址传递错误。

修正方向
  • 遍历进程内存区域:使用VirtualQueryEx枚举目标进程的所有内存块,筛选出带有MEM_COMMIT属性且可读取的私有内存区域(用户输入通常存放在这类区域)。
  • 切换解码编码:找到对应内存区域后,用Encoding.Unicode.GetString()(即UTF-16LE)解码内容。
  • 修正API声明:将ReadProcessMemory的lpBaseAddress参数改为IntPtr,匹配原生API的参数类型。

内容的提问来源于stack exchange,提问作者infinitezero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:46:28