Я делаю реверс игры с использованием Cheat Engine и OllyDBG, с помощью этого читаются и отслеживаются адреса памяти в FPS игре, эти адреса будут содержать координаты(xyz) врагов.
Моя цель - найти адрес или шаблон, который позволит мне перебрать до 32 врагов, чтобы прочитать все их координаты, для этого я пытался найти шаблон между каждым из их адресов, но безуспешно. Мне удалось собрать 3 различных адреса врагов, эта информация полезна, но поиск 32 адресов - задача, которая требует больше усилий, чем я считаю необходимым.
Как уже было сказано, у меня есть доступ к первым 3 адресам врагов, и если на основе этой информации можно проследить путь до базы либо через Cheat Engine, либо через другое программное обеспечение для обратной разработки, то я был бы признателен за этот процесс.
В конечном итоге мой вопрос заключается в том, есть ли способ обнаружить массив указателей в памяти по одному из его адресов, например, если у меня есть 3 координаты врага, могу ли я каким-то образом отследить место в памяти до адреса, который обращается ко всем 32 адресам врага, будь то с помощью Cheat Engine или другого инструмента реверсинга.
(ОП не уточнил, знает ли он, как устроены структуры. Похоже, он предполагает, что они не сложные. Я отвечу на более общий вопрос, чтобы избежать проблем локальности, предполагая, что структуры несколько сложны).
Немного способов найти другие структуры приходит на ум:
Когда у вас есть несколько примеров структур, возможно, самый простой способ найти экземпляры других структур - это найти совпадающие константы во всех трех структурах. Некоторые значения могут быть постоянными, представлять собой свойства, которые применяются ко всем вражеским сущностям в более высокоуровневом классе, передаваемом по наследству.
Возможно, где-то есть указатель на каждую сущность. Вы можете просто поискать в памяти адреса найденных структур и найти массив/структуру, в которой хранятся все сущности. Вы также можете пройтись по массивам, найденным в самих структурах, возможно, вы смотрите на связный список.
В объектно-ориентированном языке, таком как C++ или ObjC, или в процедурном языке, таком как C, должна быть функция, инициирующая структуру. обычно ее легко найти - первая функция, вызываемая после выделения объекта, довольно характерная сборка - в основном код инициализации.
Если мы говорим об ОО-коде, то поиск таблицы виртуальных функций или аналогичной конструкции позволит вам легко найти функции построения, пройтись по наследованию и найти хотя бы часть манипулирующих функций.
После получения конструкторов вы сможете легко получить все выделения и увидеть, где хранятся указатели.
Этот способ требует немного больше работы по реверсированию, но позволит вам найти лучшие способы поиска сущностей. Используя Cheat Engine и IDA, вручную нанесите на карту структуру, элементы/члены, функции, которые манипулируют структурой.
Если есть какие-либо указатели, следуйте им и реверсируйте другие структуры, которые вам встретятся.
по крайней мере для некоторых из упомянутых мною методов поиск указателей на все сущности при анализе программы может быть только первым шагом. Вы можете искать ссылки на сам список и получить лучший способ автоматического поиска сущностей при каждом перезапуске программы. Это устраняет некоторые из конс.
Сначала найдите адрес, который вы ищете. Затем выполните следующий цикл:
Пример:
Поиск параметра, находящего адрес 30000032
.
Выясните, что основой этой записи является 30000000
.
Проверка памяти - ничего причудливого вокруг.
Находим указатель на базу по адресу 20000004
.
Выясняем, что основание записи - 20000000
.
Проверяем память - по-прежнему ничего...
Находим указатель на базу по адресу 10000008
.
Обнаружение базы по адресу 10000000
.
Проверяю память - все указатели на искомые объекты находятся на расстоянии 12 байт друг от друга. (Очевидно, что это какая-то коллекция).
Последнее сканирование памяти для указателя, чтобы убедиться, что я не ошибся, на 0000040
.
Нахожу указатель на эту коллекцию, а сразу за ним: количество объектов в коллекции.
Перезапустите игру/компьютер несколько раз, чтобы найти последовательный указатель на этот адрес.
Наградить себя пивом за хорошую работу.
Как найти базу: Мне нравится использовать "сканирование указателя", и проверять последнее смещение. Наименьшее из наиболее часто встречающихся, обычно является правильным.
Иногда я пытаюсь найти запись в начале выделенной памяти, и в этом случае я уверен, что что-то является базой.
Другой трюк - найти в памяти две записи, расположенные одна за другой, определить их "максимальный размер", и это означает, что база должна быть не дальше этого числа в памяти.
Как распознать коллекции: Большинство из них ИСКЛЮЧИТЕЛЬНО упорядочены, с определенным смещением, или имеют указатели на однотипные объекты.
Например, если у вас есть:
Pointer to Player 1 data,
4 Bytes
4 Bytes
Pointer to Player 2 data,
4 Bytes
4 Bytes
Pointer to Player 3 data
Это должно прозвенеть.
Имейте в виду, что такое выравнивание может случайно встречаться в источнике, поэтому попробуйте поискать: Данные игрока 3, Данные игрока 3 +/- 4, Данные игрока 3 +/- 8.
В любом случае, если вы найдете что-то подобное, скорее всего, вы действительно близки.
Это работает для меня, надеюсь, это сработает и для вас, ребята.