![]() |
Пробыв год в одном месте и потеряв все исходники и знания я задам теперь вопрос который меня щас мучает ооочень сильно ! Пример: У нас есть адрес в формате samp.dll+0x12D8F8 который был найден в Cheat Engine и адрес 0xS3FSFD + 0х9201 который нам кто-то дал ( ну или нашли где-то ) . 😘🤓😘😇Практика : 😘🤓😘😇 Код:
ReadProcessMemory(process, (LPCVOID)(0xS3FSFD), &TestS, sizeof(TestS), NULL)[/COLOR]Код:
[/CENTER][/HEADING] Значит адрес 0xS3FSFD + 0х9201 мы вроде как можем прочитать и вроде все верно или нет то посоветуйте как правильнее 🙂, так дальше .🙂 Адрес формата : samp.dll+0x12D8F8 я не могу прочитать так как я не знаю как правильно прочитать samp.dll что-бы к нему 🙂добавить смещение 0x12D8F8 . 🙂 Вопрос : Как прочитать адрес samp.dll+0x12D8F8 а точнее samp.dll что бы к примеру его прочитать и вывести в консоль или 🙂наоборот изменить его . 🙂 Я пишу на языке с++ , использую консольно приложение , редактирую адреса памяти не через DLL ! а используя консольое 😘🤓😘😇приложение .exe тоесть из левой программы пытаюсь взаимодействовать с гта са . 😘🤓😘😇 Надеюсь я правильно все вам написал и вы правильно мой вопрос поняли , даже если не знаете на него ответ ) . 😘 😘🤓😘😇Спасибо за внимание жду ваших ответов с примерами желательно . 😇 😇 😇 🥰🥰Всем удачи ! Денег , дачи .🥰🥰 |
Может всё-таки кто-то поможет ?
|
Привет-привет.
Давай все по порядку. 1) Что такое адрес? Адрес – это цифра, правда в шестнадцатеричной системе, но все же это обычная цифра. И по каждому адресу находится какое-то значение от 0 до 255 (1 байт). Все типы данных (int; float; char...) складываются из некого массива байт. Ближе к делу. Поэтому если у тебя адрес такой: Код:
0x3FBFD + 0x9201C++: Код:
DWORD bytes2) Если у тебя адрес формата: Код:
samp.dll + 0x12D8F8C++: [CODE] #include "stdafx.h" #include #include #include DWORD getModuleBaseAddress ( DWORD pID , TCHAR * szModuleName ) // функция, которая получает этот адрес "samp.dll". её трогать не надо { DWORD dwModuleBaseAddress = 0 ; HANDLE hSnapshot = CreateToolhelp32Snapshot ( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 , pID ) ; if ( hSnapshot != INVALID_HANDLE_VALUE ) { MODULEENTRY32 ModuleEntry32 ; ModuleEntry32 . dwSize = sizeof ( MODULEENTRY32 ) ; if ( Module32First ( hSnapshot , & ModuleEntry32 ) ) { do { if ( strcmp ( ModuleEntry32 . szModule , szModuleName ) == 0 ) { dwModuleBaseAddress = ( DWORD_PTR ) ModuleEntry32 . modBaseAddr ; break ; } } while ( Module32Next ( hSnapshot , & ModuleEntry32 ) ) ; } CloseHandle ( hSnapshot ) ; } return dwModuleBaseAddress ; } int main ( ) { HWND hWnd = FindWindow ( NULL , L "GTA SA:MP" ) ; DWORD pId ; GetWindowThreadProcessId ( hWnd , & pId ) ; HANDLE process = OpenProcess ( PROCESS_ALL_ACCESS , 0 , pId ) ; DWORD moduleBase = getModuleBaseAddress ( pId , L "samp.dll" ) ; // вот тут в кавычках имя твоего модуля. и всё, в переменной уже хранится его базовый адрес int my_number ; // опять же, любой тип данных тут может быть. не забывай, что в 4 строках ниже нужно поменять название переменной, если ты захочешь её переименовать тут DWORD oldProtect = 0 ; VirtualProtectEx ( process , ( void * ) ( moduleBase + 0x12D8F8 ) , sizeof ( my_number ) , PAGE_EXECUTE_READWRITE , & oldProtect ) ; ReadProcessMemory ( process , ( void * ) ( moduleBase + 0x12D8F8 ) , & my_number , sizeof ( my_number ) , NULL ) ; VirtualProtectEx ( process , ( void * ) ( moduleBase + 0x12D8F8 ) , sizeof ( my_number ) , oldProtect , NULL ) ; std :: cout 3) А вот что ты писал про сумму – это не совсем сумма. Это указатель. То есть по одному адресу памяти хранится значение другого адреса памяти, уже который хранит именно нужные тебе данные (обычно это число). Код:
0x3FBFD –> 0x9201–> нужное тебе число (или не число, любой тип данных)C++: [CODE] DWORD bytes ; DWORD oldProtect = 0 ; // читаем данные по адресу 0x3FBFD и записывает в bytes VirtualProtectEx ( process , ( void * ) 0x3FBFD , sizeof ( bytes ) , PAGE_EXECUTE_READWRITE , & oldProtect ) ; ReadProcessMemory ( process , ( void * ) 0x3FBFD , & bytes , sizeof ( bytes ) , NULL ) ; VirtualProtectEx ( process , ( void * ) 0x3FBFD , sizeof ( bytes ) , oldProtect , NULL ) ; // прибавляет к нему наш "оффсет" (смещение) bytes += 0x9201 ; // это и есть наш новый адрес, который хранит нужные данные. читаем его: float my_number ; // например, найдём число с плавающей точкой (нецелое) по этому адресу VirtualProtectEx ( process , ( void * ) bytes , sizeof ( my_number ) , PAGE_EXECUTE_READWRITE , & oldProtect ) ; ReadProcessMemory ( process , ( void * ) bytes , & my_number , sizeof ( my_number ) , NULL ) ; VirtualProtectEx ( process , ( void * ) bytes , sizeof ( my_number ) , oldProtect , NULL ) ; // нашли. теперь делай с ним, что хочешь. для примера: выведу в консоль std :: cout Надеюсь, что я ответил на все поставленные тобой вопросы. Удачи. |
[QUOTE="Vintik"]
Привет-привет. Давай все по порядку. 1) Что такое адрес? Адрес – это цифра, правда в шестнадцатеричной системе, но все же это обычная цифра. И по каждому адресу находится какое-то значение от 0 до 255 (1 байт). Все типы данных (int; float; char...) складываются из некого массива байт. Ближе к делу. Поэтому если у тебя адрес такой: Код:
0x3FBFD + 0x9201C++: Код:
DWORD bytes2) Если у тебя адрес формата: Код:
samp.dll + 0x12D8F8C++: Код:
#include "stdafx.h"C++: [CODE] DWORD bytes ; DWORD oldProtect = 0 ; // читаем данные по адресу 0x3FBFD и записывает в bytes VirtualProtectEx ( process , ( void * ) 0x3FBFD , sizeof ( bytes ) , PAGE_EXECUTE_READWRITE , & oldProtect ) ; ReadProcessMemory ( process , ( void * ) 0x3FBFD , & bytes , sizeof ( bytes ) , NULL ) ; VirtualProtectEx ( process , ( void * ) 0x3FBFD , sizeof ( bytes ) , oldProtect , NULL ) ; // прибавляет к нему наш "оффсет" (смещение) bytes += 0x9201 ; // это и есть наш новый адрес, который хранит нужные данные. читаем его: float my_number ; // например, найдём число с плавающей точкой (нецелое) по этому адресу VirtualProtectEx ( process , ( void * ) bytes , sizeof ( my_number ) , PAGE_EXECUTE_READWRITE , & oldProtect ) ; ReadProcessMemory ( process , ( void * ) bytes , & my_number , sizeof ( my_number ) , NULL ) ; VirtualProtectEx ( process , ( void * ) bytes , sizeof ( my_number ) , oldProtect , NULL ) ; // нашли. теперь делай с ним, что хочешь. для примера: выведу в консоль std :: cout |
Цитата:
VirtualProtectEx нужен для того, чтобы установить нужному кусочку памяти необходимый уровень защиты для того, чтобы читать и записывать данные. Условно: сказать программе, что есть разрешение на запись/чтение этого участка памяти. Использовать стоит везде, где ты её читаешь или записываешь. Последствия, с которыми сталкивался я, – краш от античита с причиной "Нарушение прав доступа к памяти". Пример: 1616438552482.pngVintik · 22 Мар 2021 в 21:57' data-fancybox="lb-post-696556" data-lb-caption-extra-html="" data-lb-sidebar-href="" data-single-image="1" data-src="https://www.blast.hk/attachments/90314/" style="cursor: pointer;" title="1616438552482.png"> https://forum.antichat.xyz/attachments/27696556/ Это из краш-лога одного пользователя, который воспользовался моим скриптом без VirtualProtectEx. Теперь по поводу вопроса 4. Измени ту функцию на вот эту. Вероятно, у тебя возникнет ошибка, просто надо поставить многобайтовую кодировку. В VS это делается вот так. C++: Код:
DWORDЦитата:
|
Цитата:
[S]Про стиль общения это маска дабы общение было приятным[/S] ( 🥷[S]я не такой[/S]🥷 ) . 🤩 🥰 😀 |
Цитата:
C++: Код:
templateИспользовать его вот так: C++: Код:
auto(этот код запишет в moneyтвоё состояние, в смысле сколько денег) Или вот так: C++: Код:
auto(а этот изменит твоё здоровье до 55 единиц) Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
2. Или есть свои плюсы и минусы ? Просто по визуальному эффекту данный код меньше и скорее всего он перспективнее или он проще обнаруживается анти читом в разных играх или разницы нету чисто ради красоты . |
| Время: 20:13 |