cheats чит коды к играм прохождения

 

Code Injection

Содержание:
1. Вступление
2. Теория
3. Изменение кода игры
4. Самый примитивный code injection
5. Более продвинутый code injection
6. Пишем трейнер
7. Контакты и ссылки
8. Условия распространения

1. Вступление:

После моей предыдущей статьи про борьбу с DMA, меня попросили написать статью про code injection. Не претендую на лавры первооткрывателя - про это достаточно много написано на английском, каждая уважающая себя группа, занимающаяся взломом игр, обычно имеет у себя на сайте дюжину статей про это. И я их почти все прочитал в своё время 8) В рунете дюжины статей нету, поэтому я напишу одну - постараюсь охватить всё как можно шире.

Что нам потребуется:

  • - SoftICE

  • - Artmoney/TSearch и т.п.

  • - Утилита для поиска code caves - Sheep's Array of Sunshine (или Code Cave Chaos, или Tsongkie Code Cave Tool (TCCT))

  • - Язык программирования. В примерах - Delphi.

  • - Лист бумаги и ручка, голова, прямые руки, сгибающиеся в локтях

Хорошо бы иметь Red Alert 2, потому что я буду показывать на нём примеры (старьё? Я знаю, что старьё. Но ничего более нового и более показательного у меня не нашлось). Использую какую-то пиратскую русифицированную версию, v1.0.

Поскольку мы будем писать свой код на ассемблере, то нужно уметь на нём писать (знаний ассемблера в рамках MS-DOS вполне хватит), а также уметь пользоваться отладчиком SoftICE. Я умею. А вы? Нет? Ну, тогда учиться придётся самостоятельно, к нашей теме это не относится. Если да - то отлично, можно смело читать дальше.

2. Теория:

Итак, code injection. Code injection переводится буквально - "инъекция кода" (русского эквивалента сей термин не имеет, поэтому я буду использовать английский вариант). Под этим термином подразумевается внедрение своего кода в (чужую) программу, в нашем случае - в игру.

В статье про DMA мы занимались тем, что искали способ всегда находить нужный нам адрес в памяти. Но можно пойти дальше - зачем изменять память, когда мы можем изменять сам код игры? Код, во время выполнения, тоже хранится в памяти, его тоже можно изменять, в т.ч. программно. Это гораздо удобнее - код не меняет адрес, мы можем заставить игру делать что угодно: например, значения не придётся "замораживать" таймерами. В общем, сами увидите, как это здорово 8)

Чтобы что-то изменять, нам это нужно найти. Для этого найдём адрес интересующего нас значения в памяти, и поставим брейкпоинт на запись по этому адресу. Когда произойдёт запись - исполнение приостановится, вылезет окно отладчика, и мы увидим тот код, который изменяет это значение. Его можно будет изменять.

Так же мы посмотрим, что такое code caves и научимся ими пользоваться. Code caves (в переводе означает "пещеры кода", а точнее, "пещеры в коде". Опять же, русского эквивалента не имеет) - термин, обозначающий участки кода программы, заполненные операторами NOP (байт 90) или байтами 00, т.е. которые ничего не делают. Раз они ничего не делают, то если туда запишем свой код, ничего такого не произойдёт. Именно это мы и сделаем 8) Собственно, тогда это и будет полноценный code injection.

Что ж, давайте посмотрим поближе на примерах.

3. Изменение кода игры

Итак, как я уже говорил, всё на примере Red Alert 2. Будем менять значение денег, т.к. больше-то и нечего (можно было бы сделать мгновенное строительство, но это уже сложнее, в другой раз).

Я считаю, что SoftICE у вас уже установлен, настроен и готов к работе, и по нажатию Ctrl+D вылезает его окошко. Включим окна регистров и памяти, если выключены (команды WR и WD соотв.).

Запускаем игру. Начинаем/загружаем игру. Теперь нам нужен адрес денег, его нужно найти. Но я уже нашёл указатель на него, ещё в прошлой статье. Поэтому делаем по-нашему, по-геймхакерски: жмём Ctrl+D, смотрим, чтобы был выбран нужный процесс (Game), в SoftICE набираем:

:D A1E0C4 L4

0030:00A1E0C4 60 6B C4 06 00 00 00 00 00 00 00 00 00 00 00 00
 

(Двоеточие в начале строки - приглашение отладчика к вводу команд, т.е. то, что начинается с ":" - вводим мы, всё остальное - вывод отладчика)
D - показать значение ячейки памяти,
A1E0C4 - адрес поинтера,
L4 - длина 4 байта.
60 6B C4 06 - содержимое поинтера
(у вас, естественно, будет другое значение, это ж DMA).

Все числа выводятся задом наперёд, так что 06C46B60 - адрес, на который указывает поинтер. Далее:

:? 06C46B60 + 24C
06C46DAC 0113536428 "..."


? - вычисление выражение (результат: первое число - в шестнадцатеричной системе счисления, второе - в десятеричной, третья штука - представление этих байтов в ASCII). Добавили к 06C46B60 смещение 24C, так что адрес денег - 06C46DAC.

