Неверный дескриптор при использовании одной 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, с которыми проще работать таким образом. Вам не нужно этого делать, но я настоятельно рекомендую.