Неверный дескриптор при использовании одной HANDLE с двумя вызовами ReadProcessMemory

Я только начинаю изучать Windows API и хочу создать простую программу, которая будет считывать значения в заданном процессе.

Вот мой код

#include <stdio.h>
#include <Windows.h> 

void printError();

int main()
{
    int *buffer;

    // process input
    unsigned int pid = 0;
    printf("process ID : ");
    scanf("%d", &pid);
    getchar();
    HANDLE authorisation = OpenProcess(PROCESS_VM_READ, FALSE, pid);
    if(authorisation == NULL)
    {
        printf("OpenProcess Failed. GetLastError = %d", GetLastError());
        getchar();
        return EXIT_FAILURE;
    }   

    // adress memory input
    int *memoryAddress = 0x0;
    printf("memory address to read (in hexadecimal) : ");
    scanf("%p", &memoryAddress);
    getchar();
    printf("Reading from address : %p", memoryAddress);
    if(ReadProcessMemory(authorisation, (LPCVOID)memoryAddress, &buffer, 8, 
    NULL))
    {
        printf("\nptr2int = %p\n", buffer);
    }
    else
    {
        printError();    
    }

    int varInt = 0;
    // HERE IS THE PROBLEM
    // GetLastError return 6 : Invalid Handle 
    if(ReadProcessMemory(authorisation, (LPCVOID)buffer, &varInt, 
    sizeof(int), NULL))
    {
        printf("varInt = %d\n", varInt);
    }
    else
    {
        printError();
    }

    printf("Press ENTER to quit");
    getchar();

    return 0; 
}

void printError()
{
    printf("ReadProcessMemory Failed. GetLastError = %d", GetLastError());
    getchar();
    return EXIT_FAILURE;
}

Однако, если я создаю новый дескриптор для второго вызова RPM, он работает отлично.

Я прочитал это на MSDN:

Дескриптор, возвращенный функцией OpenProcess, может использоваться в любой функции, которая требует дескриптор процесса ".

Что я делаю неправильно?

1 ответ

Ваша проблема заключается в следующем:

int *buffer;
unsigned int pid = 0;

ReadProcessMemory(authorisation, (LPCVOID)memoryAddress, &buffer, 8, NULL);

Допустим, адрес буфера равен 0x0, а адрес pid - 0x4, потому что вы компилируете 32-битное приложение, а указатель составляет 4 байта. Когда вы вызываете RPM, вы жестко кодируете 8 байтов размером, что перезаписывает pid, делая его недействительным. Вы в основном переполнены буфером себя.

Всякий раз, когда вы используете ReadProcessMemory(), вы всегда должны использовать sizeof(originalVariable) в качестве аргумента числа байтов, чтобы у вас никогда не возникало проблем.

Если вы планируете часто получать доступ к памяти другого процесса, вам следует придерживаться этой практики:

Используйте uintptr_t для хранения адресов, а затем скомпилируйте свое приложение в соответствии с архитектурой целевого процесса. При компиляции для x64 это будет 8 байт, а для x86 - 4 байта. Вы также можете сделать свой собственный typedef, если хотите.

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

Другие вопросы по тегам