Проверим значение по этому адресу:

:D 06C46DAC L4

0030:06C46DAC 10 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00

:? 2710

2710 10000 "..."

Всё верно - это наше значение, у меня было как раз 10000. (Внимание! Если у вас другая версия игры, и поинтер имеет другой адрес, т.е. после проделанных операций вы не нашли адрес денег - ищите его с помощью Artmoney/TSearch!)

Теперь поставим брейкпоинт на найденный адрес:

:BPM 06C46DAC W
:X

BPM - устанавливает брейпоинт на адрес памяти,
W - брейкпоинт на запись.
X - закрывает окно отладчика, и возвращает нас в игру.

После того, как вернулись в игру, начинаем что-нибудь строить. Количество денег уменьшается, поэтому срабатывает брейкпоинт, вылезает окно отладчика. В нём видим что-то вроде этого (все адреса кода могут меняться в зависимости от версии игры):

В окне кода:
...
017F:004E48F7 JMP 004E4988
017F:004E48F9 SUB EAX, EDI <--- это, собственно, и есть команда уменьшения денег. В EAX - их количество
017F:004E48FB MOV [ESP+24], EDI
017F:004E48FF MOV [EBX+0000024C], EAX <--- а здесь новое значение денег попадает в память (если посмотрим в окно регистров, то увидим, что значение в EBX равно значению поинтера)
017F:004E4905 JMP 004E4953

...

В окне команд:

Break due to BPMB #0030:06C46DAC W DR3
 

Сделаем:
:BC *

BC - удалить брейкпоинт,
BC * - удаление всех брейкпоинтов (нам больше не нужны).

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

Делаем:

:A 004E48F9
0028:004E48F9


A - ввод ассемблерных команд с клавиатуры. Ввод начинается с адреса, используемого в качестве параметра. Заканчивается вводом пустой строки.

Вводим:

:A 004E48F9
017F:004E48F9 NOP
017F:004E48FB NOP
017F:004E48FC

 

Заменяем оператор SUB оператором NOP (т.е. вместо уменьшения EAX - ничего не делать). Мы вводим 2 оператора NOP, т.к. длинна команды "SUB EAX, EDI" равна двум байтам, а NOP - 1 байт (об этом нужно всегда помнить. Длина рассчитывается так: начальный адрес команды "SUB EAX, EDI" - 017F:004E48F9, начальный адрес следующей команды - 017F:004E48FB, следовательно длина команды равна FB-F9 = 2 байтам).

Теперь в окне кода мы должны увидеть такой код:

...
017F:004E48F7 JMP 004E4988
017F:004E48F9 NOP
017F:004E48FС NOP
017F:004E48FB MOV [ESP+24], EDI
017F:004E48FF MOV [EBX+0000024C], EAX
017F:004E4905 JMP 004E4953

...

Выполняем команду "X" и возвращаемся в игру. Попробуем что-нибудь построить, и видим, что... деньги не убывают 8) Замечательно. Но не всё так сладко: компьютерные игроки используют ту же самую процедуру (по крайней мере, в Red Alert 2) для вычисления их количества денег (это можно заметить по следующим проявлениям:
1) если поставить брейкпоинт (BPX) на адрес 004E48F9, увидим, что даже когда мы ничего не строим, брейкпоинт срабатывает;
2) враг просто будет строить орды солдат и танков 8) ), поэтому и у них их количество не будет уменьшаться. Подарить врагу неисчерпаемые материальные ресурсы? Ни за что! 8) О том, как с этим бороться - дальше.

 

4. Самый примитивный code injection

Итак, чтобы исправить досадную неприятность с количеством денег у врага, нам нужно будет написать немного своего кода. Как я говорил раньше, для этого мы будем использовать code caves. Здесь мы научимся ими пользоваться.

