C# 高效扫描内存地址

本文关键字:地址 内存 扫描 高效 | 更新日期: 2023-09-27 18:25:41

我写了一个可以读写内存的内存编辑器类,但我需要做的是扫描程序的内存,并找到包含我正在搜索的内存的内存地址列表。

这是内存编辑器类。

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;
    }

它滞后非常严重,我只针对记事本。当我在作弊引擎中扫描内存时,它会立即找到它,没有任何延迟。我的程序从 0 扫描到 int 的最大值,但作弊引擎将其从 0 扫描到长整型的最大值,所以我不知道我做错了什么。

有什么方法可以有效地做到这一点吗?

C# 高效扫描内存地址

我马上就看到了几个问题。

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>