Понимание памяти - взлом игры - PullRequest
2 голосов
/ 26 сентября 2019

Я пытаюсь начать учиться кодировать игровые читы на C ++.Но на данный момент я хочу понять расположение памяти и т. Д. У меня есть несколько вопросов, и я буду использовать игру Assault Cube для справки.Пожалуйста, помогите мне и объясните что-нибудь в простой форме.Я новичок.

1) Допустим, адрес базы данных ac_client.exe имеет значение 0x4000000 - это просто означает, что начало процесса выделено по этому адресу памяти?

2) Далее идет база изображений + смещение (&ac_client.exe + 0x10F4F4) - означает ли это смещение, что оно ведет вас к месту или функции внутри процесса из начальной точки?

3) В ЧитДвигатель у меня загружен Assault Cube.Я искал ценность моего здоровья.Я нашел динамический адрес здоровья.Теперь мне нужно найти статический адрес, поскольку прямого указателя на здоровье нет, я нажимаю на опцию «найти, что обращается к этому адресу» - означает ли это, что я пытаюсь найти функцию, которая использует или передает мое динамическое здоровье?переменная?

4) После нахождения статического адреса для значения здоровья.Я нашел смещение, равное 0xF8.Также ac_client.exe + 0x10F4F4 -> 0x50F4F4 - люди говорят, что 0x50F4F4 является базовым классом местного игрока, но как я узнаю это, если мне не сказали этого?Означает ли это также, что все игровые переменные находятся в классах?

Все еще немного сбит с толку, может кто-нибудь объяснить, как все это работает визуально.

1 Ответ

1 голос
/ 27 сентября 2019

1) Допустим, адрес базы данных ac_client.exe равен 0x4000000 - означает ли это, что начало процесса выделено по этому адресу памяти?

Да,но более конкретно, это базовый адрес PE (Portable Executable), когда-то отображенный в памяти.Таким образом, в адресной базе у вас есть PE-заголовок, а затем множество структур, затем разделы исполняемого файла и т. Д.

2) Далее идет Image Base + Offset (ac_client.exe + 0x10F4F4) - означает ли смещение, что оно приведет вас к месту или функции внутри процесса из начальной точки?

Технически это называется RVA ( Относительный виртуальный адрес ; этоотносительно базового адреса модуля): существует разница между смещением (которое применяется к плоскому файлу на диске) и RVA (которое применяется к файлу, отображенному в памяти).Как только исполняемый файл отображается в памяти (хотя это называется загрузчиком ОС), он приобретает другую «форму», чем на диске, поэтому смещение - это не то же самое, что RVA.

Чтобы ответить на вашвопрос, да, он указывает где-то в модуле с именем ac_client.exe.

3) В Cheat Engine я загрузил Assault Cube.Я искал ценность моего здоровья.Я нашел динамический адрес здоровья.Теперь мне нужно найти статический адрес, поскольку прямого указателя на здоровье нет, я нажимаю на опцию «найти, что обращается к этому адресу» - означает ли это, что я пытаюсь найти функцию, которая использует или передает мое динамическое здоровье?переменная?

Точно.

Я не знаком с Cheat Engine, но это можно сделать различными способами:

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

  2. Сканирование памяти: механизм поиска непосредственно в адресном пространстве процесса для всего, что указывает (или не очень далеко) на интересующее место.Если это происходит в разделе кода, у вас есть совпадение.В противном случае (например, где-то еще в разделе данных или в куче) попытайтесь найти любое местоположение кода, которое указывает на это новое местоположение.Принц и повторяйте, пока не найдете что-нибудь.

  3. Смесь вышеперечисленного.

4) После нахождения статического адреса для здоровьястоимость.Я нашел смещение 0xF8.Также ac_client.exe + 0x10F4F4 -> 0x50F4F4 - люди говорят, что 0x50F4F4 - это базовый класс локального игрока, но как мне узнать это, если мне не сказали этого?Означает ли это также, что все игровые переменные находятся в классах?

Если игра с закрытым исходным кодом, вы должны перепроектировать ее, чтобы понять все тонкости игры, чтобы иметь возможность сказать это.Это занимает много времени, сложно, и у вас никогда не будет тех же «имен», которые предполагали оригинальные программисты.«Имена» (имена классов, имена функций, имена переменных и т. Д.) Не попадают в окончательный двоичный файл: вы теряете возможность видеть имена классов и их расположение.

Есть еще несколько случаев, когдавы можете восстановить эти имена, по крайней мере, в C ++ (например, когда у вас есть что-то под названием RTTI ) или если доступна символическая информация (разработчики игр никогда не отправляют отладочную информацию, за исключением нескольких случаев).

В вашем случае (насколько я вижу игра с открытым исходным кодом и на C ++) вы можете скомпилировать игру для себя с поддержкой отладки (технически для Windows это означает символическую поддержку, создавая PDB , когдасвязывание исполняемого файла).Затем поместите игру в символический отладчик (например, Windbg) или дизассемблер, затем спросите инструмент, что за функция / класс лежат в этом точном смещении / RVA.Это действительно просто, когда у вас есть символическая информация.

Некоторые языки (например, C #, Java) можно декомпилировать (! = Дизассемблировать), и вы можете напрямую получать все имена (классы, функции, переменные и т. Д.), Если только конечный двоичный файл не защищен от декомпиляции.

Означает ли это, что все игровые переменные все находятся в классах?

Это довольно сложный вопрос с множеством различий: во-первых, это зависит от используемого языка.Если это язык OO , то , вероятно, да, за исключением глобальных, статических и локальных переменных.Некоторые языки не имеют понятия классов, поэтому расположение объектов в памяти, которыми манипулирует игра, может быть совершенно разным в играх на Си и С ++.

Еще один важный момент: у вас также может не бытьсодержимое непосредственно в классе, на которое указывает член класса.

Допустим, у вас есть игра, в которой у игрока есть инвентарь (так что класс 'Player')имеет переменный элемент с именем «инвентарь»), который, вероятно, будет управляться какой-то сложной структурой (например, ассоциативный контейнер или даже чем-то более сложным).Поскольку эти сложные структуры динамически распределяются игрой (например, new в c ++ ), все объекты в инвентаре попадают в heap , но не непосредственно в самом классе.Распределение указывается (не обязательно напрямую) членом «инвентаря», но объекты в инвентаре находятся в другом месте в памяти.

...