我编写了一个可以读写内存的内存编辑器类,但我需要做的是扫描程序的内存,找到包含我正在搜索的内存的内存地址列表。
这是内存编辑器类。
class MemoryEditor
{
public const uint DELETE = 0x00010000;
public const uint READ_CONTROL = 0x00020000;
public const uint WRITE_DAC = 0x00040000;
public const uint WRITE_OWNER = 0x00080000;
public const uint SYNCHRONIZE = 0x00100000;
public const uint END = 0xFFF;
public const uint PROCESS_ALL_ACCESS = (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE | END);
public Process targetedProcess;
[DllImport("kernel32.dll")]
public static extern int OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesWritten);
public Process targetProcess(string name, int index = 0)
{
return (targetedProcess = Process.GetProcessesByName(name)[index]);
}
public int getHandle(Process proc, uint access = PROCESS_ALL_ACCESS)
{
return OpenProcess(access, false, proc.Id);
}
public byte[] getBytesFromString(string str)
{
return Encoding.Unicode.GetBytes(str);
}
public string getStringFromBytes(byte[] byteArr)
{
return Encoding.Unicode.GetString(byteArr);
}
public int makeHex(string str)
{
return (int.Parse(str, System.Globalization.NumberStyles.HexNumber));
}
public byte[] ReadMemory(int address, int processSize)
{
byte[] buffer = new byte[processSize];
ReadProcessMemory(getHandle(targetedProcess), address, buffer, processSize, 0);
return buffer;
}
public List<int> GetAddress(byte[] memory, int index = 0)
{
List<int> buf = new List<int>();
for (int i = 0; i < int.MaxValue; i++)
if (ReadMemory(makeHex(i.ToString()), 1) == memory)
buf.Add(i);
return buf;
}
public void WriteMemory(int address, byte[] processBytes)
{
WriteProcessMemory(getHandle(targetedProcess), address, processBytes, processBytes.Length, 0);
}
public int GetObjectSize(object TestObject)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
byte[] Array;
bf.Serialize(ms, TestObject);
Array = ms.ToArray();
return Array.Length;
}
}
这是尝试查找内存地址的函数
public List<int> GetAddress(byte[] memory, int index = 0)
{
List<int> buf = new List<int>();
for (int i = 0; i < int.MaxValue; i++)
if (ReadMemory(makeHex(i.ToString()), 1) == memory)
buf.Add(i);
return buf;
}
它严重滞后,我只针对记事本。当我在Cheat Engine中扫描内存时,它立即找到它,没有任何延迟。我的程序从0扫描到int的最大值,但是Cheat Engine将它设为0到long的最大值,所以我不知道我做错了什么。
我能以任何方式有效地做到这一点吗?
答案 0 :(得分:2)
我马上就看到了几个问题。
1。您一次只能读取一个字节:
ReadMemory(makeHex(i.ToString()), 1)
我不确定,但我认为调用ReadProcessMemory
需要执行系统调用,而每个字节执行此操作肯定是一个来源慢一点。相反,您应该读取一些大小的“块”,然后在您的过程中扫描该块。 (一次做一页可能是最有效的。)
2。为什么在这个世界上,您是否正在对字符串进行所有转换?!
public int makeHex(string str)
{
return (int.Parse(str, System.Globalization.NumberStyles.HexNumber));
}
....
for (int i = 0; i < int.MaxValue; i++)
if (ReadMemory(makeHex(i.ToString()), 1) == memory)
该循环的每次迭代,您将i
转换为字符串(默认值,十进制 - 而不是十六进制),然后立即将其传递给makeHex
来解析它(作为十六进制,总是)回到整数。这有什么意义?只需传递整数!这些转换可能非常昂贵。
<pedantic>
顺便说一下,名称“makeHex
”没有意义 - 它来自十六进制并且生成一个整数。</pedantic>
< / p>