srg91 Опубликовано 26 февраля, 2017 Поделиться Опубликовано 26 февраля, 2017 Всем привет. Сегодня я расскажу о том, как создавать нужный автомобиль с помощью CE в GTA Vice City. Как и говорил partoftheworlD, это очень просто, но раз возникают вопросы, я решил написать небольшой гайд. Собственно, выйти на функции создания автомобилей очень просто - в игре есть читы, которые позволяют "вызывать" себе танк, катафалк и другие автомобили. Поэтому выйдя на функцию обработки чита - мы найдем функции для создания автомобиля. Приступим. Для начала вспомним несколько читов для создания автомобилей. Я выбрал чит-код создания катафалка - THELASTRIDE , но так же можно использовать наш любимый чит создания танка - PANZER. Собственно ввод кодов - это операция по сохранению текущего введенного символа в строку и последующая проверка получившейся строки на соответствие. Каждый введенный символ записывается как в стек, поэтому в реальности эти читы выглядят как REZNAP и EDIRTSALEHT. Но если поискать данный текст, мы его не найдем. Как же так спросите вы? На самом деле функция обработки чит-кодов срабатывает на вводе последней буквы, поэтому проще всего просто искать часть введенного кода. Выйдем в меню игры, введем чит-код THELASTRIDE и попробуем поискать подстроку TSALEHT (не забываем переворачивать чит-код) в игре: Spoiler Ура, мы нашли текст по адресу 00A0F94F. Не будем его запоминать, он нам не пригодится, а сразу посмотрим, что же творится в памяти. Нажмем на адрес правой кнопкой мыши и выбираем Browse this memory Region. Spoiler В памяти сразу поднимемся на пару строк вверх, обычно строки длиннее чем мы искали: Spoiler Ура, видим часть введенного нами кода. Так же могут присутствовать и другие куски текста, например на скришоте я немного побегал перед вводом чит-кода. Теперь мы видим, что в реальности строка ввода чит-кода больше чем мы ожидали, а её начало находится там, где присутсвуют первые символы DW DIRTSAL, т.е. по адресу 00A0F94A. Добавим этот адрес в табличку (размер строки вычислен эмпирическим путем - посчитал не нулевые байты): Spoiler Теперь если в игре мы побегаем или введем другие чит-коды, увидим как они укладываются в памяти. Посмотрим же, что использует этот буфер - попросим CE найти всех, кто использует данный адрес при вводе чит-кода Сначала жмем ПКМ на адресе в главном окне CE и выбираем Find out what accesses this address: Spoiler Теперь переключимся в игру и введем любое слово, например HELLOGHL. Этим мы отсеим инструкции, которые используют наш адрес при обычном вводе. В окне появились следующие инструкции, мы будем их игнорировать: Spoiler Теперь введем чит-код на создание автомобиля - THELASTRIDE. Внимательно следим за окном с инструкциями, т.к. в процессе ввода у меня появились еще несколько инструкций, которые используют адрес, но не влияют на появление машины. После ввода последней буквы видим следующую картину: Spoiler Уже можно заметить несколько функций, выполняющихся один раз. Для того, чтобы отсеять лишние инструкции, попробуем ввести другой чит-код, не относящийся к созданию автомобилей, например LEAVEMEALONE: Spoiler Ура, из предыдущих инструкций у нас осталось одна - инструкция mov byte ptr [00A0F94A] по адресу 004AC84A. Давайте выделим её и нажмем Show disassembler, чтобы увидеть, где она выполняется: Spoiler Собственно мы видим некое условие, после которого в наш буфер записывает 0x20, он же 32 он же пробел и вызывается некая функция gta-vc.exe+AE7C0 с аргументом AC. Заочно можно нас поздравить, потому что мы нашли нужную нам функцию, осталось только убедиться в этом. Попробуйте тем же способом найти чит-функцию для создания танка. Я её уже нашел, давайте посмотрим: Spoiler Видно, что функция находится немного в другом месте, но отличие состоит только в том, какой аргумент передается в функцию - push записывает в стек A2 , вместо AC. В остальном код условия идентичен и я предлагаю попробовать просто вызывать функцию gta-vc.exe+AE7C0 с разными параметрами. Для вызова функции мы будем использовать AutoAssembe и функцию createthread. Зайдем в AutoAssembler (откроем Memory Viewer, меню Tools - AutoAssemble) и набросаем следующий скрипт: Spoiler [ENABLE] // код, который выполнится при включении скрипта // выделяем память под нашу функцию, хватит и 64 байта alloc(our_func, 64) // начало нашей функции // фактически просто копируем код из игры our_func: // записываем в стек AC, он же 172 push 000000AC // вызываем некую функцию call gta-vc.exe+AE7C0 // убираем из стека наш AC pop ecx // конец функции ret // создаем поток, который прыгнет на нашу our_func и выполнит код createthread(our_func) [DISABLE] // код, который выполнится при выключении скрипта // просто освобождаем память от нашей функции dealloc(our_func) Добавим его в таблицу через File - Assign to current cheat table и можно закрывать окно Auto assemble. Скрипт выделяет в памяти игры 64 байта для себя, после чего записывает туда инструкции, которые мы скопировали из оригинальной игры и просит createthread выполнить их. Обратите внимание, что аргументы в данную функцию передаются как push AC. В оригинальной игре после call мы можем заметить инструкцию pop ecx. Это значит, что функция не трогает стек и мы сам должны двигать его за ним (т.е. откатить push AC). Поэтому после функции выполняется pop и мы обязательно должны его скопировать, иначе ret будет пытаться вернуть поток не куда-то по адресу 0xAA123456, а по адресу 0x000000AC. Почему pop использует ecx? В данном случае - потому что левая пятка компилятора так решила и это ни на что не влияет (ecx спокойно можно заменить на eax и другие регистры). Ура, скрипт в нашей таблице, давайте же активируем его! Смотрим на результат и...: Spoiler Наш скрипт вызвал чит-функцию создания катафалка! Наверное вы уже догадались, что если мы заменим push AC на push A2 мы увидим заспаунившися танк? Spoiler Получается, что AC - это катафалк, а A2 - танк. Поискав GTA Vice City Vehicle IDs, мы найдем, что действительно, A2 = 162 - это Vehicle ID танка, а AC = 172 - катафалк. Попробуем указать свой ID, один из списка, например 168 (такси). Передача аргумента превратится в push #168: Spoiler Можно сказать, что наш скрипт работает! Осталось вынести ID модели как переменную: Spoiler [ENABLE] // код, который выполнится при включении скрипта // выделяем память под нашу функцию, хватит и 64 байта alloc(our_func, 64) // выделяем память под переменную alloc(our_vehicle_id, 4) // объявляем нашу our_func как переменную, // чтобы можно было вызывать createthread из другого скрипта registersymbol(our_func) // объявляем нашу our_vehicle_id как переменную, // чтобы можно было обращаться из таблицы registersymbol(our_vehicle_id) // записываем начальное занчение our_vehicle_id: // sabre turbo dd #206 // начало нашей функции // фактически просто копируем код из игры our_func: // записываем в стек наш ID машины push [our_vehicle_id] // вызываем некую функцию call gta-vc.exe+AE7C0 // убираем из стека наш AC pop ecx // конец функции ret [DISABLE] // код, который выполнится при выключении скрипта // удаляем информацию о функции dealloc(our_func) unregistersymbol(our_func) // удаляем информацию о переменной dealloc(our_vehicle_id) unregistersymbol(our_vehicle_id) Я удалил из скрипта функцию вызова потока, чтобы переместить её в отдельный скрипт: Spoiler [ENABLE] createthread(our_func) [DISABLE] Теперь можно добавить в таблицу адрес our_vehicle_id, в который после записи скрипта будет записано число 206 (ID наикрутейшего Sabre Turbo). Это число отвечает за то, что мы передаем в чит-функцию и меня его мы будем менять ID заспаунившегося автомобиля: Spoiler Результат: Spoiler И о проблемах Скрипт фактически вызывает чит-код, поэтому мы начинаем слыть читерами, рейтинг в игре уменьшается и т.д. Это довольно легко обходится, т.к. если мы провалимся в функцию gta-vc.exe+AE7C0, перед самым ret есть две инструкции - add [gta-vc.exe+5B4F94],000003E8 и mov byte ptr [gta-vc.exe+60FB37],01 . Первая накидывает очки читерства (они хранятся отдельно) и устанавливает флаг - "этот парень использовал коды". Если их занопить - игра никогда не узнает о ваших проделках. И вновь, потому что мы просто вызываем функцию чит-кода, она спаунит машины только на дорогу. Она находит ближайшую RoadPoint, прибавляет по оси Z несколько метров и спаунит авто. Поэтому создать авто прямо перед игроком так просто не получится. Ну и основная проблема - это то, что в данной функции использует конструктор только для автомобилей. Он так же используется для вертолетов, но вот байки и лодки с ним заспаунить не получится (заспаунится, но крешится при посадке и выглядит, кхм...): Spoiler О том, как обойти эти проблемы и вызывать уже конструкторы классов мы узнаем в следующем уроке С видеоформатом гайдов мне сложно работать (довольно тяжело как смотреть, так и записывать их), поэтому уроки в текстовом формате. 1 13 Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 27 февраля, 2017 Поделиться Опубликовано 27 февраля, 2017 Спавн через Lua как-то так Скрытый текст Скрытый текст function SpawnGameObject(id, name) autoAssemble([[ globalalloc(spawnFunction1, $1000) spawnFunction1: push ]]..id..[[ call gta-vc.exe+AE7C0 pop ecx ret createthread(spawnFunction1)]]) speak(name) end В консоли Lua ввести, что-то типа SpawnGameObject(206, "Sabre Turbo ") Я бы не сразу догадался искать перевернутый текст и не сразу бы догадался об инструкциях add [gta-vc.exe+5B4F94],000003E8 и mov byte ptr [gta-vc.exe+60FB37],01 Интуиция мне подсказывает, что createthread() вызывать не всегда безопасно, например, когда другой поток выполняет код в той же области памяти. Я могу ошибаться, надо будет про потоки почитать. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 12 марта, 2017 Поделиться Опубликовано 12 марта, 2017 В 27.02.2017в17:17, MasterGH сказал: Интуиция мне подсказывает, что createthread() вызывать не всегда безопасно, например, когда другой поток выполняет код в той же области памяти. Я могу ошибаться, надо будет про потоки почитать. Небезопасно только при использовании общих данных, не более: когда один поток читает, а другой пишет в ту же ячейку, но тут это вроде как не грозит, потому что инструкции сразу меняют значения, даже не считывая их. Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 У меня крашится;( Автор, почему именно такой адрес? У меня на его месте байты XOR [адрес], eax это точно тот адрес? Почему номер машины кладется в стек, а в функции вызывается из esi ? Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 4 мая, 2017 Автор Поделиться Опубликовано 4 мая, 2017 (изменено) 1 hour ago, Trix said: Автор, почему именно такой адрес? Привет. Если внимать читательнее - мы выходим на адрес функции через ввод чит-кода. Как только введеный чит-код совпадает с одним из списка - в строку ввода чит-кода записывается завершающий символ и вызывается нужная нам функция (её можно определить по передаваемому параметру A2). Собственно тебе нужно выйти на следующие инструкции, там же ты и найдешь адрес функции: Spoiler Если тебе нужно найти саму функцию в игре, но ты не хочешь ориентироваться на адрес модуля - провались внутрь самой функции (ПКМ на call - далее Follow) и через aobscan найди её в игре, после так же вызывай через call. 1 hour ago, Trix said: Почему номер машины кладется в стек Увы, под руками сейчас нет игры, но если ты провалишься в функцию, что увидишь, что она берет данные из стека и записывает их в esi. По типу mov esi, [esp+4] Изменено 4 мая, 2017 пользователем srg91 Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) 1 час назад, srg91 сказал: Привет. Если внимать читательнее - мы выходим на адрес функции через ввод чит-кода. так понимаю, у нас разные версии игры, что меня затруднило((( У меня затруднения с Find out what accesses this address: получается вот такой список функций, пробовал неоднократно Скрытый текст Найти функцию, как у вас (которая сравнивает строку, как я понял) не удалось... Или она все же есть? Ибо в регионе памяти не удалось найти похожее сравнение 1 час назад, srg91 сказал: Если тебе нужно найти саму функцию в игре, но ты не хочешь ориентироваться на адрес модуля - провались внутрь самой функции (ПКМ на call - далее Follow) и через aobscan найди её в игре, после так же вызывай через call. В общем, а если есть сам адрес функции, могу ли я обратно узнать кто его вызывает? Найти адрес через ввод чита для меня осталось загадкой, буду благодарен за разъяснения, если можно. Но у меня получилось найти его вручную отмотав достаточно приличный кусок кода, так что будет интересно узнать, почему у автора есть функция, а у меня ее нет) И да, гуглил, гуглил, а найти номера всех машин не удалось даже на сайтах разработчиков модов. Нет ли у кого ссылки?) Спасибо за статью) Изменено 4 мая, 2017 пользователем Trix UPD Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) 36 минут назад, Trix сказал: В общем, а если есть сам адрес функции, могу ли я обратно узнать кто его вызывает? Угу ставишь бряк и смотришь на вершину стека. 36 минут назад, Trix сказал: И да, гуглил, гуглил, а найти номера всех машин не удалось даже на сайтах разработчиков модов. Нет ли у кого ссылки?) Плюс в статье уже все есть. В 26.02.2017 в 16:12, srg91 сказал: Поискав GTA Vice City Vehicle IDs Видимо гуглить не умеешь, первая ссылка в гугле http://www.gtamodding.com/wiki/List_of_vehicles_(VC) Изменено 4 мая, 2017 пользователем partoftheworlD Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 4 мая, 2017 Автор Поделиться Опубликовано 4 мая, 2017 7 minutes ago, partoftheworlD said: Плюс в статье уже все есть спасибо, как раз об этом писал ) 42 minutes ago, Trix said: Найти функцию, как у вас Похоже и правда нет. Это не сравнение, а запись пробела вместо конечного символа. Похоже действительно недавно появилась. В целом да, по другому наверное только мотать до кода, в GTA3 я кажется только так и делал. 43 minutes ago, Trix said: В общем, а если есть сам адрес функции, могу ли я обратно узнать кто его вызывает? Можешь, как написали выше. Но я так понимаю в твоем случае тебе это не нужно же? Я так понимаю ты хочешь просто вызвать эту функцию из своего проекта? Если так - в своем проекте ты можешь искать функцию через маску байтов по типу aobscan или, если сложно, то ты можешь просто взять смещение модуля 'gta-vc.exe', прибавить к нему смещение функции (те самые +AE7C0 в моем случае) и делать call по этому адресу. Но смещение не будет работать на других версиях игры. Поправьте, пожалуйста, если не прав. Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 3 минуты назад, srg91 сказал: Можешь, как написали выше. Но я так понимаю в твоем случае тебе это не нужно же? Я так понимаю ты хочешь просто вызвать эту функцию из своего проекта? да, хотел бы вызвать функцию из проекта ради теста) Переписал инъектируемые байты, вышло вот это Скрытый текст byte[] asm = new byte[] { 0x68, 0xB1, 0x00, 0x00, 0x00 , // - push 000000B1 { 177 } 0xE8, 0xE6, 0xE8, 0x5D, 0xFF, // - call gta-vc.exe+AE8F0 0x59, // - pop ecx 0xC3 // - ret }; Однако, игра все так же крашится, в чем я мог допустить ошибку? Ссылка на комментарий Поделиться на другие сайты Поделиться
DieVis Опубликовано 25 декабря, 2017 Поделиться Опубликовано 25 декабря, 2017 (изменено) Здравствуйте, а как выйти через активацию кода в игре на адрес\инструкцию в другой игре, коды через стрелочки на клаве... Пример: Скрытый текст Коды на машины:1) → → ↓ ←2)→ ↑ → ↑3) ← ← ← →4) → → ← ←5) ↓ ↓ → ←6) → → → →Код на персонажей:7) ↓ ↓ ↓ ← Коды отключаются только после перезапуска игры, и вводятся один раз за сессию, после перезапуска вводить по новой. Изменено 25 декабря, 2017 пользователем DieVis Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 25 декабря, 2017 Поделиться Опубликовано 25 декабря, 2017 56 минут назад, DieVis сказал: Коды отключаются только после перезапуска игры, и вводятся один раз за сессию, после перезапуска вводить по новой. Обработчик событий клавиатуры возможно. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения