【问题标题】:How do I find strings inside a memory dumped byte array converted to UTF8 encoded string?如何在转换为 UTF8 编码字符串的内存转储字节数组中找到字符串?
【发布时间】:2017-01-27 01:02:11
【问题描述】:

我正在开发一个视频游戏作弊引擎,它利用简单的内存操作来实现其目标。我已经成功地编写了一段代码,将进程的内存转储到 byte[] 并遍历这些数组以搜索所需的字符串。搜索的代码是这样的:

    public bool FindString(byte[] bytes, string pName, long offset)
    {
        string s = System.Text.Encoding.UTF8.GetString(bytes);
        var match = Regex.Match(s, "test");
        if (match.Success)
            return true;
        return false;
    }

然后我打开一个 32 位版本的记事本(因为这是我的转储方法的条件)并在其中键入单词“test”并在调试模式下运行我的程序以查看是否曾经遇到过条件.它不是。

经过进一步检查,我在其中一次迭代中检查了“s”字符串的内容,因此是:

\0\0\0\0\0\0\0\0���\f\0\u0001����\u0001\0\0\0 \u0001�\0\0\0\0\0          \u0001�\0\0\0\0\0\0\0�\0\0\0\0\0\0\0�\0\0\0\0\0\u0010\0\0\0\0\0\0\0 \a�\0\0\0\0\0\0\0�\0\0\0\0\0\u000f\0\0\0\u0001\0\0\0\0\0\0\0\0\0\0\0�\u000f�\0\0\0\0\0�\u000f�\0\0\0\0\0\0�\0\0\0\0\0\0\0\0\0\0\0\0\u0010\0\0\0\0\0\0\0\0\0����\f\0\0\0\0\0\0\0�\0\0����\0\0\0\0\0\0\u0010\0\0\0\0\0\0 \0\0\0\0\0\0\0\u0001\0\0\0\0\0\0\0\u0010\0\0\0\0\0\0�\0\0\0\0\0\0\0�����\u007f\0\0\u0002\0�\u0002\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0�\u000f�\0\0\0\0\0�\u000f�\0\0\0\0\0\u001f\0\0\0\0\0\0\0��������\u0010\u0001�\0\0\0\0\0\u0010\u0001�\0\0\0\0\0\u0018\0�\0\0\0\0\0\u0018\0�\0\0\0\0\0\0\0\0\0\0\0\0\0�\u0002�\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00\a�\0\0\0\0\00\a�\0\0\0\0\0�\u0002�\0\0\0\0\0�M�^\u000e\u000e_\u007f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\u0001\0\0\0\0\0\0\u0010\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\u0001\0\0\0\u0001\0\0\0\0\0\0\0\0\0\0\0\b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\u0001\0\0\0\b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\a\0\0\0\0\0\0`\a\0\0\0\0\0\0\u0004\0\0\0\0\0\0\0\0�\u001f\0\0\0\0\0�\u001d\u0014)�\u007f\0\0����\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0�\a\0\u0002\0\0\0\0\0\0\0\0\0\0\0\0�\0\0\0\0\0\0\0\u0001\0\0\0\u0001\0\0\0\0\0\0\0\0\0\0\0P\u0001�\0\0\0\0\0\0\u0003�\0\0\0\0\0\u0010\u0003�\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0�

我继续检查这个方法的每个传递的's'变量,发现我看不到任何这种格式的字符串。

我的问题很简单。我做错了什么,我找不到这个字符串?转储成功了,但与我的解析方法有关的事情给我带来了麻烦。

UPDATE(转储内存的代码)

    void ScanProcess(Process process)
    {
        // getting minimum & maximum address
        var sys_info = new SYSTEM_INFO();
        GetSystemInfo(out sys_info);
        var proc_min_address = sys_info.minimumApplicationAddress;
        var proc_max_address = sys_info.maximumApplicationAddress;
        var proc_min_address_l = (long)proc_min_address;
        var proc_max_address_l = (long)proc_max_address;

        //Opening the process with desired access level
        var processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false, process.Id);
        var mem_basic_info = new MEMORY_BASIC_INFORMATION();
        var bytesRead = 0;  // number of bytes read with ReadProcessMemory

        while (proc_min_address_l < proc_max_address_l)
        {
            VirtualQueryEx(processHandle, proc_min_address, out mem_basic_info, 28); //28 = sizeof(MEMORY_BASIC_INFORMATION)

            //If this memory chunk is accessible
            if (mem_basic_info.Protect == PAGE_READWRITE && mem_basic_info.State == MEM_COMMIT)
            {
                //Read everything into a buffer
                byte[] buffer = new byte[mem_basic_info.RegionSize];
                ReadProcessMemory((int)processHandle, mem_basic_info.BaseAddress, buffer, mem_basic_info.RegionSize, ref bytesRead);

                var MemScanner = new MemScan();
                Memscanner.FindString(buffer, process.ProcessName, proc_max_address_l);
            }

            // move to the next memory chunk
            proc_min_address_l += mem_basic_info.RegionSize;
            proc_min_address = new IntPtr(proc_min_address_l);

            if (mem_basic_info.RegionSize == 0)
            {
                break;
                mem_basic_info.RegionSize = 4096;
            }
        }
    }

【问题讨论】:

  • 也许问题不在于搜索,而在于转储和随后加载所述转储
  • 已更新转储代码。这是一种非常标准的方法。
  • 感谢更新

标签: c# regex parsing ram dump


【解决方案1】:

我不知道MemScan.FindString() 做了什么,但我想问题是您正在搜索字符串中的字符串,而不是字节数组中的字节数组。

通过使用System.Text.Encoding.UTF8.GetString(bytes); 转换内存内容,您假设存储在内存中的所有内容都可以解释为有效的UTF8 编码。

您的FindString() 必须接受参数为byte[] 而不是string,并且您需要弄清楚进程名称是如何存储在内存中的(很可能是UTF-16)。

【讨论】:

  • FindString 在这篇文章中定义,在它的顶部,它接受字节数组。
  • 哦,我忽略了这一点。尽管如此,问题仍然存在,进程名称是如何在内存中编码的,您需要在字节级别进行搜索,而不是字符串。见stackoverflow.com/questions/4859023
【解决方案2】:

对于初学者,您不能使用记事本(或任何非二进制查看工具来查看您的字节)。

您需要使用 BitConverter API:

https://msdn.microsoft.com/en-us/library/system.bitconverter(v=vs.110).aspx

...遍历数据并编写/搜索数据以找到您要查找的内容(记住您转储数据的任何编码)。

顺便说一句 - 这是一个有用的 HexEditor:http://www.hexworkshop.com/

【讨论】:

  • “对于初学者,您不能使用记事本(或任何非二进制查看工具来查看您的字节)。” - OP 没有尝试 在记事本中查看二进制内容 而不是他将其用作测试平台,以在单词 "test" 出现在内存中时进行触发,例如在 NotePad 中键入单词test
猜你喜欢
  • 2012-07-17
  • 2013-09-14
  • 2011-01-18
  • 2017-05-18
  • 2013-09-12
  • 1970-01-01
  • 2015-03-15
  • 2011-04-30
  • 2014-01-29
相关资源
最近更新 更多