Вопрос по c++, windows, winapi – Чтение процесса из памяти процесса не возвращает все

4

Я пытаюсь просканировать память стороннего приложения. Я уже узнал адрес; сейчас на0x0643FB78, Дело в том, что я никогда не смогу там подняться, так какLPMODULEENTRY32->modBaseAddr является0x00400000 а такжеLPMODULEENTRY32->modBaseSize это просто0x006FF000таким образом, максимальный адрес, который я могу сканировать для этого модуля,0x00AFF000.

Означает ли это, что адрес, который я ищу, живет в другом процессе / модуле / потоке / чем-то? Я вполне уверен, что процесс, который я имею, содержит адрес. Как мне тогда получить доступ к памяти? Спасибо.

MODULEENTRY дает вам адресаcode, Наверняка вас больше интересуют данные? Это может появиться где угодно, в зависимости от того, где Windows выделил кучу. Или, надеюсь, раздел данных, поскольку у вас будет мало надежды на повторение этого адреса, если он действительно находится в куче. Используйте VirtualQueryEx () для перечисления выделений в адресном пространстве. Hans Passant

Ваш Ответ

2   ответа
9

LPMODULEENTRY Возможно, вы начинаете не в том направлении. Я бы прошел через блоки памяти в целевом процессе сVirtualQueryEx вместо. Это даст вамMEMORY_BASIC_INFORMATION о каждом блоке в этом процессе. Вы можете использоватьReadProcessMemory и просматривайте блоки, чтобы найти то, что вы ищете.

Вот некоторый старый код, который я написал, чтобы сделать примерно то же самое, но ищет строку, а не указатель:

#include <iostream>
#include <vector>
#include <string>
#include <windows.h>
#include <algorithm>
#include <iterator>

template <class InIter1, class InIter2, class OutIter>
void find_all(unsigned char *base, InIter1 buf_start, InIter1 buf_end, InIter2 pat_start, InIter2 pat_end, OutIter res) {
    for (InIter1 pos = buf_start;
        buf_end!=(pos=std::search(pos, buf_end, pat_start, pat_end));
        ++pos)
    {
        *res++ = base+(pos-buf_start);
    }
}

template <class outIter>
void find_locs(HANDLE process, std::string const &pattern, outIter output) {

    unsigned char *p = NULL;
    MEMORY_BASIC_INFORMATION info;

    for ( p = NULL;
        VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info);
        p += info.RegionSize ) 
    {
        std::vector<char> buffer;

        if (info.State == MEM_COMMIT && 
            (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE)) 
        {
            SIZE_T bytes_read;
            buffer.resize(info.RegionSize);
            ReadProcessMemory(process, p, &buffer[0], info.RegionSize, &bytes_read);
            buffer.resize(bytes_read);
            find_all(p, buffer.begin(), buffer.end(), pattern.begin(), pattern.end(), output);
        }
    }
}

int main(int argc, char **argv) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <process ID> <pattern>", argv[0]);
        return 1;
    }

    int pid;
    sscanf(argv[1], "%i", &pid);

    std::string pattern(argv[2]);

    HANDLE process = OpenProcess( 
        PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 
        false,
        pid);

    find_locs(process, pattern, 
        std::ostream_iterator<void *>(std::cout, "\n"));

    return 0;
}
Замечательно, это, несомненно, поставит меня на правильный путь. Спасибо. Mikulas Dite
@GuyAvraham: данные дословно копируются из целевого процесса, поэтому они в любом формате, который используется целевым процессом.pos это остаток от более ранней версии кода - он вообще не используется.
@ Джерри Гроб - +1 за отличный ответ. Две вещи, которые я хотел бы задать далее: 1) После того, как я прочитал содержимое страницы в символьный векторstd::vector<char> buffer - как мне "лечить"? Это ? Я имею в виду, содержит ли он символы ASCII или символы в кодировке UTF-8 / UTF-16? Если в памяти содержатся символы ASCII, как мне преобразовать их в Unicode (я думаю, это должен быть UTF-16)? 2) Для чего именноstd::vector<char>::iterator pos используется для ? Ваша помощь очень ценится!
3

которые отображаются с определенными средствами защиты. Эти страницы заключены в модули. Каждый модуль имеет базу и размер. Однако ReadProcessMemory полностью абстрагируется от вас. Вы должны быть в состоянии читать память независимо от того, в каком модуле она находится.

В этом случае память находится не в модуле, который вы просматриваете. Если вам нужно найти, где он находится, вы можете перебирать модули и проверять базу и размер с помощью CreateToolHelp32Snapshot, Module32First и Module32Next.

Разместите некоторый код, и мы поможем вам выяснить, где вы ошиблись. Почему вы так уверены, что адрес того, что вы ищете, является адресом, который вы указали? Адреса часто указываются с базовым модулем + смещение из-за ASLR. Как вы получаете целевой процесс управления? У вас должны быть определенные права доступа для использования ReadProcessMemory.

Спасибо, это понимание, которого мне не хватало. Я принял ответ Джерри, потому что он получил пример кода. Mikulas Dite

Похожие вопросы