Ссылочка. Сейчас убегаю на работу, так что подробности напишу позже. Смотрим, вникаем, задаём вопросы, если что-то не ясно.
Ещё раз выражаю благодарность Xipho с форума Gamehacklab[RU], т.к. решение проблемы, возникшей при записи урока, нашлось именно благодаря его подсказке. Иначе бы мне пришлось дальше перелопачивать кучу иностранных ресурсов в поисках ответа, а это затянуло бы выход урока.
В нём мы реализуем (при помощи родного отладчика и любимого ассемблера, конечно же) возможность телепортации главного героя с место на место, даже если игра сама по себе так не умеет. Красивая штука, впечатляющая, не в каждом трейнере такое встретишь - потому что не все так умеют. А вы теперь уметь будете. :)
Следующие видеоуроки посвящу опциям rapid fire (быстрая стрельба) и no recoil (без отдачи), затем поломаем немного стратегии и RPG (мгновенная постройка зданий, работа с инвентарём и т.д.), после чего, вооружённые навыками, потихоньку начнём трейнеры писать.
Трейнеры будем писать сразу же на ассемблеры, причина довольно простая:
Ассемблер - низкоуровневый язык (чем ниже уровень - тем больше возможностей), выглядит он довольно странно и сам по себе сильно отличается от ЯВУ - языков высокого уровня, таких как C++, C#, Delphi или Visual Basic, на которых программирует подавляющее большинство вменяемых людей. :)
Код на языке ассемблера достаточно долго писать (команды маленькие и короткие, но их много - язык очень подробный), но этот код очень быстро выполняется и программы получаются крайне компактными, а учитывая то, что алгоритм работы трейнера по сути всегда один и тот же (и я вам его покажу и подробно объясню), то мы напишем его один раз и будем постепенно дорабатывать, не забивая голову языками высокого уровня. Кто захочет - тот освоит и их, тут разницы принципиальной нет. В будущем нам ЯВУ тоже наверняка понадобятся. ;)
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-сделаем парочку горячих клавиш. При чем с ОСОБЫМ алгоритмом, если при нажатии на одну из двух этих комбинаций инициализации под телепорт не было, то сделать её.
По первым двум пунктам - согласен, копировать-вставить в АА - это чисто моя привычка, давняя.
ОтветитьУдалитьПо поводу "на ассемблере сложно" отдельных потоков:
Выполнение cmp занимает два такта, так что со всякими современными i7 я не вижу тут проблемы производительности, 15 байт под хранение + 20-30 под код = не вижу проблем с памятью, но об этом чуток ниже.
Я не сильно любитель скриптовых языков (хотя мощно и удобно - не спорю) - я больше автономные трейнеры люблю, написанные на чистом ассемблере. Зачем, кстати, АА при внедрении кода вставляет такие дикие кучи nop'ов между участками кода (штук по 10-15) - не понимаю, надо в коде CE порыться.
Весь этот код должен крутиться в VirtualAlloc() памяти трейнера или внедрённой DLL, оптимизировать код можно ещё долго (вариант не самый удачный, но практичный - один раз внедрить код и потом менять два байта по хоткеям, выходит довольно просто), а вот скрипт в самом CE или на Lua ресурсов жрёт, на мой взгляд, побольше, да и меня в мелкую дрожь бросает от трейнеров размером в 3+ мб без звука и графики.
Не уверен, что современная школа геймхакинга ориентируется на связку CE+Lua, я ориентируюсь на чистый асм. Можно ведь и на бейсике трейнеры писать, но они будут более громоздкие и менее производительные, а это не так здорово, как возможность разобраться в ассемблере.
Урок довольно сумбурный, слегка нелогичный, много сбиваешься. Наверное, пишешь импровизированно, а желательно заранее подготовить спич или набросок по теме, перед самой записью. За чистый асм спасибо. Возможно стоило добавить блок схему работы твоего кода, для наглядности, чтобы не путаться в переходах и флагах. ИДА может строить такие, ну или в паинте, визио набросать можно такую, вручную. Возможно стоило упоминуть, что в играх кроме координат бывают ещё и тайлы, и тогда их тоже стоит учитывать в телепорте.
ОтветитьУдалитьСпасибо за урок. Продолжай, ждём новых роликов и уроков. Не плохо было бы увидеть урок по инструментам которые могут облегчить работу или решить проблему при хакенге игр.
Сбиваюсь - на момент записи уже устал сильно. Пишу всегда с первой попытки, если говорить сходу - лучше вспоминается нужная информация. Стараюсь говорить лучше, правда. :)
ОтветитьУдалитьС инструментами (идой, олей - как минимум) знакомить буду, возможно даже в следующем уроке.
Иллюстрации тоже будут, но пока что код не такой сложный, как может быть.
>>>Зачем, кстати, АА при внедрении кода вставляет такие дикие кучи nop’ов между участками кода (штук по 10-15) – не понимаю, надо в коде CE порыться
ОтветитьУдалить----------------
Попробуй писать не
адрес0: jmp адрес1, а
адрес0: jmp short адрес1
Это только в том случае, если адрес0 находится от ареса1 на расстоянии в байт, а может быть и в два байта, у же не помню.
---------------
Чистый ассемблер это хорошо. Свои трейнеры на языке программирования это тоже хорошо. НО. На всём этом "далеко не уедешь" - не дотягивают они до той сформированной функциональной базы что есть у CE (у меня например нет времени переписывать эту функциональную базу в свой трейнер) Самая ключевая сторона у Cheat Engine это текстовые скрипты позволяющие на полную катушку работать с виртуальным адресным пространством игры. А не CE-трейнер, это "пшик" - запишет/прочитает сотню байтов по адресам... а как же анализ дизассемблерного кода и ассемблирование? Не спорю, может быть этой функциональности и не надо кому-то. Но я, например, за то чтобы не писать каждый раз трейнер для официально всё новой и новой пропатченой игры. Сделал один раз трейнер и всё, он и будет работать, если конечно разработчики не добавят несколько строк кода рядом с ключевым таким образом, что сигнатура кода станет не уникальной.
Сканер сигнатур пишется не так трудно и есть в подавляющем большинстве движков известных гх-команд. Зачем в функционал трейнеров впихивать ассемблер\дизассемблер - вот этого не совсем понимаю, хотя и универсально\удобно. Больше, в принципе, ничего от трейнера не требуется - внедриться в память игры (напрямую, через virtualalloc или через dll), переписать нужную инструкцию и потом безопасно выгрузиться из памяти, восстановив оригинал. CE так тоже умеет, но буквально пару дней назад я столкнулся с тем, что мне не хватает прав на операцию записи - с чистым ассемблером такого не возникло бы. То, что АА не требует себе права меня удивило, не буду скрывать.
ОтветитьУдалитьPS: Есть пара задумок по поводу генерации байт-кода, т.е. скормил тулзе адрес инструкции - а она тебе выдала готовый байт-код сигнатуры. Думаю, была бы полезная утилитка.
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 для тебя проще чем тот, который ты записал на видео? :)
Мда... не получилось вставить код, твоё парсер съел все теги.
ОтветитьУдалитьИдём тогда сюда (http://forum.gamehacklab.ru/topic/906-телепорт-keng-a-crimsonland/)