C#有效扫描内存地址

时间:2013-08-01 04:35:50

标签: c# memory editor

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

这是内存编辑器类。

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的最大值,所以我不知道我做错了什么。

我能以任何方式有效地做到这一点吗?

1 个答案:

答案 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>