Перейти к содержанию

Вопрос про чтение и запись в память на С++


Рекомендуемые сообщения

Я начинающий и еще не очень сильно разобрался в работе указателей на С++. Но мне нужно из процесса игры прочесть и сохранить три координаты и в нужный момент по нажатию клавиши все это записать в память. pID процесса и все что еще необходимо я нашел и написал(из видео уроков и msdn), но только не могу написать само прочтение и записаь в память. Кому не сложно объяснить помогите пожалуйста. Исходники если надо, то я скину. Вот эти самые адреса из которых надо читать, сохранять и писать

0xB6F5F0 - Указатель игрока (CPed)

(CPed+0x14) +0x30 = [dword] позиция по X-координате

(CPed+0x14) +0x34 = [dword] позиция по Y-координате

(CPed+0x14) +0x38 = [dword] позиция по Z-координате

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

Привет!

Есть две функции - [WriteProcessMemory] и [ReadProcessMemory]. Первая, значит,

пишет в память, а вторая её читает. В аргументах разобраться достаточно просто,

нужен хэндл целевого процесса, откуда читать\писать будешь, адрес (адресного

пространства процесса), куда будешь писать\читать, буфер, что писать или в

который читать, да и всё, в общем-то.

Как найти хэндл процесса я объяснять сейчас не буду, это ещё проще. Поясню

немного разве что про чтение указателей. Допустим, тебе нужно прочитать

указатель (возьму твой пример):

1. Читаешь "CPed + B6F5C0", получаешь DWORD (4 байта, адрес).

2. Прибавляешь к нему 0x30, т.е. смещение.

3. Читаешь ещё раз получившееся, опять получаешь DWORD.

4. Когда смещения кончились, ты прочитал уже значение - приводишь его к нужному

типу.

Т.е. прочитал адрес, прибавил смещение, прочитал, прибавил следующее, прочитал

и так далее, пока не прочитал уже само значение указателя. Примеры есть на

форуме (на плюсах - от [Coder], на шарпе можно у меня поискать (ссылка в

подписи или в местном разделе видео).

Как-то так.

/*---------------------------------------------------------------------------*/

  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

Привет!

Есть две функции - [WriteProcessMemory] и [ReadProcessMemory]. Первая, значит, пишет в память, а вторая её читает. В аргументах разобраться достаточно просто, нужен хэндл целевого процесса, откуда читать\писать будешь, адрес (адресного пространства процесса), куда будешь писать\читать, буфер, что писать или в который читать, да и всё, в общем-то.

Как найти хэндл процесса я объяснять сейчас не буду, это ещё проще. Поясню немного разве что про чтение указателей. Допустим, тебе нужно прочитать указатель (возьму твой пример):

1. Читаешь "CPed + B6F5C0", получаешь DWORD (4 байта, адрес).

2. Прибавляешь к нему 0x30, т.е. смещение.

3. Читаешь ещё раз получившееся, опять получаешь DWORD.

4. Когда смещения кончились, ты прочитал уже значение - приводишь его к нужному типу.

Т.е. прочитал адрес, прибавил смещение, прочитал, прибавил следующее, прочитал и так далее, пока не прочитал уже само значение указателя. Примеры есть на форуме (на плюсах - от [Coder], на шарпе можно у меня поискать (ссылка в подписи или в местном разделе видео).

Как-то так.

Как работают эти функции я разобрался из твоих уроков и уроков Codera, я не могу понять как с самого начала когда найти базовый адрес CPed, когда у нас есть адрес 0xB6F5F0 который хранит адрес CPed. И еще есть один непонятный момент куда читает функция ReadProcessMemory.

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

RPM читает в свой третий аргумент:

_Out_  LPVOID lpBuffer,

Указатель искать нужно каким-нибудь сканером памяти, вроде Cheat Engine, или

же я тебя неправильно понял.

/*---------------------------------------------------------------------------*/

Ссылка на комментарий
Поделиться на другие сайты

RPM читает в свой третий аргумент:

_Out_  LPVOID lpBuffer,

Указатель искать нужно каким-нибудь сканером памяти, вроде Cheat Engine, или же я тебя неправильно понял.

Да ты меня не правильно понял) В CE у меня уже все координаты найдены, теперь же я хочу, чтобы в любой момент времени я мог нажать клавишу и координаты записались(как делал ты в видео-уроке, но только я хчу реализовать на С++ и для трех осей), а потом нажать другую и опять вернуться на тоже место. И я не могу понять с чего начать читать потому что все что у меня есть в начале это указтель на CPed 0xB6F5F0 и я не знаю, как его прочитать, чтобы потом читать со смещениями. Как-то так) Сори если очень муторно по-другому я пока что не могу объянсить

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

