20111021

Между делом.

Обновил настройки RSS-канала. Теперь работает, как надо. :)
Сегодня будет следующий видеоурок.

20111016

Продолжение видеоуроков!

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

20110929

Статья про FPU.

Как и обещано, [ссылка]. :D

Вторая часть седьмого видеоурока - делаем спидхак для Crimsonland!

С разбегу - [ссылка]!

Во второй части я покажу, как делается взлом скорости ("быстро бегать") для замечательной аркады Crimsonland, попутно объясню значение пары новых ассемблерных команд, характерных только для данного типа взлома. А именно:

fld [eax] - загружает значение типа float (с плавающей точкой) в [математический сопроцессор] (он же FPU) для последующих операций над ним.
fstp [eax] - соответственно, выгружает результат обратно в регистр eax.

Как именно вся эта фигня работает нам знать не настолько важно. Нам будут встречаться конструкции вида:

fld [eax+1234]
fadd [edi] (то же, что и add)
fsub [esx] (то же, что и sub)
fstp [eax+1234]


Основная мысль заключается в том, что главный процессор не умеет работать с дробными числами (float), так что для этого существует процессор поменьше - сопроцессор, который умеет только это. Командой fld (float load) мы заставляем главный процессор скормить нужное нам число сопроцессору, дальше в нём происходят какие-то действия над числом (fadd, fsub и т.п.), после чего по команде fstp число грузится обратно в главный процессор. Очень похоже на code-injection, правда? :)

Наша задача - или вклиниться в действия над значением после его загрузки в сопроцессор (пример - на видео), или посмотреть, что происходит чуть раньше - скажем, какая разница в координатах прибавляется\убавляется, часто можно обнаружить некоторый множитель. Типа, идём шагом - координаты умножаются на единичку, бежим бегом - умножаются на пять (бежим впятеро быстрее, чем идём шагом). Механизм действий схож для большинства игр, т.к. практически все хранят координаты в типе float, но ньюансы встречаются - нет универсального решения.

Теорию про сопроцессор и сопутствующие ему команды я выложу тут.



20110925

Ещё немного чтива

Нашёл ещё один неплохой вводный курс по ассемблеру - [ссылка]. В нём используется flat assembler, он же fasm - один из синтаксисов этого языка. Надо сказать, что ассемблера существует достаточно дофига диалектов - есть fasm, masm, nasm, tasm, в общем - много вариантов. Между собой они различаются разными поддерживаемыми фичами и набором команд. Самый популярный - masm, или Macro Assembler производства Microsoft. Если будем писать что-то на ассемблере, то выберу я именно этот - под него пишется большинство статей и он обладает наиболее богатой документацией. :)

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

20110924

Первая часть седьмого видеоурока, или знакомимся со структурами.

Итак!

Тянуть время дальше стало катастрофически лень, так что я быстренько сел и записал вводное видео. Простите, что так поздно, дела-дела. :)

В этом видео я постарался объяснить значение такой офигенно полезной штуки, как структура.
Это, если не обращаться к википедии и заумным книжкам, просто способ организовать какую-то информацию. Относительно игр нам надо просто понимать, что своя структура есть у каждого игрового объекта, для однотипных объектов она чаще всего одинаковая (структура "монстр" - у каждого монстра, "игрок" - у каждого игрока, "пуля" - у каждой пули и так далее), а при взломе помним самое главное - в памяти все значения конкретной структуры чаще всего хранятся рядышком, бывает что просто подряд. :D

Нам это может сильно помочь при поиске каких-то величин, которые на экране не отображаются и которые найти обычными способами довольно проблематично. Например, ломаем мы гоночки. В какой-то момент нам ВНЕЗАПНО очень захотелось найти массу нашей машины. Да-да, раз в игре есть хоть какая-то физика (а в современных играх для этого дела целые физические движки созданы) - то есть и масса и все основные законы. Все ведь помнят второй закон Ньютона из школьного курса физики? Если нет, то поясню: чем меньше будет масса нашей машины, тем быстрее она будет ускоряться. Так что на старте с машиной весом в 5 грамм мы всех уделаем. ^^

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

Такие вот пироги. Смотрим, вникаем, запоминаем: [ссылка].


20110923

Следующие видеоуроки

Помните, что я указал в последнем видеоуроке? "Будем учиться быстро бегать и высоко прыгать". Это значит, что мы будем искать координаты игрока и работать с ними.

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

Частей планируется 2-3, первая - про необходимые понятия и теорию, вторая - про "быстро бегать", ну а третья, очевидно, - про "высоко прыгать". Как пройдём это всё и материал более-менее усвоится - покажу, как делается "Rapid fire hack" - это когда мы из какого-то медленно стреляющего оружия будем стрелять аки из шестиствольного пулемёта - в общем, быстро, очень быстро!

На этом основной курс "как научиться ломать игры" будет в общем-то окончен, так что дальше буду выкладывать какие-то конкретные фичи (как найти то или иное труднодоступное для обычного поиска значение, более простой метод поиска указателей и т.п.), может быть коснусь темы снятия игровых защит - да, бывает и так, в современных играх - почти повсеместно.

