MasterGH Опубликовано 11 декабря, 2009 Поделиться Опубликовано 11 декабря, 2009 Здесь будет рассматриватся и может обсуждаться/дополняться моё руководство по Autoassembler Engine. Нужные ссылки на CE:1. Сайт английской версии (последняя версия CE 6.0 на 20 апреля 2011 )2. Русская CE 5.6 (устанавливается поверх английской CE 5.6 находящаяся на официальном сайте; если хотите генерировать трейнеры, то только лучше на этой версии пока не вышла версия CE6.1)3. Русская CE 5.5Статья в которой обсуждается работа с автоассемблером (весь пункт 3): DevilMyCry.rar. Эту статью лучше прочитать после чтения информации ниже.Дополнительная информация:Если делаете читы для себя, то Вам будет достаточно автоассемблерных скриптов CE. Если нужны трейнеры, то их генерировать может CE 5.6 и будущая CE 6.1. CE 6.0 генерировать трейнеры не умеет, но зато поддерживает LUA - скрипты, которые могут создавать трейнеры скриптами только при наличии CE6.0. Чтобы делать трейнеры на LUA скриптах нужно иметь опыт программирования. Для новичков проще пользоваться автоассемблерными скриптами.На официальном сайте ожидается конечный реализ CE 6.1 с поддержкой русского языка.Зайдите в подфорум реализы Cheat Engine чтобы попробовать возможности CE 6.1 Альфа 8.-----------------------------------------1. Обзор автоассемблераПосмотрим с чем придётся иметь дело...Рис.1 Окно автоассемблера после генерации шаблонаЕсли Вы решите исправить код игры, то вам придётся писать код в этом окне. Также Вам вручную придётся убирать комментарии если они вам мешают. К сожалению разработчик Дарк Байт не позаботился о том как убрать эти комментарии одним махом.Сейчас я напишу как сгенерировать такой шаблон. А затем как и что в нём редактировать.1) Подключитесь к процессу игры. Надеюсь Вы знаете как это делать. В версии CE 6.0 это можно сделать через значок "Компьютер"2) Найдите адрес нужного параметра1 в игре3) На адресе вызовете меню правым кликом мыши и поставьте брейкпоинт "на запись" или "на доступ". Надеюсь вы знаете как это сделать, если немного знаете английский.4) Войдите в игру и измените значение параметра15) Если вы сделали всё правильно, то в окне брейкпоинтов появится инструкция или их будет несколько.6) Перейдите по инструкции в дизассемблер. Надеюсь вы знаете как это сделать, если немного знаете английский.Ну а теперь смотрите рисунок. Он сделан на основе статьи, которую я выложил выше:Рис.2 Создание скрипта инъекции кодаИтак вы прошли весь путь создания скрипта. Вы не только узнали как генерировать шаблон, но и узнали куда вписывать новый код. С помощью скриптов вы можете:1) встроить чит-код удобно вклинив новое условие в код игры;2) быстро проверить работоспособность чит-кода;3) "получить" байты чит-кода для создания трейнера.Скрипт открывает перед вами МОЩНЫЕ возможности. Иногда нужно извернуться, чтобы написать скрипт. В этом есть кайф - изменить код игры под себя, обмануть игру.Это было знакомство, а теперь переходим к деталям.2 Скриптовые инструкцийСкрипты включают в себя инструкции ассемблера (будут разобраны позже), а также ряд специальных скриптовых команд. Существуют две основные директивы[DISABLE] // восстановить оригинальный код[ENABLE] // включить новое условиеЛистинг 1Под каждой директивой располагается код активации и деактивации чита. Пример0081e159:db 90 90[DISABLE]0081e159:dec [ecx] // вычесть единицу из адреса ecx (ecx считайте «переменной»)[ENABLE]Листинг 2Этот приём позволяет очень просто внедрить чит-код. Вычитание никогда не произойдёт. Подробнее будет ниже.Бывают такие случае что в ecx, могут проскакивать разные адреса и поэтому требуется сделать сложное внедрение. Для того чтобы это сделать нужно, вклинить условие в место 0081e159: db 90 90 изменив и не нарушив логику кода. Сделать это можно вписав прыжок в адрес 0081e159, который затрёт часть других инструкции (располагающихся ниже) ноп-ами. Об этом внедрении будет позже. А сейчас вернёмся к простому затиранию инструкций нопами.На этапе внедрения чит-кода вы можете увидеть, что каждая ассемблерная инструкция занимает определённое количество байт кода. Будьте внимательны и соблюдайте размер и логику, чтобы не напортачить чего либо, а то будет вылет из игры. Наверно, вы сталкивались – запускаешь трейнер чей-то и тут ВЫЛЕТ. Вот чтобы этого не было надо быть внимательным и знать ассемблерные инструкции.Возьмём за пример.Code :0081e159 - ff 09 - dec [ecx] //(это можно посмотреть в окнах бряков или окне дизассемблера)Листинг 3Как видно тут два байта занимает инструкция dec [ecx]. Думаю вы знаете что она означает вычитание единицы из адреса в ecx. Допустим можно стереть эту инструкцию, чтобы, например, патроны не вычитались.Чтобы инструкцию «потереть» нужно забить её «ноп»-ами. И сделать это можно либо так0081e159:nopnop[DISABLE]0081e159:dec [ecx][ENABLE]Листинг 4Либо так0081e159:db 90 90[DISABLE]0081e159:dec [ecx][ENABLE]Листинг 5Либо так0081e159:db 90 90[DISABLE]0081e159:db ff 09 // тоже самое что dec [ecx][ENABLE]Листинг 6db означает данные байта (data byte). Таким образом в данном случае патроны не будут изменяться.Но что делать, если я хочу чтобы патронов было жёстко 100 штук. Для этого нужно вписать Mov [адрес или регистр], патроны. Листинг 7Я сейчас точно не помню, но эта инструкция занимает, вроде, пять байт. А у нас доступно только два свободных байта (см. листинг 3) и как же быть?! Скрипт ниже, естественно, работать не будет0081e159:Mov [ecx],#100 // крах игры//затираются нижестоящие инструкции с нарушением логики кода[DISABLE]0081e159:dec [ecx][ENABLE]Листинг 8..ведь мы затрём пять байтов вместо двух. Игра вылетит. Для того чтобы игра не вылетела, нужно быть внимательным и соблюдать логику кода. Это это всё очень просто.Смотрим нижестоящие инструкции, например, одна из них будет такой.Code :0081e159 - ff 09 - dec [ecx]Code :0081e15b - xx xx xx xx xx– mov eax,[ecx]Листинг 9(код байтов инструкции mov я точно не помню, ссори, смотреть лень)Прыжок на свободное место в котором мы укажем новое условие занимает пять байт это "eb xx xx xx xx" . Это значит, что прыжок затрёт пять байт, начиная с адреса 0081e159 и оставит два байта «ошмётка» последующей инструкции (ий) которые выделены красным. Ошмётки мы затираем ноп-ми (иначе будет вылет) и восстанавливаем инструкции в выделенной памяти соблюдая логику кода.Совет.Вам нужно обращать внимание, что когда вы внедряете чит-код, то вы затераете пять байт по стандарту прыжкомJmp адрес (занимает пять байт)или в редких случаяхcall адрес (занимает пять байт)Таким образом, скрипт примет вид ниже. Появляются новые скриптовые команды.Alloc(newmem,2024) //выделение памяти рамзмером 2024 байт, которые округляться до 4 кбLabel(x1) //метка адресаnewmem:Mov [ecx],#100mov eax,[ecx] //дописали стёртую инструкциюjmp x10081e159:Jmp newmemx1:nop //наши 2 ошмёткаnop[DISABLE]0081e159:dec [ecx]mov eax,[ecx]dealloc(newmem)//высвобождаем выделённую память,чтобы не засорять память.[ENABLE]Листинг 10Теперь игра не должна вылетать.Если вы знаете инструкции ассеблера, то можно закрепить основы давайте рассмотрим пример из игры.mov ecx,[eax] mov edx,[esp+04]//<< здесь сработал бряк...core.dll+4285C: //<<адрес кода игрыЛистинг 11Инструкция mov edx,[esp+04] работает с адресом здоровья как моего игрока, так и других игроков. Что бы прописать здоровье моего игрока я нашёл многоуровневый указатель (как это делать напишу потом) и построил скрипт с фильтром. Сам фильтр можно видеть ниже.mov ebx,[core.dll+00155744] //строим многоуровневый указательmov ebx,[ebx+350]add ebx,43C //ebx=[[core.dll+00155744h]+350h]+43Ch – многоуровневый указатель, cmp eax,ebx //если игрок наш, то прописать 250 очков здоровьяpop ebx //восстановили ebxjne short originalcodemov byte ptr [eax],#250 //пишем здоровье нашему гирокуoriginalcode: //метка оригинального кодаmov ecx,[eax] //дописываем затёртые инструкции для восстановления логики кодаmov edx,[esp+04]push ebx //регистр нам будет нужен, поэтому запихнём его в стек и потом вернём обратноЛистинг 12А теперь листинг 12 встроим весь скрипт.UnrealTournament2003+ (InfHealth)*/ [ENABLE]alloc(newmem,2024) label(returnhere) label(originalcode) newmem:push ebx mov ebx,[core.dll+00155744] add ebx,350 mov ebx,[ebx] add ebx,43C cmp eax,ebx //ebx=[[core.dll+00155744h]+350h]+43Chpop ebx jne short originalcodemov byte ptr [eax],#250 originalcode: mov ecx,[eax] mov edx,[esp+04] jmp returnhere core.dll+4285c: jmp newmem nop returnhere: [DISABLE] core.dll+4285c:mov ecx,[eax] mov edx,[esp+04] /*MasterGH(c) 04.01.08. Листинг 13Обратите внимание на то, как мы встроили новое условие. Мы сравнили игрока со своим по его указателю и если это свой игрок, то запишем ему полное здоровье.Совет.Внимательно следите нужно ли сохранения регистра флагов pushf/popf. В большинстве случаев это не нужно, в противном будет измнена логика и может быть крах игры.В скриптах можно много чего «мутить». Разберём специальные команды скрипта (возможно это не все команды, см. справку CE)ALLOC(имя, размер)- выделение памятиDEALLOC(имя) - высвобождение памятиLABEL(имя) - объявление метокFULLACCESS(адрес/метка, размер) - установка полного доступа по адресуREGISTERSYMBOL(имя) - регистрация метки, метка будет доступна в окне адресов и вдругих скриптахUNREGISTERSYMBOL(имя) - убираем меткуDEFINE(имя,инструкция) - почти неприменятся, если инструкция повторяется то удобно её обзвать и присвоить имяINCLUDE(имя файла) - учитывает метки других файлов-скриптовLOADBINARY(адрес,имя файла) - загрузка данных или кода из файла по данному адресуCREATETHREAD(адрес) - создание потока, который будет выполняться начиная с адресаLOADLIBRARY(имя файла) - подгрузка библиотекиREADMEM(адрес,размер) - в скрипт вставляются байты с некоторого адреса.db, dw, dd - означает вставка байтов, 2 байтов, 4 байтов.Ну и примеры из англоязычной справкиБазовая основа скрипта. jmp 00410000nopnopnop00410000:mov [00580120],esimov [esi+80],ebxxor eax,eaxjmp 0045103100451029:Листинг 14Использование меток. 00451029:jmp 00410000nopnopnopmylabel:00410000:mov [00580120],esimov [esi+80],ebxxor eax,eaxjmp mylabellabel(mylabel)Листинг 15Использование выделения памяти00451029:jmp 00410000nopnopnop00410000:mov [alloc1],esimov [esi+80],ebxxor eax,eaxjmp 00451031alloc(memloc1,4)Листинг 16Использование меток и выделения памятиlabel(mylabel)00451029:jmp 00410000nopnopnopmylabel:00410000:mov [alloc1],esimov [esi+80],ebxxor eax,eaxjmp mylabelalloc(alloc1,4)Листинг 17Установка полного доступа. Обычно, используется совместно с областью неиспользуемого кода. Мной не рекомендуется, разве что в очень специфических задачах. Стоит отказаться от codecave (дыр кода), чтобы это не приводило к краху игры, а пользоваться выделением памяти.//из-за выравнивания кратному 1 странице памяти…00451029:jmp 00410000nopnopnop00410000:mov [00400800],esimov [esi+80],ebxxor eax,eaxjmp 00451031FULLACCESS(00400800,4) //доступ будет не к 4-м байтам, а к 4 кб (в 32 разрядных системах и 8 кб в 64 рязрядных)Листинг 18Использование DEFINE, как переопределение инструкций. 00400500:clear_eaxDEFINE(clear_eax,xor eax,eax)Листинг 19Использование чтения памяти некоторого размераalloc(x,16)alloc(script,2048)script:mov eax,[x]mov edx,[x+c]retx: // по этой метке будет записано 16 байт с адреса 00410000readmem(00410000,16) Листинг 20Пару слов стоит сказать о проверочных байтах. Все они вместе являются уникальной последовательностью (так предполагается) по которой можно установить адрес внедрения. Это нужно чтобы чит-код работал со всеми версиями игры.Пару слов про шаблоны.Шаблоны, возможно требуется доработать, поэтому о них пока писать руководство не буду.Опции Перехват API и переопределения кода, довольно специфичны и пока рассматриваться не будут. В общем если хотите научится писать скрипты, то учите ассемблерные инструкции и читайте темы на этом форуме.Если вам нужно в скрипте использовать указатели, то можно сделать их следующим образом.Такdd 0[[game.exe+3070A0]+68]+1e4: Или такmov eax,[eax+68] mov [eax+1e4],0mov eax,[game.exe+3070a0] 3. Ассемблерные инструкцииАссемблерные инструкции.Чтобы научиться писать скрипты нужно:1) Учиться по примерам скриптов на нашем форуме или на форуме CE2) Много практики3) Читать справку CE, статьи и примеры. Хорошие статьи, но на английском можно найти также здесь.О скриптах CE.Скрипты CE обладают ограничениями. Сложно описать какими именно и в каких ситуациях, но один пример можно привести. Если Вам требуется чтобы скрипт изменялся в какой-то момент определённым образом например перед первым запуском, то вы НЕ сможете это сделать только скриптами Автоассемблера. Ну, может быть и можно в зависимости от ситуации - исправлять машинный код скрипта1 машинным кодом скрипта2 с помощью Автоассемблера. Однако, есть более удобное решение - LUA Engine. Информацию по LUA Engine вы сможете найти в соседней теме. Ссылка на комментарий Поделиться на другие сайты Поделиться
Akama Опубликовано 14 февраля, 2010 Поделиться Опубликовано 14 февраля, 2010 Как сделать чтобы узнать адрес инструкции (или как правильно сказать...) чтобы тот имел вид Process.exe+XXX. Process.exe это запущенная игра, ХХХ это смещение. Стандартно в автоассемблер списывается адрес без смещения. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 15 февраля, 2010 Автор Поделиться Опубликовано 15 февраля, 2010 Можно перейти в отладчик по инструкции и нажать комбинацию: ctrl+M.Либо печатаешь вручную, либо дальше добавляешь адрес инструкции из отладчика в таблицу CE и дважды кликаешь по нему, появится окошко из которого можно скопировать в буфер "Process.exe+XXX". Пока других способов нет. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 6 июля, 2011 Поделиться Опубликовано 6 июля, 2011 (изменено) Не знаю, ответят или нет, но спрашиваю:А при замене куска памяти(Injection), если его можно включать и выключать, да и вообще, может произойти крэш?Типа, прога обращается к адресу 004F2A12, а инжект в этот момент заменяет адреса с 004F2A00 по 004F2A20(допустим).Я только второй день вплотную знакомлюсь со всей этой ассемблерной фигнёй, так что вопросов масса, но этот меня волнует больше всего.Ещё вопрос: иногда случается крэш без видимой причины. Всё вроде работает, но при установке брейкпоинта и пошаговом выполнении иногда крэшится. В чём может быть причина?Так всё работает идеально, а поставил брейкпоинт, пару циклов(и не обязательно пару, может вообще не вылететь, может вылететь сразу же) вручную запустил(ну в смысле кнопка Run, когда прога на брейкпоинте тормознёт), и крэш.Ну и интересно было бы как добавить к float'ному значению float'ное же.А то в eax что-то вроде 175.4727812, и добавть надо, допустим 3.4383Читал статьи(где про FPU), но автоассемблер говорит что хрен бы знал чего я от него хочу... Изменено 6 июля, 2011 пользователем Dark_XSM Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 6 июля, 2011 Автор Поделиться Опубликовано 6 июля, 2011 А при замене куска памяти(Injection), если его можно включать и выключать, да и вообще, может произойти крэш?Типа, прога обращается к адресу 004F2A12, а инжект в этот момент заменяет адреса с 004F2A00 по 004F2A20(допустим).Очень маловероятно что может произойти "крэш" процесса современной игры....иногда случается крэш без видимой причины. Всё вроде работает, но при установке брейкпомнта и пошаговом выполнении иногда крэшится. Это, кстати, тоже вопрос, в чём может быть причина?Так всё работает идеально, а поставил брейкпоинт, пару циклов(и не обязательно пару, может вообще не вылететь, может вылететь сразу же) вручную запустил(ну в смысле кнопко Run, когда прога на брейкпоинте тормознёт), и крэш.Причина скорее в антиотладочной защите. В Cheat Engine есть режим VEH-дебегера в таких случаях. Но против некоторых версий Старфорса не поможет.Ну и интересно было бы как добавить к float'ному значению float'ное же.А то в eax что-то вроде 175.4727812, и добавть надо, допустим 3.4383Читал статьи(где про FPU), но автоассемблер говорит что хрен бы знал чего я от него хочу...Если я не ошибся, то где-то так:[ENABLE]//code from here to '[DISABLE]' will be used to enable the cheatalloc(newmem,2048) //2kb should be enoughlabel(returnhere)label(originalcode)label(exit)label(value)newmem://....push eax //eax = 175.4727812fld dword [esp]fadd dword [value]fstp dword [esp]pop eax // eax = eax + 3.4383originalcode://...exit:jmp returnherevalue:dd (float)3.4383"Test.exe"+556DE:jmp newmemreturnhere:[DISABLE]"Test.exe"+556DE:mov eax,004546C0//Alt: db B8 C0 46 45 00dealloc(newmem) Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 7 июля, 2011 Поделиться Опубликовано 7 июля, 2011 Хм... это бы конечно хорошо, но как это скрестить с тем что есть я не понял.Есть вот что:newmem:pushf //на всякийpush ebx //в ebx строю указатель, в eax он уже естьmov ebx,[[[some.dll+01249F10]+11]+200] //собсно, постройка указателяadd ebx,208 //всё ещё она...cmp eax,ebx //сравнение того что у меня получилось с тем что записано в eax, ибо через это место единовременно считается примерно 200 переменных для разных адресовjne originalcode //прыг если не тоadd [eax],500000 //а если то, то, к примеру, добавить 500 тысяч обычных прям в памятьmovss xmm0,[eax] //запись из памяти в какое-то страшное местоoriginalcode:pop ebx //восстановление ebx до чего-то там в диапозоне от 1 до 7popf //восстановление "на всякий"mov ecx,esi //неизвестная фигняmovss [eax],xmm0 //запись в память из какого-то страшного местаjmp returnhereИменно тут вместо 500000 требуется нечто более точное, ибо в [eax] число с точкой, и требует точности, а то что я написал хоть и работает, но немного не так как хотелось бы.mov ecx,esi сюда запихать пришлось потому что в месте внедрения не хватило места для джампа. Я не знаю что они делают.P.S Я, кстати, думаю, что там где +500000 можно записывать не в память, а локально, но не знаю есть ли смысл. Быстродействие не страдает абсолютно, а для чего ещё менять запись?..upd:Вот до чего додумался за просмотром серии симпсонов(7-й сезон):newmem:pushfpush ebxmov ebx,[[[[[p4dftre.dll+01849C8C]+24]+28]+128]+4]add ebx,208cmp eax,ebxjne originalcodefld dword [ebx]fadd dword [value]fstp dword [ebx]movss xmm0,[ebx]originalcode:pop ebxpopfmov ecx,esimovss [eax],xmm0jmp returnherevalue:dd (float)1.0Удивительно, но работает именно так как надо.Благодарю за помощь.Хоть я и не понял как работает вот это:fld dword [esp]fadd dword [value]fstp dword [esp]...value:dd (float)1.0(это я к тому, что хотелось бы подробностей, как оно взаимосвязано, но самому смотреть лень) Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 7 июля, 2011 Автор Поделиться Опубликовано 7 июля, 2011 В какой-то игре случай с добавлением числа с точкой может быть разным и придётся писать инструкции иначе. Мой пример для всех игр не подходит и его нужно менять.Попробую написать подробнее.push eax //eax = 175.4727812fld dword [esp]fadd dword [value]fstp dword [esp]pop eax // eax = eax + 3.4383push eax //eax уже предположительно равен 175.4727812 и его помещаем в стек в [esp]fld dword [esp] // загружаем в ST0 значение 175.4727812 из стекаfadd dword [value] // добавляем к ST0 значение [value], меняется ST0fstp dword [esp] // перезаписываем значение в стеке c выплёвываем из ST0 уже суммуpop eax // eax = eax + 3.4383 // почти аналогично "выплёвываем" из стека сумму в eaxПо поводу твоего примера, лучше не писать цепочку в скрипте типа mov ebx,[[[[[p4dftre.dll+01849C8C]+24]+28]+128]+4] и убрать лишние инструкции. Цепочку лучше так не писать, потому что она рассчитывает один раз и ассемблируется как mov ebx,[адрес]. А адрес в течении игры может быть другим! Может быть вылет из игры. Если есть полная цепочка указателей, то лучше не делать сравнений... И того получаем:newmem: pushf mov ecx,[p4dftre.dll+01849C8C] mov ecx,[ecx + 24] mov ecx,[ecx + 28] mov ecx,[ecx + 128] mov ecx,[ecx + 4] lea ecx,[ecx + 208] // ecx = [[[[[p4dftre.dll+01849C8C]+24]+28]+128]+4]+208 fld dword [value] faddp dword [ecx] movss xmm0,[ecx] popf mov ecx,esi jmp returnherevalue: dd (float)1.0Может быть я где-то ошибся поэтому надо проверить в отладке. И ещё если знать работу с XMM-рами, то возможно можно ещё короче написать, т.к. в xmm0 в "младшей" части уже есть значение, к которому надо прибвить value. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 7 июля, 2011 Поделиться Опубликовано 7 июля, 2011 По поводу твоего примера, лучше не писать цепочку в скрипте типа mov ebx,[[[[[p4dftre.dll+01849C8C]+24]+28]+128]+4] и убрать лишние инструкции. Цепочку лучше так не писать, потому что она рассчитывает один раз и ассемблируется как mov ebx,[адрес]. А адрес в течении игры может быть другим! Может быть вылет из игры.Если честно, не очень понял. Адрес же через указатели генерится... и если адрес которым будет оперировать игра не совпадёт с тем с которым планировалось, просто ничего не произойдёт... по моему...Если есть полная цепочка указателей, то лучше не делать сравнений...Эм... указатель-то вроде точный... но не делать сравнения, значит просто его туда дописать отдельно? Э... что-то я тут подвис. Там же куча переменных идёт, через xmm0, все разные, для разных адресов...А в этом примере получается что любой адрес будет получать то что генерится в ecxИ кстати, почему ecx?lea ecx,[ecx + 208]Учтём.P.S В общем, либо я туплю, либо чего-то не понимаю. В данной ситуации это немного разные вещи... Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 7 июля, 2011 Автор Поделиться Опубликовано 7 июля, 2011 Если честно, не очень понял. Адрес же через указатели генерится... и если адрес которым будет оперировать игра не совпадёт с тем с которым планировалось, просто ничего не произойдёт... по моему...Если в течении игры адрес рассчитанный по цепочке указателей поменяется, то запись в него вызовет исключение времени выполнения, крах игры и сообщение об исключении. Если адрес за всю игру меняться не будет, то можно оставить цепочку указателей так как ты оформил. Проверить поменяется указательили нет, можно во время игры пройдя какую-то её часть. Если чит будет работать значит конечный адрес не поменялся.Эм... указатель-то вроде точный... но не делать сравнения, значит просто его туда дописать отдельно? Э... что-то я тут подвис. Там же куча переменных идёт, через xmm0, все разные, для разных адресов... А в этом примере получается что любой адрес будет получать то что генерится в ecx И кстати, почему ecx?Да, писать "отдельно", точнее встраивать новое условие записи в адрес через цепочку указателей в код игры.Ну, куча переменных... надо так написать код, чтобы логика кода игры работала так как надо.По ecx будет только тот адрес, который задан указателем. xmm0 и eax остаются в своём контексте выполнения кода, т.е. они равны значения без изменения.ecx я взял, потому что в него в оригинальном коде будет все равно перезапись из esi. А это значит, что ecx "свободная переменная" для наших действий до оригинального кода. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 8 июля, 2011 Автор Поделиться Опубликовано 8 июля, 2011 Ой. Инструкцию "movss xmm0,[ecx]" надо убрать. По идеи xmm0 дальше использоваться не будет. А если будет, то надо по другому написать. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 8 июля, 2011 Поделиться Опубликовано 8 июля, 2011 xmm0 используется там каждые 20-30 строк, при чём постоянно с записями типа movss xmm0,[какой-нить адрес], и movss [тот же адрес],xmm0Предыдущий код я понял, в тот раз затупил из-за movss xmm0,[ecx], но без неё всё стало ясно.Не совсем понял чемmov ecx,[[[[[p4dftre.dll+01849C8C]+24]+28]+128]+4]lea ecx,[ecx+208]хужеmov ecx,[p4dftre.dll+01849C8C]mov ecx,[ecx + 24]mov ecx,[ecx + 28]mov ecx,[ecx + 128]mov ecx,[ecx + 4]lea ecx,[ecx + 208]Одно и то же делают вроде?Или это в целях повышения стабильности? Типа, "а вдруг!.."?Но ведь если адрес поменяется, оба варианта окажутся не верными... и в случае сравнения вообще ничего не произойдёт, всё будет идти как раньше, вылета не будет.Кстати, крэш.Разбираюсь.upd: помогла заменаfld dword [value]faddp dword [ecx]наfld dword [ecx]fadd dword [value]fstp dwoed [ecx]Работает, но выглядит ужасно(не код, а последствия его срабатывания).Всё же оставлю сравнение, бывает когда изменение переменной нежелательно(оно само определяет, надо ли менять)newmem:pushfmov ecx,[[[[[p4dftre.dll+01849C8C]+24]+28]+128]+4]lea ecx,[ecx+208]cmp eax,ecxjne originalcodefld dword [ecx]fadd dword [value]fstp dword [ecx]movss xmm0,[ecx]originalcode:popfmov ecx,esimovss [eax],xmm0jmp returnhere Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 9 июля, 2011 Автор Поделиться Опубликовано 9 июля, 2011 Одно и то же делают вроде?Или это в целях повышения стабильности? Типа, "а вдруг!.."?Не одно и тоже. Способ который я привёл рассчитывает указатель каждый раз заново, а твой - только при активации чита. Применять тот или иной способ зависит от кода игры. Посмотри в дизассемблере что у тебя получается при активации чита. Так же советую это делать почаще для версии CE 6.1, т.к. она может неправильно ассемблировать.По поводу вылета на "faddp dword [ecx]". У меня вообще эта инструкция не ассемблировалась. Похоже она работает только с регистрами FPU. Ссылка на комментарий Поделиться на другие сайты Поделиться
VoLT Опубликовано 9 июля, 2011 Поделиться Опубликовано 9 июля, 2011 MasterGH а реально вызывать процедуры из CE по горячей клавише? Допустим при внедрении DLL можно вызвать фунцию из неё ... хотелось бы без DLL так же вызывать произвольную функцию в игре Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 10 июля, 2011 Поделиться Опубликовано 10 июля, 2011 Посмотри в дизассемблере что у тебя получается при активации чита.Понял.И ещё вопрос возник. Не совсем по этой теме...Я так понял, на LUA можно несколько удобнее сделать?Там же во время выполнения можно менять переменные по горячим клавишам, таким образом включая/отключая разные секции кода?Тогда получается что в моём случае можно было бы менять сразу несколько переменных, включая и отключая любые из них, не трогая остальные(записывающиеся в адреса), а в автоассемблере есть только варианты вкл/выкл вообще всего...Жаль что из программирования я тока про Паскаль чего-то помню, и про Java Script Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 10 июля, 2011 Автор Поделиться Опубликовано 10 июля, 2011 MasterGH а реально вызывать процедуры из CE по горячей клавише? Допустим при внедрении DLL можно вызвать фунцию из неё ... хотелось бы без DLL так же вызывать произвольную функцию в игреДа, реально. Предвижу несколько способов. Покажу на мой взглядлучший из них, но не проверенный и не полный, поэтому могут быть ошибки. function FunctionSpawnCar(hotkey) autoAssemble("CREATETHREAD(SpawnCar)") end function SetHotKey(func, hotkey) local objectHotKey = createHotkey(func, hotkey) generichotkey_setKeys(objectHotKey, hotkey) generichotkey_onHotkey(objectHotKey, func) end function Deinitialization() autoAssemble([[ unregistersymbol(SpawnCar) dealloc(SpawnCar) ]]) end function Initialization() local address = ... // получить адрес вызываемой функции local AAscript = [[ alloc(SpawnCar,2048) registersymbol(SpawnCar) label(stringCar) SpawnCar: push ... push ... push stringCar call ]]..address..[[ ret stringCar: db ... 00 // hex-строка машины оканчивающаясь нулевым символом ]] autoAssemble(AAscript) --создание формы трейнера -- ... --привязка функции Deinitialization() к закрытию формы -- ... --Назначение хоткеев setHotKey(FunctionSpawnCar, VK_F2) -- спавн некоторой машины end function onOpenProcess(processid) Initialization() end local aalist = getAutoAttachList() stringlist_add(aalist, "gta4.exe")Как видно здесь Lua код вперемешку с Автоассемблером. Есть инициализация, деинициализация, првязка горячей клавиши, создание потока на АА. Могут быть проблемы с поточной синхронизацией или другие, надо проверять на практике...Понял.И ещё вопрос возник. Не совсем по этой теме...Я так понял, на LUA можно несколько удобнее сделать?Там же во время выполнения можно менять переменные по горячим клавишам, таким образом включая/отключая разные секции кода?Тогда получается что в моём случае можно было бы менять сразу несколько переменных, включая и отключая любые из них, не трогая остальные(записывающиеся в адреса), а в автоассемблере есть только варианты вкл/выкл вообще всего...Жаль что из программирования я тока про Паскаль чего-то помню, и про Java Script1. Можно ли на Lua делать удобнее не знаю. Для каждого человека своё видение удобства.2. По горячим клавишам можно выполнять Lua функцию, которая могла бы на АА скриптах что-то делать... создавать новые "секции кода" и уничтожать старые.3. Переменные можно менять и без Lua. Зарегистрируй их в АА через registersymbol. Создай другой АА который бы менял значения по зарегистрированным меткам.4. Когда Lua поддержки в CE не было у меня была та же проблема. Lua я не знал, но учился на примерах. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 14 июля, 2011 Поделиться Опубликовано 14 июля, 2011 Ещё вопрос имеется.Есть несколько строк типа "repe movsd", в которых происходит что-то страшное.Мне в это надо вмешаться, и что-то подправить, но я не представляю как, и что...Как оно работает, и как вмешаться в её работу?Там что-то происходит, с участием адреса 306F962C (хотя скорее не он нужен), надо что бы этого не происходило.upd: думаю, это важно.Во время работы этой строки меняются esi и edi, с шагом 4 байта, и ecx с шагом 100000184306F926801B2F610...00000183306F926C01B2F614 Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 14 июля, 2011 Автор Поделиться Опубликовано 14 июля, 2011 "repe movsd" циклически перемещает данные 4-х байт из адреса EDI+ecx*4 в адрес ESI+ecx*4 уменьшая указанный ecx на единицу до тех пор пока ecx не будет равен нулю. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 18 июля, 2011 Поделиться Опубликовано 18 июля, 2011 Не знаю где спросить, а ИНет почему-то сильно тормозит, и просмотр тем куда надо писать может занять до 30 минут, так что спрашиваю тут:Нельзя ли поставить брейкпоинт так, что бы он срабатывал только тогда, когда число в адресе становится равным, к примеру, 5 ?Я не знаю как сформулировать вопрос, так что опишу ситуацию:Есть некий адрес, который используется для хранения самых разных значений, в том числе и нужного мне.Обращений к адресу примерно 1000 в секунду, примерно с 600 разных мест.И какое-то из обращений пишет в адрес цифру 5Можно как-то просто узнать, где она пишется, а не проверять каждую из 600 функций вручную? Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 18 июля, 2011 Поделиться Опубликовано 18 июля, 2011 Если для отладки используешь OllyDebug - там можно ставить условные брейкпоинты. Если же делаешь это в СЕ - тогда можно воспользоваться Lua. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 18 июля, 2011 Поделиться Опубликовано 18 июля, 2011 LUA я не знаю, на OllyDBG оно жалуется что найден отладчик. Ссылка на комментарий Поделиться на другие сайты Поделиться
aliast Опубликовано 18 июля, 2011 Поделиться Опубликовано 18 июля, 2011 В CE 6.1 я ставил условные бряки на конкретные значения в регистрах так. Сначала F5 ставит обычый бряк, потом правой кнопкой на бряке "Назначить\Изменить условия точки останова" и писал к примеру EBX==0x0E1244 (простое условие). Бряк срабатывал только когда в EBX проскакивало 0E1244. С обычными адресами не пробовал, но может быть можно задать условие вида "0xADDRESS==5"? Не уверен что синтаксис верен... Ссылка на комментарий Поделиться на другие сайты Поделиться
Dark_XSM Опубликовано 18 июля, 2011 Поделиться Опубликовано 18 июля, 2011 5 флоатная, выглядит как 40A00000"0xADDRESS" уже пробовал.Можно бы вычислить по обращениям в период между началом загрузки, и записью значения в постоянное место, но почему-то условие типа ((ESP == 0x0012FABC) and (EDI == 0x40A00000)) не срабатывает.А иначе я задолбаюсь кнопку продолжения тыкать. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 18 июля, 2011 Автор Поделиться Опубликовано 18 июля, 2011 Dark_XSM, вот Lua-код заготовка для решения твоей задачи. Ссылка на комментарий Поделиться на другие сайты Поделиться
misha Опубликовано 10 июля, 2012 Поделиться Опубликовано 10 июля, 2012 Привет! Использовал раньше вставки ассемблера для стационарных адресов, а сейчас понадобилось для адреса, найденного с помощью аобскан. Как быть?Простое подставление в код не помогает.Вот пример:results=AOBScan("83 C4 10 F3 0F 7E 4D D8 66 0F 57 C0 F2 0F 2A C0 F2 0F 59 C8 66 0F D6 4D E0","+X-W-C")count=stringlist_getCount(results)address_aob1 =getAddress(stringlist_getString(results,0))workTemplateAsmText1 = [[alloc(newmem,2048) //2kb should be enoughlabel(returnhere)label(originalcode)label(exit)newmem: //this is allocated memory, you have read,write,execute access//place your code hereoriginalcode:mulsd xmm1,xmm0mov [ebp-20],00000000exit:jmp returnhere]]..address_aob1..[[jmp newmemnopnopnopnopreturnhere: ]]autoAssemble(workTemplateAsmText1) Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 10 июля, 2012 Автор Поделиться Опубликовано 10 июля, 2012 Под newmem должен быть код. Его нет - результата в игре не увидишь. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения