c# - 用偏移量读取内存值的通用方法
问题描述
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern int ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[In, Out] byte[] buffer, int size, out IntPtr lpNumberOfBytesRead);
private byte[] ReadBytes(Process process, MemoryAddress address, int bytesToRead)
{
var value = new byte[bytesToRead];
var baseAddress = GetBaseAddressByModuleName(process, address.Module.Value) + address.BaseAddress;
var handle = GetProcessHandle(process);
ReadProcessMemory(handle, (IntPtr)baseAddress, value, bytesToRead, out var bytesRead);
foreach (var offset in address.Offsets)
{
ReadProcessMemory(handle,
new IntPtr(BitConverter.ToInt32(value, 0) + offset),
value,
bytesToRead,
out bytesRead);
}
return value;
}
private static int GetSize<T>()
{
return Marshal.SizeOf(typeof(T));
}
这与 float、int、double 和 strings 一起工作正常:
public long ReadLong(Process process, MemoryAddress address)
{
return ReadBytes(process, address, GetSize<long>()).ConvertTo<long>();
}
这是我的问题(ConvertTo
只是使用的扩展BitConverter
。):
public short ReadShort(Process process, MemoryAddress address)
{
return ReadBytes(process, address, GetSize<short>()).ConvertTo<short>();
}
public byte ReadByte(Process process, MemoryAddress address)
{
return ReadBytes(process, address, 1)[0];
}
使用这些方法时,会在 foreach 循环中引发异常ReadBytes
:System.ArgumentException: 'Destination array is not long enough to copy all the items in the collection. Check array index and length.'
我想它与BitConverter.ToInt32
. 使用ToInt16
forshort
可以消除异常,但会产生错误的结果。如何正确对待偏移量short
和byte
值?
解决方案
我明白你现在在做什么——你正在跟踪一系列对象引用,这些引用指向存储在最后一个对象中的值。像这样的东西应该适用于 32 位地址指针,这听起来像你正在做的事情:
private byte[] ReadBytes(Process process, MemoryAddress address, int bytesToRead)
{
var value = new byte[bytesToRead];
var currentAddress = new byte[4];
var baseAddress = GetBaseAddressByModuleName(process, address.Module.Value) + address.BaseAddress;
var handle = GetProcessHandle(process);
ReadProcessMemory(handle, (IntPtr)baseAddress, currentAddress, 4, out var bytesRead);
foreach (var offset in address.Offsets.Take(address.Offsets.Length - 1))
{
ReadProcessMemory(handle,
new IntPtr(BitConverter.ToInt32(currentAddress, 0) + offset),
currentAddress,
4,
out bytesRead);
}
ReadProcessMemory(handle,
new IntPtr(BitConverter.ToInt32(currentAddress, 0) + address.Offsets.Last()),
value,
bytesToRead,
out bytesRead);
return value;
}
推荐阅读
- angular - getDisplayMedia 需要用户手势来执行
- r - 如何将今天的日期附加到文件名中以保存为 Excel 工作簿?
- mongodb - 查询 MongoDB 嵌套文档并找到完全匹配的内部对象,其中一个过滤器将其自己的字段值作为条件
- ios - 每当我更改文件时,SwiftUI Preview 都会暂停
- php - POST 请求在被第三个应用调用时返回空,但在手动调用时不返回
- python - 从 x_train 和 y_train 创建数据集
- swift - 通过 DidDismiss 再次调用广告 - Swift
- r - 如何在 Rstudio 的源窗格中渲染 stargazer 的输出?
- swift - pod trunk push - 错误:意外的重复任务
- geocode - 这里地图 - 地理编码 API - 报告错误的邮政编码