С чтением указателей вся фишка в том, что их нужно читать по очереди. Типа,

есть цепочка:

0x1234567 + 0x12 + 0x15 + 0x20 = значение.

Порядок такой:

1. Прочитали 0x1234567 - там будет лежать адрес.

2. Прибавили к прочитанному адресу 0x12 (первое смещение) - получили новый

адрес.

3. Прочитали значение нового адреса - опять получаем адрес.

4. Прибавили к новому прочитанному адресу второе смещение (0x15), опять

получили новый адрес.

5. Прочитали.

6. Прибавили.

7. Прочитали.

8. Смещения кончились - значит мы прочитали уже значение указателя, а не

очередной его адрес из цепочки.

/*---------------------------------------------------------------------------*/

Ссылка на комментарий
Поделиться на другие сайты

С чтением указателей вся фишка в том, что их нужно читать по очереди. Типа, есть цепочка:

0x1234567 + 0x12 + 0x15 + 0x20 = значение.

Порядок такой:

1. Прочитали 0x1234567 - там будет лежать адрес.

2. Прибавили к прочитанному адресу 0x12 (первое смещение) - получили новый адрес.

3. Прочитали значение нового адреса - опять получаем адрес.

4. Прибавили к новому прочитанному адресу второе смещение (0x15), опять получили новый адрес.

5. Прочитали.

6. Прибавили.

7. Прочитали.

8. Смещения кончились - значит мы прочитали уже значение указателя, а не очередной его адрес из цепочки.

Спасибо большое если я правильно понял, то сейчас все получится.

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

Ты можешь посмотреть у меня в уроках, как это на C# делается. Принцип

абсолютно тот же самый, различий между ним и C++ там минимум - только в

синтаксисе.

/*---------------------------------------------------------------------------*/

Ссылка на комментарий
Поделиться на другие сайты

Ты можешь посмотреть у меня в уроках, как это на C# делается. Принцип абсолютно тот же самый, различий между ним и C++ там минимум - только в синтаксисе.

Я смотрел все твои уроки и кодера тоже. Именно после уроков мне и захотелось перевести все с СЕ на С++ потому, что он открывает еще большие просторы.

Ты можешь посмотреть у меня в уроках, как это на C# делается. Принцип абсолютно тот же самый, различий между ним и C++ там минимум - только в синтаксисе.

Keng можешь объяснить как хотя бы прочесть одну координату, я а дальше я на примере сдедлаю. Вот та часть которую я написал сейчас, в вот здесь послностью весь код https://yadi.sk/d/6nkwuunIZdgPq

case WM_KEYDOWN:

if(wParam == 0x49)

{

DWORD pID = UpdatePID("grand_theft_auto_san_andreas.dll");

DWORD offsets_coordX[2] = {0xE, 0x1E};

DWORD offsets_coordY[2] = {0xE, 0x22};

DWORD offsets_coordZ[2] = {0xE, 0x26};

MessageBox(hWnd,"Сохранение координат","Lol",MB_OK);

DWORD coord_X; DWORD coord_X1;

DWORD coord_Y; DWORD coord_Y1;

DWORD coord_Z; DWORD coord_Z1;

DWORD center = 0;

DWORD center_X = 0;

DWORD center_Y = 0;

DWORD center_Z = 0;

ReadProcessMemory(hWnd,(LPCVOID)Base, (LPVOID)CPed, sizeof(Base), NULL);

center = CPed + 0xE;

ReadProcessMemory(hWnd,(LPCVOID)center, (LPVOID)coord_X1, sizeof(center), NULL);

center_X = coord_X1 + 0x1E;

ReadProcessMemory(hWnd,(LPCVOID)center_X, (LPVOID)coord_X, sizeof(center_X), NULL);

ReadProcessMemory(hWnd,(LPCVOID)center, (LPVOID)coord_Y1, sizeof(center), NULL);

center_Y = coord_Y1 + 0x22;

ReadProcessMemory(hWnd,(LPCVOID)center_Y, (LPVOID)coord_Y, sizeof(center_Y), NULL);

ReadProcessMemory(hWnd,(LPCVOID)center, (LPVOID)coord_Z1, sizeof(center), NULL);

center_Z = coord_Z1 + 0x26;

ReadProcessMemory(hWnd,(LPCVOID)center_Z, (LPVOID)coord_Z, sizeof(center_Z), NULL);

}

