Как найти строки внутри массива байтов с дампом памяти, преобразованного в строку в кодировке UTF8?

Я работаю над чит-движком для видеоигр, который использует простые манипуляции с памятью для достижения своей цели. Мне удалось написать фрагмент кода, который сбрасывает память процесса в 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-разрядную версию блокнота (поскольку для этого предназначен мой метод дампа), набираю в нем слово «тест» и запускаю свою программу в режиме отладки, чтобы увидеть, выполняется ли когда-либо условие. Это не.

При дальнейшем осмотре я проверяю содержимое строки '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' и обнаружил, что не вижу никаких строк в этом формате.

Мой вопрос прост. Что я делаю не так, что не могу найти эту строку? Сброс выполняется успешно, но что-то, связанное с моим методом разбора, вызывает у меня проблемы.

ОБНОВЛЕНИЕ (код для дампа памяти)

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

person Steffon Scott    schedule 27.01.2017    source источник
comment
Ну может проблема не в поиске, а в сбросе и последующей загрузке упомянутого дампа?   -  person MickyD    schedule 27.01.2017
comment
Обновлен кодом дампа. Это довольно стандартный метод, плавающий вокруг.   -  person Steffon Scott    schedule 27.01.2017
comment
Спасибо за обновление   -  person MickyD    schedule 27.01.2017


Ответы (2)


Я не знаю, что делает MemScan.FindString(), но я думаю, проблема в том, что вы ищете строку для строки, а не для массива байтов в массиве байтов.

Преобразовывая содержимое памяти с помощью System.Text.Encoding.UTF8.GetString(bytes);, вы предполагаете, что все, что хранится в памяти, может быть интерпретировано как допустимая кодировка UTF8.

Ваш FindString() должен принимать параметры как byte[], а не string, и вам нужно выяснить, как имя процесса хранится в памяти (скорее всего, UTF-16).

person devio    schedule 27.01.2017
comment
FindString определен в этом посте вверху, и он принимает байтовые массивы. - person Steffon Scott; 27.01.2017
comment
О, это я упустил из виду. Тем не менее, остается вопрос, как имя процесса кодируется в памяти, и искать нужно на уровне байтов, а не по строкам. См. stackoverflow.com/questions/4859023. - person devio; 27.01.2017

Во-первых, вы не можете использовать Блокнот (или любой небинарный инструмент просмотра для просмотра ваших байтов).

Вам нужно использовать API BitConverter:

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

... для просмотра данных и составления/поиска данных, чтобы найти то, что вы ищете (сохраняя в памяти любую кодировку, которую вы сбросили данные).

Кстати, вот полезный HexEditor: http://www.hexworkshop.com/

person curveto    schedule 27.01.2017
comment
Во-первых, вы не можете использовать Блокнот (или любой другой инструмент просмотра, не поддерживающий двоичный код, для просмотра ваших байтов). — OP не пытается просмотреть двоичный контент в Блокноте, а он использует его в качестве испытательного стенда для запуска, когда слово test появляется в памяти, например, при вводе слова test в NotePad - person MickyD; 27.01.2017