Параллельно приступим к написанию трейнеров. Эта тема довольно объёмная и абстрактная - зависит она в основном от умения программировать. Всё ещё думаю, как к ней грамотно подойти, но какой-никакой план уже есть. :)

20110921

Видеоуроки по С++

Делюсь очень хорошим курсом из 60 видеоуроков (с комментариями на английском языке) по С++. Достойная штука для тех, кто хочет начать изучать плюсы, рекомендую! (:

[ссылка]

20110916

Шестой видеоурок, так сказать! :D

А если серьёзно - просто видеопояснение к [предыдущей записи] о Code-Injection. Ломаем таймер матча в Mortal Combat 4, а ещё - узнаём две новых команды ассемблера (совсем простеньких):

inc \ dec [регистр] - англ. increment (увеличение) \ decrement (уменьшение) - увеличивает или уменьшает содержимое [регистра] на единичку. Пример:

mov edi, 5 //кладём в edi пятёрочку
dec edi      //делаем магию!!

В итоге в edi будет лежать четыре. :)


В следующих двух видеоуроках будем учиться высоко (очень высоко!) прыгать и не менее быстро бегать. Оставайтесь на линии, Ваш звонок очень важен для нас! :D

[ссылка на урок]


Code-Injection: Подробности

В [пятом уроке] (и в четвёртом тоже ^^) мы рассматривали такую технику, как Code-Injection, или, если буквально, "инъекция кода". Давайте остановимся на этой штуке ещё немного - больно уж часто она используется. Больше скажу - одна из самых распостранённых техник взлома. :)

Итак. Представим, что имеется у нас вот такой гипотетический код игры:

Адрес   |  Команда      |    Комментарий
---------------------------------------------------------------------------------
0000000: mov eax, 3     //помещаем в регистр eax число "3"
0000001: sub eax, 1      //вычитаем из еах единичку
0000002: cmp eax, 0    //сравниваем еах с нулём
0000003: je "exit"         //если еах = 0, то выходим из игры
0000004: add eax, 2    //иначе прибавляем к еах двойку
0000005:
0000006:
0000007:
0000008:
0000009:
---------------------------------------------------------------------------------

Скажем, нашли мы нужный адрес в Cheat Engine, включили отладчик дабы посмотреть - а с чего это у нас заканчиваются жизни (которые, как вы поняли, в еах находятся), отладчик нам выплёвывает адрес 0х00000001.

Если мы хотим, чтобы жизни просто не убавлялись, мы заменяем команду "sub eax, 1" nop'ами - командами, которые ничего не делают. Почему я написал во множественном числе? Всё просто - одна команда "nop" занимает один байт места, а вот "sub eax, 1" места занимает чуток побольше. Точные значения нас сейчас не волнуют (их можно посмотреть в отладчике), скажем, что это четыре байта. Поэтому вместо:

sub eax, 1

Мы должны будем написать четыре команды "nop", по одной на каждый байт:

nop
nop
nop
nop

Если не соблюдать это правило (количество байт кода всегда неизменно) - получите синий экран и придётся делать заново.

Идём дальше. В чём суть техники Code-Injection? Мы берём какую-то команду (в данном примере - ту, что вычитает у нас жизни) и заменяем её на команду jmp - прыжок или переход. Там выполняем какой-то код, затем возвращаемся обратно - в код игры. Смотрите:

Адрес   |  Команда      |    Комментарий
---------------------------------------------------------------------------------

0000000: mov eax, 3             //помещаем в регистр eax число "3"
0000001: jmp [0000006]      //переходим ("прыгаем") на адрес 0x0000006
0000002: cmp eax, 0            //сравниваем еах с нулём
0000003: je "exit"                 //если еах = 0, то выходим из игры
0000004: add eax, 2            //иначе прибавляем к еах двойку
0000005:
0000006: add eax, 10 //добавляем к еах десять
0000007: jmp [0000002] //прыгаем обратно - на адрес 0x0000002
0000008:
0000009:
---------------------------------------------------------------------------------
В результате этих действий мы заставили игру выполнить наш код (находящийся под адресам 0х0000006-0х0000007) а затем вернуться обратно и продолжить свой. Что нам это даёт? На самом деле - что угодно, всё зависит от фантазии и навыков программирования. Можно добавить жизней, можно патронов, можно всех врагов убить, можно любимой бабушке привет  передать - в общем, чего душа пожелает, а дальше игра послушно вернётся к своим делам. :)

Почему делать нужно именно так? Потому что про количество байт и длину кода я писал не просто так - мы не можем уместить тысячу байт кода в размеры одной трёх-четырёхбайтовой команды - поэтому засовываем код в отдельный участок памяти, обращаемся к нему, а затем продолжаем исполнение игрового кода. Прелесть в том, что код всегда будет находиться в одном и том же месте - адреса меняться не будут. Такая вот загогулина. Использовать этот не слишком хитрый приём мы будем ещё очень много раз, так что понимание успеет придти. Если же нет - пишите, задавайте вопросы. :)