Заранее спасибо.

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/


#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <string>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
//0x035EA564 + 0x40 + 0x3A8 + 0xC + 0x10 + 0x90 = 4 bytes DWORD

HWND hwnd = FindWindow(0, L"Assassin's Creed IV Black Flag");
DWORD value = 0;
DWORD addr = 0x035EA564;
DWORD pid;
printf("Handle: 0x%x\n", hwnd);
printf("Address: 0x%x\n", addr);
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_VM_READ, 0, pid);
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0x40;
printf("Old addr: 0x%X, offset: 0x40, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0x3A8;
printf("Old addr: 0x%X, offset: 0x3A8, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0xC;
printf("Old addr: 0x%X, offset: 0xC, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0x10;
printf("Old addr: 0x%X, offset: 0x10, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0x90;
printf("Old addr: 0x%X, offset: 0x90, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %d\n", value);
printf("Error: %d\n", GetLastError());

cin.get();
return 0;
}

Результат:

1555a041f8.png

В цикл или ещё как-нибудь красиво сам это завернёшь, я только подал идею.

/*---------------------------------------------------------------------------*/

  • Плюс 2
Ссылка на комментарий
Поделиться на другие сайты


#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <string>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
//0x035EA564 + 0x40 + 0x3A8 + 0xC + 0x10 + 0x90 = 4 bytes DWORD

HWND hwnd = FindWindow(0, L"Assassin's Creed IV Black Flag");
DWORD value = 0;
DWORD addr = 0x035EA564;
DWORD pid;
printf("Handle: 0x%x\n", hwnd);
printf("Address: 0x%x\n", addr);
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_VM_READ, 0, pid);
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0x40;
printf("Old addr: 0x%X, offset: 0x40, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0x3A8;
printf("Old addr: 0x%X, offset: 0x3A8, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0xC;
printf("Old addr: 0x%X, offset: 0xC, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0x10;
printf("Old addr: 0x%X, offset: 0x10, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %x\n", value);
printf("Error: %d\n", GetLastError());

addr = value + 0x90;
printf("Old addr: 0x%X, offset: 0x90, new addr: 0x%X\n", value, addr);
value = 0;
printf("Success: %d\n", ReadProcessMemory(phandle, (void*)addr, &value, sizeof(value), 0));
printf("Read: %d\n", value);
printf("Error: %d\n", GetLastError());

cin.get();
return 0;
}

Результат:

1555a041f8.png

В цикл или ещё как-нибудь красиво сам это завернёшь, я только подал идею.

Спасибо буду теперь доделывать, чтобы у меня все работало.

Ссылка на комментарий
Поделиться на другие сайты

Keng я как только не пробывал, но у меня постоянно не может прочесть Handle процесса, но есть одна странность, что значение в базы он читает, но не записывает и поэтому дальше чтение по со смещениями не идет. Я пробывал делать, как ты, но у меня все равно пишет unused <Чтение памяти невозможно> , хотя значение базы читает правильно, я проверял на отладке, но не записывает его. Я снимал защиту на чтение с помощью функции VirtualProtect, но все равно пишет, что чтение невозможно. Если у тебя будет свободная минутка, то можешь написать чтение на координату Х, а дальше я уже сам пойму.

Ссылка на комментарий
Поделиться на другие сайты

HWND hwnd = FindWindow(0, L"здесь имя окна игры");

Я делал так выдает ошибку 1 IntelliSense: аргумент типа "const wchar_t *" несовместим с параметром типа "LPCSTR" , а если удаляю букву L то переменная hwnd пустая и выдает ошибку unused <Чтение памяти невозможно>

.

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

Попробуй:

HWND hwnd = FindWindowA("0", "asdfg");

И проверь в свойствах проекта, как он относится к юникоду.

/*---------------------------------------------------------------------------*/

Ссылка на комментарий
Поделиться на другие сайты

Попробуй:

HWND hwnd = FindWindowA("0", "asdfg");

И проверь в свойствах проекта, как он относится к юникоду.

Вообщем попробывал, как ты сказал все тоже самое. Потом я решил начать писать все с нуля написал только чтение из памяти без всяких клавиш тупо вывод на консоль значений при каждом смещении, так все равно читате только то , что в базовом адресе и все дальше не идет. Я не знаю, что делать. Делал все, как показано у тебя в видео 1 к 1, только изменяется название игры и базовый адрес со смещениями

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

Предположу, что что-то не так. Можешь показать цепочку указателей в таблице

Cheat Engine и твой код на C++, который читает? Вряд ли в моём коде где-то

ошибка - проверил на нескольких указателях.

/*---------------------------------------------------------------------------*/

Ссылка на комментарий
Поделиться на другие сайты

Предположу, что что-то не так. Можешь показать цепочку указателей в таблице Cheat Engine и твой код на C++, который читает? Вряд ли в моём коде где-то ошибка - проверил на нескольких указателях.

B3lfgj03Blw.jpgSRhhhlJlEPw.jpg

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

Покажи значение переменной CPed и из какого процесса ты читаешь

(вызов FindWindow).

/*---------------------------------------------------------------------------*/

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

Покажи значение переменной CPed и из какого процесса ты читаешь

(вызов FindWindow).

/*---------------------------------------------------------------------------*/

SCnnMOIrToA.jpg

А во время исполнения программы значение CPed == содержимому Base

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

Интересно!

А в диспетчере задач процесс прям такой и висит - с "dll" на конце? Не "exe"?

У меня есть подозрение, что ты не в том процессе ищешь.

/*---------------------------------------------------------------------------*/

Ссылка на комментарий
Поделиться на другие сайты

/*---------------------------------------------------------------------------*/

Интересно!

А в диспетчере задач процесс прям такой и висит - с "dll" на конце? Не "exe"?

У меня есть подозрение, что ты не в том процессе ищешь.

/*---------------------------------------------------------------------------*/

VfGCjfbh6kU.jpg

pID определяет правильно с таким названием и CE подключается к этому же процессу

Ссылка на комментарий
Поделиться на другие сайты

Хм, ну в принципе читать по смещениям это не так уж и сложно должно быть..  Недавно делал похожее...

Могу глянуть если проблема именно в получении hWnd окна или процесса...

 

Или проблема уже решена?

 

Ну а так то я заметил что ты не верно написал смещения, в СЕ у тебя стоит первое же смещение "0x14" а ты читаешь "0xE", это же вроде разные значения, или я ошибаюсь?

 

И еще не знаю как в C++, но я когда писал на C# чтение адресов то у меня была проблема что я хранил прочтенные адреса в int вместо uint, так что в эту сторону можешь тоже глянуть, мне помогло..

Ссылка на комментарий
Поделиться на другие сайты

Хм, ну в принципе читать по смещениям это не так уж и сложно должно быть..  Недавно делал похожее...

Могу глянуть если проблема именно в получении hWnd окна или процесса...

 

Или проблема уже решена?

 

Ну а так то я заметил что ты не верно написал смещения, в СЕ у тебя стоит первое же смещение "0x14" а ты читаешь "0xE", это же вроде разные значения, или я ошибаюсь?

 

И еще не знаю как в C++, но я когда писал на C# чтение адресов то у меня была проблема что я хранил прочтенные адреса в int вместо uint, так что в эту сторону можешь тоже глянуть, мне помогло..

 

Проблемане решена, если не сложно, то можем глянуть вместе в скайпе(lol_44_lol) или в RC.  А по поводу смещений, да я не прав, но все равно дело до них не доходит, ошибка возникает в другом.

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.