Перезапустите игру, альт-табом переключитесь на рабочий стол, запустите утилиту для поиска code caves (у меня - Sheep's Array of Sinshine), нужно будет указать имя процесса. В результате увидим список code cave'ов: начальный адрес, длину и секцию (г-н [Sheep] рекомендовал использовать только секцию кода .data, как самую безопасную).

В Red Alert 2 имеем code cave с начальным адресом 00B12024, длины FDC (4060) байт.

Перед тем, как писать свой код, попробуем лишь сделать переход в code cave и вернуться назад.

Заменим инструкцию "SUB EAX, EDI" на инструкцию безусловного перехода в code cave - "JMP 00B12024":

:A 004E48F9
017F:004E48F9 JMP 00B12024
017F:004E48FE

Инструкция JMP имеет длину 5 байтов, поэтому последующие две инструкции окажутся запороты: вместо


017F:004E48F9 SUB EAX, EDI
017F:004E48FB MOV [ESP+24], EDI
017F:004E48FF MOV [EBX+0000024C], EAX
017F:004E4905 JMP 004E4953

будем иметь

017F:004E48F9 JMP 00B12024
017F:004E48FE AND AL, 89
017F:004E48FF OR DWORD PTR ...
017F:004E4905 JMP 004E4953

поэтому нам придётся восстановить ещё и эти две инструкции в нашем code cave. Поэтому же нужно всегда предварительно смотреть, сколько байтов будет занимать написанная нами инструкция, и записывать на бумажку старые, чтобы их потом восстановить.

Хорошо, теперь займёмся собственно code cave'ом:

:A 00B12024
017F:00B12024 SUB EAX, EDI
017F:00B12026 MOV [ESP+24], EDI
017F:00B1202A MOV [EBX+024C], EAX
017F:00B12030 JMP 004E4905
017F:00B12035

Этим кодом мы ничего не изменяем в нормальном ходе игры - просто восстанавливаем все испоганенные нами инструкции, и возвращаемся к инструкции, которая была после "MOV [EBX+024C], EAX". Теперь, при исполнении изменённого кода, когда очередь дойдёт до адреса 004E48F9 произойдёт переход к адресу 00B12024, там выполнится прежних 3 инструкции, и снова произойдёт переход назад, к адресу 004E4905. Это и есть простейший code injection - мы изменили код игры.

Вернёмся в игру и посмотрим результат. Если работает нормально, и деньги убавляются - значит всё хорошо, если игра завершается аварийно - значит вы где-то напортачили в коде, придётся перезапускаться и делать всё по-новой.

5. Более продвинутый code injection

Теперь напишем свой код в code cave. Здесь мы уже делаем полноценный code injection. Как сделать так, чтобы деньги не убавлялись у нас, но убавлялись у компьютерного игрока? Сделаем очень просто - сравним значение в регистре EAX со значением в ячейке памяти, на которую указывает нам поинтер.

В нашем code cave пишем такой код:

:A 00B12024
01F7:00B12024 PUSH EDX <--- положим значение EDX в стек, т.к. мы собираемся его поменять, чтобы его потом восстановить
01F7:00B12025 MOV EDX, [A1E0C4] <--- это у нас адрес поинтера, указывает на (адрес денег-24C)
01F7:00B1202B ADD EDX, 24C <--- добавим смещение
01F7:00B12030 CMP [EDX], EAX <--- сравним EAX со значением по адресу в EDX (т.е. с количеством наших денег)
01F7:00B12032 JZ 00B12036 <--- если равно, то "перепрыгнем" следующую инструкцию
01F7:00B12034 SUB EAX, EDI
01F7:00B12036 POP EDX <--- снимем с вершины стека предыдущее значение EDX
01F7:00B12037 MOV [ESP+24], EDI <--- восстановленный код
01F7:00B1203B MOV [EBX+0000024C], EAX
01F7:00B12041 JMP 004E4905
01F7:00B12036

После произведённых изменений деньги не будут уменьшаться только у нас, а у компьютера будут (для уверенности можно проверить это - поставить BPX 00B12034).

Всё 8) Мы успешно внедрили свой код.

6. Пишем трейнер

Чтобы не проделывать все эти трюки вручную, напишем трейнер. Серьёзный, взрослый трейнер с code injection 8) Пишем его абсолютно так же, как писали если бы изменяли значение в памяти.

Просмотрим машинные коды ассемблерных команд до и после замены SUB на JMP:

До:
:D 004E48F9 L5
017F:004E48F9 2B C7 89 7C 24 24 89 83 4C 02 00 00 ...

После:
:D 004E48F9 L5
017F:004E48F9 E9 26 D7 62 00 24 89 83 4C 02 00 00 ...

То же самое проделаем и с кодом в code cave. Всё это необязательно делать вручную - в Sheep's Array of Sunshine есть дампер памяти с форматированием для различных языков программирования. Просто пишем начальный адрес, длину - и готово.

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

Исходники трейнера на Delphi прилагаются.

На этом у меня всё. Удачи. br0k3n_MinD.

7. Контакты и ссылки

Персональные уроки по почте я давать не намерен. Откровенно ламерские письма будут отвергнуты (типа, "ничего не понимаю, объясни" или "пришли мне SoftICE на мыло") и, хуже того, рискуют быть где-нибудь опубликованы мной 8) Если у вас есть какая-нибудь более или менее конструктивная критика, действительно принципиальные и хорошие вопросы, идеи, предложения - то пишите, буду рад.
 

Сообщения об ошибках и неточностях также приветствуются.

< Обсуждение статьи у нас на форуме >

E-mail: br0k3n_MinD@mail.ru

Официальный сайт [Sheep]'а - http://www.sheeprec.cjb.net
(Sheep's Array of Sunshine искать там 8) )

Если что - гугл в помощь.

8. Условия распространения и всё прочее

Статья написана специально для сайта http://www.CheMax.ru , поэтому публикация статьи где-либо без разрешения владельцов сайта запрещена.

07 апреля 2006 года.

То, что было прочитано перед тем, как был написан этот туториал:

http://www.sheeprec.cjb.net
http://tsongkie.com/
http://www.ghu.as.ro/

...и оттуда дальше по ссылкам 8)

[новости]  [cheats]  [чит коды]  [chemax]  [полезные утилиты]  [статьи]  [форум

Copyright© 2001-2017 
CheMax Team