20111103

Телепорт!

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

Ещё раз выражаю благодарность Xipho с форума Gamehacklab[RU], т.к. решение проблемы, возникшей при записи урока, нашлось именно благодаря его подсказке. Иначе бы мне пришлось дальше перелопачивать кучу иностранных ресурсов в поисках ответа, а это затянуло бы выход урока.

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

Следующие видеоуроки посвящу опциям rapid fire (быстрая стрельба) и no recoil (без отдачи), затем поломаем немного стратегии и RPG (мгновенная постройка зданий, работа с инвентарём и т.д.), после чего, вооружённые навыками, потихоньку начнём трейнеры писать.

Трейнеры будем писать сразу же на ассемблеры, причина довольно простая:

Ассемблер - низкоуровневый язык (чем ниже уровень - тем больше возможностей), выглядит он довольно странно и сам по себе сильно отличается от ЯВУ - языков высокого уровня, таких как C++, C#, Delphi или Visual Basic, на которых программирует подавляющее большинство вменяемых людей. :)

Код на языке ассемблера достаточно долго писать (команды маленькие и короткие, но их много - язык очень подробный), но этот код очень быстро выполняется и программы получаются крайне компактными, а учитывая то, что алгоритм работы трейнера по сути всегда один и тот же (и я вам его покажу и подробно объясню), то мы напишем его один раз и будем постепенно дорабатывать, не забивая голову языками высокого уровня. Кто захочет - тот освоит и их, тут разницы принципиальной нет. В будущем нам ЯВУ тоже наверняка понадобятся. ;)

