WINAPI ReadProcessMemory всегда один и тот же адрес
-
12-12-2019 - |
Вопрос
Я прочитал некоторые данные из процесса (адрес:0x58F03C) с помощью функции WINAPI. ReadProcessMemory
:
DWORD proc_id;
GetWindowThreadProcessId(hwnd, &proc_id);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc_id);
int value=0;
while (1)
{
ReadProcessMemory(hProcess, (LPVOID)0x58F03C, &value, sizeof(value), 0);
cout << "val: " << value << endl;
}
Поскольку адрес меняется каждый раз, когда я перезапускаю процесс, мне интересно, есть ли способ всегда получать один и тот же адрес?Он должен быть, потому что я вижу много «программ-тренеров», которые способны на это.Как они получают правильное значение адреса для чтения/записи?
В настоящее время я получаю его путем сканирования значения с помощью CheatEngine
и выполните следующее сканирование для определения измененного значения.
Спасибо.
Решение
Вы столкнулись с динамическим распределением памяти.В мире CheatEngine они называются «указатели».
Рассмотрим некоторые данные (например, uint32_t
/DWORD
) внутри памяти, которая была malloc
'д.Если вы найдете адрес данных, нет никакой гарантии, что при следующем запуске процесса адрес будет тот же.Это связано с тем, что память, возвращаемая malloc
может быть основано в другой точке памяти.
Хитрость, используемая для обхода динамического распределения памяти, заключается в том, чтобы найти адрес статической кучи, который может привести вас к адресу интересующего вас значения.Учебник CheatEngine покажет вам, как это делается.То же самое относится и к многоуровневым указателям.На более высоком уровне это соответствует динамически выделяемой памяти, которая содержит указатель на некоторую другую динамически выделяемую память и так далее.
Метод, используемый в CheatEngine для получения указателей, работает примерно так:
- Установите аппаратную точку останова доступа по адресу интересующего вас значения данных.
- Когда код обращается к нему, аппаратная точка останова покажет вам, как выглядит код.
Обычно код будет выглядеть примерно так:
mov eax, 0x1234ABCD
dec dword ptr ds:[eax+0x85]
Это может соответствовать некоторому коду, который уменьшает ваше здоровье при ударе врагом.В данном случае 0x1234ABCD — это указатель, а 0x85 — смещение.В коде C это могло произойти:
struct some_struct* blah = malloc(...);
...
blah->HP--;
0x1234ABCD будет адресом blah
.Значение HP находится где-то внутри блока, на который указывает blah
.Смещение в блоке памяти равно 0x85.Тогда, если бы вы писали трейнер, вы бы прочитали DWORD
(QWORD
если 64-битный) по адресу 0x1234ABCD и добавьте к значению 0x85.Это даст вам адрес значения HP.
Другие советы
Это будет работать, если адрес находится в части исполняемости раздела данных, где проживает PrealLocated переменные (не подходит для кучи и стека) ...
Посмотрите на «Перечислять все модули для процесса» Пример на MSDN .
Это использует enumprocessmodules () Чтобы получить модульные ручки.Это являются базовыми адресами изображения.
Вы можете получить базовый адрес изображений для исполняемого и настроить свой адрес.