ReadProcessMemory
通过此 P/Invoke 签名调用 C# 时,我遇到了一些非常奇怪的行为:
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
int dwSize,
out int lpNumberOfBytesRead
);
在我的应用程序中,我正在扫描具有读写访问权限的内存区域的整个内存(并且应用了更多过滤器,不过这是另一部分)。
扫描部分的代码是这样的:
int numberOfBytes;
if (!NativeMethods.ReadProcessMemory(handle, region.StartAddress,
buffer, (int)region.RegionSize, out numberOfBytes))
// The handle, region (custom struct containing some fields from the
// MEMORY_BASIC_INFORMATION struct), and buffer come from parameters.
并且代码完美运行。它扫描整个内存以查找字节序列。那里没有问题。
在我的程序流程中更进一步,我有这个代码:
注意:它使用与前面的代码相同的句柄 IntPtr(检查它)并且它在同一个线程中运行
int bytesRead;
byte[] buffer = new byte[128]; // In my real app this is some calculated value
// however that irrelevant. It's calculated 128.
if (!NativeMethods.ReadProcessMemory(handle, location.Location,
buffer, buffer.Length, out bytesRead))
continue; // Error while reading
// At this point buffer == null, so the next line causes an exception
if (bytesRead != buffer.Length) continue;
代码非常相似,但由于某种原因,对缓冲区的引用丢失并且缓冲区设置为空。如果它不是外部调用,我会 100% 确定这是一个错误,因为缓冲区没有作为ref
或out
参数传递。但是我知道 .NET 在外部调用(例如编组)时会做一些伏都教的事情。
使情况更加奇怪的是,当我将该代码替换为:
int bytesRead;
byte[] buffer = new byte[128];
byte[] bufferRef = buffer;
if (!NativeMethods.ReadProcessMemory(handle, location.Location,
buffer, buffer.Length, out bytesRead))
continue; // Error while reading
buffer = bufferRef;
if (bytesRead != buffer.Length) continue;
代码很简单。内存读取和所有!所以发生的所有事情都是由于某种原因buffer
变量失去了对实际缓冲区的引用。它把我搞糊涂了。
这种行为是由于我做错了什么(例如错误的 P/Invoke)造成的,它是否危险(泄漏内存?),并且可以解释?
我的配置:
- .NET 框架 4.0
- Visual Studio Professional 2012(版本 11.0.51106.01 更新 1)
- 已安装 .NET Framework 4.5.50709
- 以管理员身份运行
- 发生在发布和调试版本中,在 Visual Studio 主机可执行文件和常规构建可执行文件中。
- Windows 7 64 位
- 我正在读取内存的进程是 32 位的
- 构建配置:平台:任何 CPU
编辑:我正在使用的完整 NativeMethods 类可以在这里找到:http: //paste2.org/p/2770271
Edit2:我添加了解决问题的简单步骤,可以在此处找到答案。