8 комментариев:

  1. 1. Установка бряков может быть на "чтение и запись" и на "запись". Просто на "чтение" не существует.

    2. Из меню окна Автоассемблера как это было показано проще делать в следующей последовательности. Сначала делаем фрейм в автоассемблере "активация и деактивация" вызывая эту функцию из меню, а затем вызываем инъекцию. Получается без ручных копирования и вставки. Кому надо этот процесс описан здесь рис. 37 и рис.38 (http://chemax.ru/articles/dmc_tutor3.php)

    3. Телепорт сделанный на ассемблере как-то "закрученный и неудобный" и возможно должен состоять не из одно скрипта, а из трёх. При чем с флагами - это не очень хороший вариант. Операция чтения координат и записи это операция на несколько раз, а код инъекции с проверкой по флагам, что надо записать или прочитать координаты выполняется ой-йо-йой сколько раз. Поэтому для производительности и даже для удобства я бы сделал запись и чтение координат через отдельные потоки...

    Это чисто мой вариант предпочтения.

    Скрипт1. Инициализация памяти под "пользовательские" координаты и регистрация одной метки под которой эти координаты расположены. Делаем инъекцию по вытаскиванию и сохранению адреса на текущие координаты. Этот адрес регистрируем как метку. Этот скрипт должен вызваться один раз.
    Скрипт2. Сохранение координат. Написать код сохранения координат через скриптовую команду createthread(метка) над директивами [ENABLE] и [DISABLE]. Это означает что этот код будет выполняться в любом случае
    Скрипт3. Загрузка координат. Сделать также через createthread(метка)

    В таблице CE создать запись типа "заголовок" и под неё перетянуть все три скрипта. Назвать её Телепорт. Под ней первый скрипт - инициализация, второй - Сохранение положение. Трейтий - Загрузить положение.
    ------------
    Ну, и естественно на Lua-коде я раз в десять быстрее напишу, то что сейчас написал по трём скриптам выше на АА. На Lua точно также - сделаем инъекцию по вытаскивания указателя на АА-скрипте через Lua функцию autoAssemble(text, targetself OPTIONAL). На Lua сделаем две функции чтения и записи по этому адресу c проверкой что к адресу можно обращаться. Ну и на Lua-сделаем парочку горячих клавиш. При чем с ОСОБЫМ алгоритмом, если при нажатии на одну из двух этих комбинаций инициализации под телепорт не было, то сделать её.

    ОтветитьУдалить
  2. По первым двум пунктам - согласен, копировать-вставить в АА - это чисто моя привычка, давняя.

    По поводу "на ассемблере сложно" отдельных потоков:
    Выполнение cmp занимает два такта, так что со всякими современными i7 я не вижу тут проблемы производительности, 15 байт под хранение + 20-30 под код = не вижу проблем с памятью, но об этом чуток ниже.

    Я не сильно любитель скриптовых языков (хотя мощно и удобно - не спорю) - я больше автономные трейнеры люблю, написанные на чистом ассемблере. Зачем, кстати, АА при внедрении кода вставляет такие дикие кучи nop'ов между участками кода (штук по 10-15) - не понимаю, надо в коде CE порыться.

    Весь этот код должен крутиться в VirtualAlloc() памяти трейнера или внедрённой DLL, оптимизировать код можно ещё долго (вариант не самый удачный, но практичный - один раз внедрить код и потом менять два байта по хоткеям, выходит довольно просто), а вот скрипт в самом CE или на Lua ресурсов жрёт, на мой взгляд, побольше, да и меня в мелкую дрожь бросает от трейнеров размером в 3+ мб без звука и графики.

    Не уверен, что современная школа геймхакинга ориентируется на связку CE+Lua, я ориентируюсь на чистый асм. Можно ведь и на бейсике трейнеры писать, но они будут более громоздкие и менее производительные, а это не так здорово, как возможность разобраться в ассемблере.

    ОтветитьУдалить
  3. Читатель3/11/11 16:35

    Урок довольно сумбурный, слегка нелогичный, много сбиваешься. Наверное, пишешь импровизированно, а желательно заранее подготовить спич или набросок по теме, перед самой записью. За чистый асм спасибо. Возможно стоило добавить блок схему работы твоего кода, для наглядности, чтобы не путаться в переходах и флагах. ИДА может строить такие, ну или в паинте, визио набросать можно такую, вручную. Возможно стоило упоминуть, что в играх кроме координат бывают ещё и тайлы, и тогда их тоже стоит учитывать в телепорте.

    Спасибо за урок. Продолжай, ждём новых роликов и уроков. Не плохо было бы увидеть урок по инструментам которые могут облегчить работу или решить проблему при хакенге игр.

    ОтветитьУдалить
  4. Сбиваюсь - на момент записи уже устал сильно. Пишу всегда с первой попытки, если говорить сходу - лучше вспоминается нужная информация. Стараюсь говорить лучше, правда. :)

    С инструментами (идой, олей - как минимум) знакомить буду, возможно даже в следующем уроке.

    Иллюстрации тоже будут, но пока что код не такой сложный, как может быть.

    ОтветитьУдалить
  5. >>>Зачем, кстати, АА при внедрении кода вставляет такие дикие кучи nop’ов между участками кода (штук по 10-15) – не понимаю, надо в коде CE порыться
    ----------------
    Попробуй писать не
    адрес0: jmp адрес1, а
    адрес0: jmp short адрес1

    Это только в том случае, если адрес0 находится от ареса1 на расстоянии в байт, а может быть и в два байта, у же не помню.
    ---------------
    Чистый ассемблер это хорошо. Свои трейнеры на языке программирования это тоже хорошо. НО. На всём этом "далеко не уедешь" - не дотягивают они до той сформированной функциональной базы что есть у CE (у меня например нет времени переписывать эту функциональную базу в свой трейнер) Самая ключевая сторона у Cheat Engine это текстовые скрипты позволяющие на полную катушку работать с виртуальным адресным пространством игры. А не CE-трейнер, это "пшик" - запишет/прочитает сотню байтов по адресам... а как же анализ дизассемблерного кода и ассемблирование? Не спорю, может быть этой функциональности и не надо кому-то. Но я, например, за то чтобы не писать каждый раз трейнер для официально всё новой и новой пропатченой игры. Сделал один раз трейнер и всё, он и будет работать, если конечно разработчики не добавят несколько строк кода рядом с ключевым таким образом, что сигнатура кода станет не уникальной.

    ОтветитьУдалить
  6. Сканер сигнатур пишется не так трудно и есть в подавляющем большинстве движков известных гх-команд. Зачем в функционал трейнеров впихивать ассемблер\дизассемблер - вот этого не совсем понимаю, хотя и универсально\удобно. Больше, в принципе, ничего от трейнера не требуется - внедриться в память игры (напрямую, через virtualalloc или через dll), переписать нужную инструкцию и потом безопасно выгрузиться из памяти, восстановив оригинал. CE так тоже умеет, но буквально пару дней назад я столкнулся с тем, что мне не хватает прав на операцию записи - с чистым ассемблером такого не возникло бы. То, что АА не требует себе права меня удивило, не буду скрывать.

    PS: Есть пара задумок по поводу генерации байт-кода, т.е. скормил тулзе адрес инструкции - а она тебе выдала готовый байт-код сигнатуры. Думаю, была бы полезная утилитка.

    ОтветитьУдалить
  7. keng, я сделал телепорт на CETRAINER с поддержкой хоткеев, отображением формы, с автоаатачем к процессу.. Если интересно то вот исходник. Сохранить в кодировки UTF-8 без BOM в Notpad++ как файл crimsonland.CETRAINER




    658FBD4EC3301485D306EAD0143131E319A48832010312B8AD40B4A5902046E4925B7A85E31B6C1728036FCA23F00E2469CAC262FBDC9FE3F3FD343C2F990C0E5922FA0332D98E331235985171967A630833E7FB7EEB12F079EE9A5F7E42B9FFDDD87CC0D4CDFDCF467841260573F544DA869D29C64BEB201B815EB4A738428D197E82574FC56EA9800553DB43A9E89909993B24DDDA4B40414EC6716130B3A495D4297FEB4627D131BFBB8F3B422168B7CE10AEE43A02BBD1429105B65526AE9EC1842C96D66C27A71ED81747B92856C07841413A945350417D772BC6E6EE1AF1A0446CEED784D78DBF9467DD88C7F20D785E9BF3539E1BB0965FF317586EB78F223E2499FEEF0FCB7E6740DA45622E4D0C8E75CEC7F1D5A3B83CBF8BFB4958B5EAFF7FB62A359619B442410B8360F818DEDB557982EE69CED82C1FE007A42BCFDB8554E89645F5B567E4CC8513690A58418A4CD05E897230F03CEF17



    4
    "X"
    80000008
    Float
    crimsonland.exe+8853C


    5
    "Y"
    80000008
    Float
    crimsonland.exe+8853C+4



    X = 0.0
    Y = 0.0
    local isUserAction = false

    function SavePosition()
    X = readFloat('crimsonland.exe + 8853C')
    Y = readFloat('crimsonland.exe + 8853C + 4')
    isUserAction = true
    end

    function LoadPosition()
    if isUserAction then
    writeFloat('crimsonland.exe + 8853C', X)
    writeFloat('crimsonland.exe + 8853C + 4',Y)
    end
    end

    function OnCheckHotkeys()
    if isKeyPressed(VK_K) then
    SavePosition()
    return
    end
    if isKeyPressed(VK_L) then
    LoadPosition()
    return
    end
    end

    form_show(trainerMainForm)
    control_setCaption(trainerMainForm, 'Teleport Crimsonland v1.9.8 RUS (game not found)')


    function FormClose(sender)
    closeCE()
    return caFree
    end

    processlist = getAutoAttachList()
    strings_add(processlist, 'crimsonland.exe')

    function onOpenProcess(processid)
    hotKeyTimer = createTimer(trainerForm)
    timer_setInterval(hotKeyTimer, 100)
    timer_onTimer(hotKeyTimer, OnCheckHotkeys)
    control_setCaption(trainerMainForm, 'Teleport Crimsonland v1.9.8 RUS (game is run)')
    end



    У меня заняло 20 минут на написание кода и то я отвлекался половину времени. Интересно узнать твоё мнение keng, на твоё усмотрение этот вариант на Lua для тебя проще чем тот, который ты записал на видео? :)

    ОтветитьУдалить
  8. Мда... не получилось вставить код, твоё парсер съел все теги.
    Идём тогда сюда (http://forum.gamehacklab.ru/topic/906-телепорт-keng-a-crimsonland/)

    ОтветитьУдалить

Не люблю мат и низкий уровень грамотности. Чем конкретнее поставите свой вопрос и чем лучше он будет выглядеть - тем большая вероятность на мой ответ. :)