Chusa Опубликовано 13 августа, 2014 Поделиться Опубликовано 13 августа, 2014 Я начинающий и еще не очень сильно разобрался в работе указателей на С++. Но мне нужно из процесса игры прочесть и сохранить три координаты и в нужный момент по нажатию клавиши все это записать в память. pID процесса и все что еще необходимо я нашел и написал(из видео уроков и msdn), но только не могу написать само прочтение и записаь в память. Кому не сложно объяснить помогите пожалуйста. Исходники если надо, то я скину. Вот эти самые адреса из которых надо читать, сохранять и писать0xB6F5F0 - Указатель игрока (CPed)(CPed+0x14) +0x30 = [dword] позиция по X-координате(CPed+0x14) +0x34 = [dword] позиция по Y-координате(CPed+0x14) +0x38 = [dword] позиция по Z-координате Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 14 августа, 2014 Поделиться Опубликовано 14 августа, 2014 /*---------------------------------------------------------------------------*/Привет!Есть две функции - [WriteProcessMemory] и [ReadProcessMemory]. Первая, значит, пишет в память, а вторая её читает. В аргументах разобраться достаточно просто, нужен хэндл целевого процесса, откуда читать\писать будешь, адрес (адресного пространства процесса), куда будешь писать\читать, буфер, что писать или в который читать, да и всё, в общем-то.Как найти хэндл процесса я объяснять сейчас не буду, это ещё проще. Поясню немного разве что про чтение указателей. Допустим, тебе нужно прочитать указатель (возьму твой пример):1. Читаешь "CPed + B6F5C0", получаешь DWORD (4 байта, адрес).2. Прибавляешь к нему 0x30, т.е. смещение.3. Читаешь ещё раз получившееся, опять получаешь DWORD.4. Когда смещения кончились, ты прочитал уже значение - приводишь его к нужному типу.Т.е. прочитал адрес, прибавил смещение, прочитал, прибавил следующее, прочитал и так далее, пока не прочитал уже само значение указателя. Примеры есть на форуме (на плюсах - от [Coder], на шарпе можно у меня поискать (ссылка в подписи или в местном разделе видео).Как-то так./*---------------------------------------------------------------------------*/ 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 14 августа, 2014 Автор Поделиться Опубликовано 14 августа, 2014 Привет!Есть две функции - [WriteProcessMemory] и [ReadProcessMemory]. Первая, значит, пишет в память, а вторая её читает. В аргументах разобраться достаточно просто, нужен хэндл целевого процесса, откуда читать\писать будешь, адрес (адресного пространства процесса), куда будешь писать\читать, буфер, что писать или в который читать, да и всё, в общем-то.Как найти хэндл процесса я объяснять сейчас не буду, это ещё проще. Поясню немного разве что про чтение указателей. Допустим, тебе нужно прочитать указатель (возьму твой пример):1. Читаешь "CPed + B6F5C0", получаешь DWORD (4 байта, адрес).2. Прибавляешь к нему 0x30, т.е. смещение.3. Читаешь ещё раз получившееся, опять получаешь DWORD.4. Когда смещения кончились, ты прочитал уже значение - приводишь его к нужному типу.Т.е. прочитал адрес, прибавил смещение, прочитал, прибавил следующее, прочитал и так далее, пока не прочитал уже само значение указателя. Примеры есть на форуме (на плюсах - от [Coder], на шарпе можно у меня поискать (ссылка в подписи или в местном разделе видео).Как-то так.Как работают эти функции я разобрался из твоих уроков и уроков Codera, я не могу понять как с самого начала когда найти базовый адрес CPed, когда у нас есть адрес 0xB6F5F0 который хранит адрес CPed. И еще есть один непонятный момент куда читает функция ReadProcessMemory. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 14 августа, 2014 Поделиться Опубликовано 14 августа, 2014 /*---------------------------------------------------------------------------*/RPM читает в свой третий аргумент:_Out_ LPVOID lpBuffer,Указатель искать нужно каким-нибудь сканером памяти, вроде Cheat Engine, или же я тебя неправильно понял./*---------------------------------------------------------------------------*/ Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 14 августа, 2014 Автор Поделиться Опубликовано 14 августа, 2014 RPM читает в свой третий аргумент:_Out_ LPVOID lpBuffer,Указатель искать нужно каким-нибудь сканером памяти, вроде Cheat Engine, или же я тебя неправильно понял.Да ты меня не правильно понял) В CE у меня уже все координаты найдены, теперь же я хочу, чтобы в любой момент времени я мог нажать клавишу и координаты записались(как делал ты в видео-уроке, но только я хчу реализовать на С++ и для трех осей), а потом нажать другую и опять вернуться на тоже место. И я не могу понять с чего начать читать потому что все что у меня есть в начале это указтель на CPed 0xB6F5F0 и я не знаю, как его прочитать, чтобы потом читать со смещениями. Как-то так) Сори если очень муторно по-другому я пока что не могу объянсить Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 14 августа, 2014 Поделиться Опубликовано 14 августа, 2014 /*---------------------------------------------------------------------------*/С чтением указателей вся фишка в том, что их нужно читать по очереди. Типа, есть цепочка:0x1234567 + 0x12 + 0x15 + 0x20 = значение.Порядок такой:1. Прочитали 0x1234567 - там будет лежать адрес.2. Прибавили к прочитанному адресу 0x12 (первое смещение) - получили новый адрес.3. Прочитали значение нового адреса - опять получаем адрес.4. Прибавили к новому прочитанному адресу второе смещение (0x15), опять получили новый адрес.5. Прочитали.6. Прибавили.7. Прочитали.8. Смещения кончились - значит мы прочитали уже значение указателя, а не очередной его адрес из цепочки./*---------------------------------------------------------------------------*/ Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 14 августа, 2014 Автор Поделиться Опубликовано 14 августа, 2014 С чтением указателей вся фишка в том, что их нужно читать по очереди. Типа, есть цепочка:0x1234567 + 0x12 + 0x15 + 0x20 = значение.Порядок такой:1. Прочитали 0x1234567 - там будет лежать адрес.2. Прибавили к прочитанному адресу 0x12 (первое смещение) - получили новый адрес.3. Прочитали значение нового адреса - опять получаем адрес.4. Прибавили к новому прочитанному адресу второе смещение (0x15), опять получили новый адрес.5. Прочитали.6. Прибавили.7. Прочитали.8. Смещения кончились - значит мы прочитали уже значение указателя, а не очередной его адрес из цепочки.Спасибо большое если я правильно понял, то сейчас все получится. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 14 августа, 2014 Поделиться Опубликовано 14 августа, 2014 /*---------------------------------------------------------------------------*/Ты можешь посмотреть у меня в уроках, как это на C# делается. Принцип абсолютно тот же самый, различий между ним и C++ там минимум - только в синтаксисе./*---------------------------------------------------------------------------*/ Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 14 августа, 2014 Автор Поделиться Опубликовано 14 августа, 2014 Ты можешь посмотреть у меня в уроках, как это на C# делается. Принцип абсолютно тот же самый, различий между ним и C++ там минимум - только в синтаксисе.Я смотрел все твои уроки и кодера тоже. Именно после уроков мне и захотелось перевести все с СЕ на С++ потому, что он открывает еще большие просторы.Ты можешь посмотреть у меня в уроках, как это на C# делается. Принцип абсолютно тот же самый, различий между ним и C++ там минимум - только в синтаксисе.Keng можешь объяснить как хотя бы прочесть одну координату, я а дальше я на примере сдедлаю. Вот та часть которую я написал сейчас, в вот здесь послностью весь код https://yadi.sk/d/6nkwuunIZdgPqcase 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);}Заранее спасибо. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 14 августа, 2014 Поделиться Опубликовано 14 августа, 2014 /*---------------------------------------------------------------------------*/#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 DWORDHWND 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;}Результат:В цикл или ещё как-нибудь красиво сам это завернёшь, я только подал идею./*---------------------------------------------------------------------------*/ 2 Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 14 августа, 2014 Автор Поделиться Опубликовано 14 августа, 2014 #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 DWORDHWND 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;}Результат:В цикл или ещё как-нибудь красиво сам это завернёшь, я только подал идею.Спасибо буду теперь доделывать, чтобы у меня все работало. Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 14 августа, 2014 Автор Поделиться Опубликовано 14 августа, 2014 Keng я как только не пробывал, но у меня постоянно не может прочесть Handle процесса, но есть одна странность, что значение в базы он читает, но не записывает и поэтому дальше чтение по со смещениями не идет. Я пробывал делать, как ты, но у меня все равно пишет unused <Чтение памяти невозможно> , хотя значение базы читает правильно, я проверял на отладке, но не записывает его. Я снимал защиту на чтение с помощью функции VirtualProtect, но все равно пишет, что чтение невозможно. Если у тебя будет свободная минутка, то можешь написать чтение на координату Х, а дальше я уже сам пойму. Ссылка на комментарий Поделиться на другие сайты Поделиться
Coder Опубликовано 15 августа, 2014 Поделиться Опубликовано 15 августа, 2014 HWND hwnd = FindWindow(0, L"здесь имя окна игры"); Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 15 августа, 2014 Автор Поделиться Опубликовано 15 августа, 2014 HWND hwnd = FindWindow(0, L"здесь имя окна игры");Я делал так выдает ошибку 1 IntelliSense: аргумент типа "const wchar_t *" несовместим с параметром типа "LPCSTR" , а если удаляю букву L то переменная hwnd пустая и выдает ошибку unused <Чтение памяти невозможно>. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 15 августа, 2014 Поделиться Опубликовано 15 августа, 2014 /*---------------------------------------------------------------------------*/Попробуй: HWND hwnd = FindWindowA("0", "asdfg");И проверь в свойствах проекта, как он относится к юникоду./*---------------------------------------------------------------------------*/ Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 15 августа, 2014 Автор Поделиться Опубликовано 15 августа, 2014 Попробуй: HWND hwnd = FindWindowA("0", "asdfg");И проверь в свойствах проекта, как он относится к юникоду.Вообщем попробывал, как ты сказал все тоже самое. Потом я решил начать писать все с нуля написал только чтение из памяти без всяких клавиш тупо вывод на консоль значений при каждом смещении, так все равно читате только то , что в базовом адресе и все дальше не идет. Я не знаю, что делать. Делал все, как показано у тебя в видео 1 к 1, только изменяется название игры и базовый адрес со смещениями Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 15 августа, 2014 Поделиться Опубликовано 15 августа, 2014 /*---------------------------------------------------------------------------*/Предположу, что что-то не так. Можешь показать цепочку указателей в таблице Cheat Engine и твой код на C++, который читает? Вряд ли в моём коде где-то ошибка - проверил на нескольких указателях./*---------------------------------------------------------------------------*/ Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 16 августа, 2014 Автор Поделиться Опубликовано 16 августа, 2014 Предположу, что что-то не так. Можешь показать цепочку указателей в таблице Cheat Engine и твой код на C++, который читает? Вряд ли в моём коде где-то ошибка - проверил на нескольких указателях. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 16 августа, 2014 Поделиться Опубликовано 16 августа, 2014 /*---------------------------------------------------------------------------*/Покажи значение переменной CPed и из какого процесса ты читаешь (вызов FindWindow)./*---------------------------------------------------------------------------*/ Ссылка на комментарий Поделиться на другие сайты Поделиться
Coder Опубликовано 16 августа, 2014 Поделиться Опубликовано 16 августа, 2014 Автор VirtualProtect изменяет защиты памяти в локальном процессе, тебе нужно VirtualProtectEx использовать. Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 16 августа, 2014 Автор Поделиться Опубликовано 16 августа, 2014 /*---------------------------------------------------------------------------*/Покажи значение переменной CPed и из какого процесса ты читаешь (вызов FindWindow)./*---------------------------------------------------------------------------*/А во время исполнения программы значение CPed == содержимому Base Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 16 августа, 2014 Поделиться Опубликовано 16 августа, 2014 /*---------------------------------------------------------------------------*/Интересно!А в диспетчере задач процесс прям такой и висит - с "dll" на конце? Не "exe"?У меня есть подозрение, что ты не в том процессе ищешь./*---------------------------------------------------------------------------*/ Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 16 августа, 2014 Автор Поделиться Опубликовано 16 августа, 2014 /*---------------------------------------------------------------------------*/Интересно!А в диспетчере задач процесс прям такой и висит - с "dll" на конце? Не "exe"?У меня есть подозрение, что ты не в том процессе ищешь./*---------------------------------------------------------------------------*/pID определяет правильно с таким названием и CE подключается к этому же процессу Ссылка на комментарий Поделиться на другие сайты Поделиться
SiriusED Опубликовано 22 августа, 2014 Поделиться Опубликовано 22 августа, 2014 Хм, ну в принципе читать по смещениям это не так уж и сложно должно быть.. Недавно делал похожее...Могу глянуть если проблема именно в получении hWnd окна или процесса... Или проблема уже решена? Ну а так то я заметил что ты не верно написал смещения, в СЕ у тебя стоит первое же смещение "0x14" а ты читаешь "0xE", это же вроде разные значения, или я ошибаюсь? И еще не знаю как в C++, но я когда писал на C# чтение адресов то у меня была проблема что я хранил прочтенные адреса в int вместо uint, так что в эту сторону можешь тоже глянуть, мне помогло.. Ссылка на комментарий Поделиться на другие сайты Поделиться
Chusa Опубликовано 22 августа, 2014 Автор Поделиться Опубликовано 22 августа, 2014 Хм, ну в принципе читать по смещениям это не так уж и сложно должно быть.. Недавно делал похожее...Могу глянуть если проблема именно в получении hWnd окна или процесса... Или проблема уже решена? Ну а так то я заметил что ты не верно написал смещения, в СЕ у тебя стоит первое же смещение "0x14" а ты читаешь "0xE", это же вроде разные значения, или я ошибаюсь? И еще не знаю как в C++, но я когда писал на C# чтение адресов то у меня была проблема что я хранил прочтенные адреса в int вместо uint, так что в эту сторону можешь тоже глянуть, мне помогло.. Проблемане решена, если не сложно, то можем глянуть вместе в скайпе(lol_44_lol) или в RC. А по поводу смещений, да я не прав, но все равно дело до них не доходит, ошибка возникает в другом. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения