Гость Опубликовано 22 января, 2014 Поделиться Опубликовано 22 января, 2014 Всем привет.Интересует такой вопрос - как сделать из опции "Бесконечное здоровье" - "Убийство с одного удара"?Допустим, я разобрал структуру, узнал как отличить игрока от противника. Но не получается сделать 2 независимые друг от друга опции. То есть, если я не хочу использовать бесконечное здоровье, а только убийство с одного удара, или наоборот. Как быть в этом случае?Бесконечное здоровьеnewmem:cmp [edi+13],#200je healthsub [edi+505],eaxjmp returnherehealth:sub [edi+505],0jmp returnhereУбийство с одного удара:newmem:cmp [edi+13],#200je one_hit_killmov [edi+505],0jmp returnhereone_hit_kill:sub [edi+505],0jmp returnhere Ссылка на комментарий Поделиться на другие сайты Поделиться
ICEBURG Опубликовано 22 января, 2014 Поделиться Опубликовано 22 января, 2014 Сделай еще одну проверку с коде:label(pHealth)registersymbol(pHealth)newmem:cmp [pHealth],0je +(через сколько прыгаем)cmp [edi+13],#200je healthsub [edi+505],eaxjmp returnherehealth:sub [edi+505],0jmp returnherepHealth:dd 0[DISABLE]unregistersymbol(pHealth)По хоткею меняешь в СЕ метку pHealth (1 или 0) Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 22 января, 2014 Поделиться Опубликовано 22 января, 2014 Так ведь таким образом мы просто привяжем часть скрипта к хоткею (если я правильно понял). Но мне надо разделить сами опции, т.е. чтобы при включении убийства с одного удара - не срабатывала бы опция "бесконечное здоровье", и наоборот - чтобы опция "бесконечное здоровье" не сбрасывала опцию убийства с одного удара, т.е. чтобы они друг друга не перезаписывали, и работали как вместе, так и отдельно друг от друга. Ссылка на комментарий Поделиться на другие сайты Поделиться
Tiger Опубликовано 22 января, 2014 Поделиться Опубликовано 22 января, 2014 я вижу тут две разные инструкции в первом скриптеsub [edi+505],eaxво второмmov [edi+505],0но если предположить, что первый тот, который нужен, тогда так[ENABLE]aobscan(address_aob,29 87 05 05 00 00 XX XX XX XX XX XX XX XX XX XX) // отредактируешь еще пару байтalloc(newmem, 2048)label(exit1)label(exit2)registersymbol(address_aob)registersymbol(En_health)registersymbol(En_one_hit_kill)newmem:pushfcmp [edi+13],#200jne exit1cmp [En_health],00je exit2xor eax,eax// mov [edi+505],#200 // можно заодно заполнить шкалу здоровья героя, как понимаю 200 HP это и есть максимумjmp exit2exit1:cmp [En_one_hit_kill],00je exit2mov eax,[edi+505]exit2:popfsub [edi+505],eaxretEn_health:db 00 00 00 00En_one_hit_kill:db 00 00 00 00address_aob:call newmemdb 90 // nop[DISABLE]address_aob:db 29 87 05 05 00 00 XX XX XX XX XX XX XX XX XX XX // отредактируешь еще пару байтunregistersymbol(address_aob)unregistersymbol(En_health)unregistersymbol(En_one_hit_kill)dealloc(newmem)ну и соответственно два скрипта активации[ENABLE]En_health:db 01[DISABLE]En_health:db 00 и [ENABLE]En_one_hit_kill:db 01[DISABLE]En_one_hit_kill:db 00и тогда вложишь два скрипта, активации на скрипт инжекта, ПКМ на родительском и там внизу "настройка группы" - 1 опция. "скрывать вложения если неативна..." и хоткеи активации трейнера на родителя, опциональные на соответственно вторые два скрипта. Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 23 января, 2014 Поделиться Опубликовано 23 января, 2014 (изменено) Нет, 200 - это идентификатор игрока, у противников всегда разные ID.sub [edi+505],eax - оригинальная инструкция, которая работает со здоровьем, mov [edi+505],0 - измененная оригинальная инструкция, которая записывает 0 (убивает противника, по которому прошел удар).В моем первом скрипте идет проверка по ID:newmem:cmp [edi+13],#200 //сравниваем значение по смещению 13, если значение 200 - значит это игрокje health // прыжок на опцию "бесконечного здоровья" для игрокаsub [edi+505],eax //если не игрок (ID другой) - ничего не меняем, т.е. оставляем оригинальную инструкцию потери здоровьяjmp returnhereTiger, твой пример я не понял, если честно, т.к. не знаком с аобсканом, и не знаю большинство ассемблерных инструкций. Но разобраться в нем попробовал все-таки.[ENABLE]aobscan(address_aob,29 87 05 05 00 00 XX XX XX XX XX XX XX XX XX XX) // понятия не имею что это, если проверочные байты - то откуда они взялись?alloc(newmem, 2048)label(exit1) // видимо, для выхода из опции, т.е. вставка оригинальной инструкции при отключении опции //для бесконечного здоровьяlabel(exit2) // то же самое, но для убийства с одного удараregistersymbol(address_aob) // регистрируем проверочные байты аобскана?registersymbol(En_health) // для включения / отключения бесконечного здоровьяregistersymbol(En_one_hit_kill) // для включения / отключения убийства с одного удараnewmem:pushf // не знаю для чего этоcmp [edi+13],#200 // сравнение ID, если 200 - значит игрок (не здоровье (для Tiger))jne exit1 // прыжок на опцию убийства с одного удара, если ID не равен 200 и не нулюcmp [En_health],00 // проверка включения опции бесконечного здоровья?je exit2 // если не включена опция бесконечного здоровья - прыгаем на оригинальную инструкциюxor eax,eax // проверка значения, видимо должно работать со строкой ниже, если не равно - ставим 200// mov [edi+505],#200 // можно заодно заполнить шкалу здоровья героя, как понимаю 200 HP это и есть максимум // но нет, 200 - ID игрокаjmp exit2 // прыжок на оригинальную инструкцию, но зачем? проверка включения опции бесконечного здоровья была, и там уже делали прыжок на оригинальную инструкцию потери здоровьяexit1: // опция убийства с одного удараcmp [En_one_hit_kill],00 // проверяем, включена ли опция убийства с одного удараje exit2 //если результат проверки равен нулю - прыгаем на оригинальную инструкцию потери здоровьяmov eax,[edi+505] // если опция включена - наносим урон, равный текущему количеству здоровья?exit2: // оригинальная инструкция потери здоровьяpopf // не знаю для чегоsub [edi+505],eaxret // не знаю для чегоEn_health:db 00 00 00 00 // что это делает?En_one_hit_kill:db 00 00 00 00 // тот же вопросaddress_aob:call newmemdb 90 // nop[DISABLE]address_aob:db 29 87 05 05 00 00 XX XX XX XX XX XX XX XX XX XX // отредактируешь еще пару байтunregistersymbol(address_aob)unregistersymbol(En_health)unregistersymbol(En_one_hit_kill)dealloc(newmem)Как вы наверное поняли - знаю я немного. Думаю, можно сделать и без аобскана.Собственно, можно-ли сделать так://за основу взят скрипт Tiger из предыдущего поста[ENABLE]alloc(newmem, 2048)registersymbol(health)registersymbol(one_hit_kill)label(returnhere)label(original)newmem:cmp [health],0 //сравниваем, если 0 (не включена)je original // выполняем оригинальную инструкциюjmp health // если не 0 - выполняем опцию бесконечного здоровьяcmp [one_hit_kill],0 // убийство с одного удара, логика аналогична с предыдущими тремя строкамиje originaljmp one_hit_killjmp returnherehealth:sub [edi+505],0jmp returnhereone_hit_kill:mov [edi+505],0jmpreturnhereoriginal:sub [edi+505],eaxjmp returnhereЕсли кого повеселил своим нубизмом - хорошо, но пожалуйста, пните в нужное русло, очень хочется понять как делается подобная опция...Добавлено:Все, понял как сделать. Нашел старенькую статью MasterGH, в которой описывается взлом на примере игры DMC.Всем спасибо Изменено 23 января, 2014 пользователем NullAlex Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 23 января, 2014 Поделиться Опубликовано 23 января, 2014 В той статье я не делал инъекцию в одну инструкцию, а делал в две. Одна работала только с игроком, а другая работала с игроком и ботами.--------Если делать инъекцию в одну инструкцию, то нужно выполнить множество сравнений. Вот логика в стиле C++/C#, которую можно переписать на ассемблерную инъекцию.if(isGodMode && !isOneHitKill){ if(pPlayer == myPlayer){ // своему игру записывать максимальное здоровье }else{ // чужому игроку отнимать очки здоровья как в оригинальном коде }}else if(!isGodMode && isOneHitKill){ if(pPlayer == myPlayer){ // своему игру отнимать очки здоровья как в оригинальном коде }else{ // чужого игрока убивать сразу }}else if(isGodMode && isOneHitKill){ if(pPlayer == myPlayer){ // своему игру записывать максимальное здоровье }else{ // чужого игрока убивать сразу }}else{// без разницы своему или чужому игру отнимать очки здоровья как в оригинальном коде}Возможно эту логику можно упростить. Где-то Xipho на АА-скриптах для CE показывал пример. Вот не помню где, да и искать лень. Поищи в сообщениях Xipho на форуме. Ссылка на комментарий Поделиться на другие сайты Поделиться
doc9009 Опубликовано 23 января, 2014 Поделиться Опубликовано 23 января, 2014 вот простенький пример решения твоей проблемы http://forum.gamehacklab.ru/topic/2223-%D0%BE%D1%82%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D0%BE%D0%BF%D1%86%D0%B8%D0%B9-%D1%82%D1%80%D0%B5%D0%B9%D0%BD%D0%B5%D1%80%D0%B0-%D0%BF%D1%80%D0%B8-%D0%BE%D0%B4%D0%BD%D0%BE%D0%B9-%D0%B8-%D1%82%D0%BE%D0%B9/ Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 23 января, 2014 Поделиться Опубликовано 23 января, 2014 MasterGH, да, я нашел вторую инструкцию, и сделал для нее убийство с одного удара, а для первой - бесконечное здоровье.doc9009, большущее спасибо за статью! Удалил кучу кода, даже вторая инструкция уже больше не нужна Ссылка на комментарий Поделиться на другие сайты Поделиться
Bromvol Опубликовано 23 января, 2014 Поделиться Опубликовано 23 января, 2014 MasterGH правильно написал логику создания для такого скрипта, но она на С++/С#. Я попробовал сделать этот чит для игры Darksiders:Wrath of War(она под рукой). Вот собственно скрипт с обьяснениями[ENABLE]alloc(newmem,1024)label(returnhere)label(original)label(exit)label(1HK)label(UH)label(UH1HK)label(UH1HKaction)label(1HKaction)label(1HKaction2)label(UHaction)label(UHaction2)label(e_1HK)label(e_UH)label(e_UH1HK)label(e_original)registersymbol(e_1HK) //регистрируем включение Убийства с одного удараregistersymbol(e_UH) //регистрируем включение Бесконечного здоровьяregistersymbol(e_UH1HK) //регистрируем включение Убийства с одного удара и Бесконечного здоровьяregistersymbol(e_original) //регистрируем включение оригинальной инструкцииnewmem:cmp [e_1HK],1 //Сравниваем Убийство с одного удара?je 1HK //Прыг на Убийство с одного удараcmp [e_UH],1 //Сравниваем Бесконечное здоровье?je UH //Прыг на Бесконечное здоровьеcmp [e_UH1HK],1 //Сравниваем убийство с одного удара и бесконечное здоровье?je UH1HK //Прыг на Убийство с одного удара и Бесконечное здоровьеcmp [e_original],1 //Сравниваем ничего не делатьje original //Прыг если ничего не делатьjmp original //Прыгаем, если ничего не делать на оригинальную инструкцию.1HK: //Убийство с одного удараcmp [ecx+0000000C],0 //Сравниваем наш ли герой?je original //Если наш, то выполнять оригинальную инструкциюjmp 1HKaction //А если нет, то прыг на выполнение убийства с одного удараUH: //Бесконечное здоровьеcmp [ecx+0000000C],0 //Сравниваем наш ли герой?je UHaction //Если наш, то прыг на выполнение Бесконечного здоровьяjmp original //Если не наш, то прыг на оригинальную инструкциюUH1HK: //Бесконечное здоровье и Убийство с одного удараcmp [ecx+0000000C],0 //Если наш герой?je UHaction2 //то прыг на выполнение Бесконечного здоровьяjmp 1HKaction2 //А если не наш, то прыг на выполнение Убийства с одного удара1HKaction: //Выплолнение Убийства с одного удараcmp [ecx+00000100],(float)1 //Сравниваем текущее значение здоровья противника, если равно или меньше 1,jle original //то прыг на оригинальную инструкцию,mov [ecx+00000100],(float)1 //а если нет, то присваеваем текущему значению здоровья 1jmp original //прыг на оригинальную инструкциюUHaction: //Выполнение Бесконечного здоровьяfild [ecx+000001dc] //Смотрим максимум здоровья для глав герояfstp [ecx+00000100] //Записиваем максимум здоровья в текущее значение здоровья глав герояjmp original //Прыг на оригинальную инструкциюUH1HKaction: //Выполнение Бесконечного здоровья и Убийства с одного удараcmp [ecx+0000000C],0 //Если наш герой?je UHaction2 //то прыг на выполнение Бесконечного здоровьяjmp 1HKaction2 //А если не наш, то прыг на выполнение Убийства с одного удараUHaction2: //Выполнение Бесконечного здоровьяfild [ecx+000001dc] //Смотрим максимум здоровья для глав герояfstp [ecx+00000100] //Записиваем максимум здоровья в текущее значение здоровья глав герояjmp original //Прыг на оригинальную инструкцию1HKaction2: //Выплолнение Убийства с одного удараcmp [ecx+00000100],(float)1 //Сравниваем текущее значение здоровья противника, если равно или меньше 1,jle original //то прыг на оригинальную инструкцию,mov [ecx+00000100],(float)1 //а если нет, то присваеваем текущему значению здоровья 1jmp original //прыг на оригинальную инструкциюoriginal: //оригинальная инструкцияcomiss xmm0,[ecx+00000100]jmp exitexit:jmp returnheree_1HK: //значение включения Убийства с одного удараdd 0 //присваеваем 0e_UH: //значение включения Бесконечного здоровьяdd 0 //присваеваем 0e_UH1HK: //значение включения Убийства с одного удара и Бесконечного здоровьяdd 0 //присваеваем 0e_original: //значение включения оригинальной инструкцииdd 0 //присваеваем 0006593C4:jmp newmemnopnopreturnhere:[DISABLE]006593C4:comiss xmm0,[ecx+00000100]unregistersymbol(e_1HK)unregistersymbol(e_UH)unregistersymbol(e_UH1HK)unregistersymbol(e_original)dealloc(newmem)А вот собственно сам скрипт для игры Darksiders: Wrath of War. Думаю скрипт можно немного сократить.Тут главное сделать правильное назначение горячих клавиш. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Tiger Опубликовано 23 января, 2014 Поделиться Опубликовано 23 января, 2014 По поводу проверочных байтов:1) внимательно на картинку под спойлером и исправь ***xx xx xx*** на числа, как показано в зеленых рамочках на картинке под спойлером ниже2) скинуть мне в личку ссылку на игру и подождать в ответ готовой таблицы с пояснением алгоритма.Изображение:Коротко про aobscanaobscan(переменная_aob, набор_сверяемых_байт)Данная инструкция ищет в оперативной памяти зарезервированной приложением (игрой) совпадения с цепочкой указанных байт, данных цепочек может быть несколько, но как правило в оборот идет первая совпавшая; отсюда, чем длинее цепочка тем лучше, до разумных пределовДалее выполняяregistersymbol(переменная_aob)мы получаем глобальную метку в коде, что очень важно, когда выделение памяти приложением трактуется, как динамическое. В данном случае при каждом перезапуске мы получаем новые адреса для старых инструкций ["Game.exe"+654065] -> ["Game.exe"+484650] и даже после выхода обновлений на игру скрипт останется работоспособным в последующих версиях, если патч не затрагивал данную инструкцию, что тоже очень важно. в противном случае скрипт просто не будет работать / активироваться.и в секции DISABLE мы отменяем резервацию "глобальной метки"unregistersymbol(переменная_aob)Обратив внимание на черные рамочки вы заметите, что переводя скрипт с локации по статическому адресу (справа) на локацию по метке (слева) ["xrGame.dll"+21F196]->[ammo_aob] мы практически добавляем всего несколько сток и заменяем адрес на метку:Используем call - ret связку в замену переходов из кода на сраницу инжекта и затем обратно+: убираем лишние метки, сокращаем код-: не заметилПример:aobscan(переменная_aob, набор_сверяемых_байт)registersymbol(переменная_aob)newmem:******retадрес: -> переменная_aob:call newmemnop[DISABLE]адрес: -> переменная_aob:******unregistersymbol(переменная_aob)[ENABLE]Как вы уже поняли цепочку можно продолжать бесконечно, но если случается так, что после инструкции нет возможности дописать. Можно начать цепочку в любом месте программного кода выше или ниже, но тогда мы соответственно должны добавить или отнять от нашей метки число байт стоящих между началом требуемого места инжекта (исходной инструкцией) и началом цепочки проверочных байт например:Пример:aobscan(переменная_aob, XX XX XX XX набор_сверяемых_байт)registersymbol(переменная_aob)newmem:******retпеременная_aob+4:call newmemnop[DISABLE]переменная_aob+4:******unregistersymbol(переменная_aob)[ENABLE]PSCтарайся сохранять флаги процессора, которые ты изменяешь командой cmp x,y и другими махинациями... "залез - верни, как было". puchf- сохранил / popf-восстановилxor eax,eax - кроме коррекции флагов еще и обнуляет eax и длина инструкции всего два байта, для теста на "0" используйtest eax,eaxона только флаги меняет eax останется с исходным значением.Алгоритм понят абсолютно верно, за исключением того , что я изменял только входные данные, не трогая инструкцию, но все что работает имеет право на существование).Со временем научишься сокращать вырезая "бесполезняк" и лишние лейблы с джампами, которые ты сделал, чтобы пошагово понять логику. Смысл в том, что после инжекта (настоятельно рекомендую использовать вызов функции и аборт, нежели прижок туда и обратно.) весь твой код между newmem: и строчкой call newmem / jmp newmem распологается на выделенной странце, по строкам которой можно лазать вверх и вниз, исспользуя ее собственные адреса newmem+4 / newmem+2с и т.д. создавать метки, выделять место под хранение данных (как и адреса в основном коде программы). 2 Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 24 января, 2014 Поделиться Опубликовано 24 января, 2014 Tiger, спасибо большое за объяснение, уже более понятно стало, что делает аобскан, и как примерно с ним работать. Только осталось еще несколько вопросов, например, почему в отладчике берем ниже 2 строки? А не 3 и не 5? Или это не имеет значения, т.е. этими байтами мы будем искать нужные данные в памяти, и можно было взять как 2 строки байт, так и 10 (для верности)?Данная инструкция ищет в оперативной памяти зарезервированной приложением (игрой) совпадения с цепочкой указанных байт, данных цепочек может быть несколько, но как правило в оборот идет первая совпавшая; отсюда, чем длинее цепочка тем лучше, до разумных пределов Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 24 января, 2014 Поделиться Опубликовано 24 января, 2014 Мне кажется вот наиболее простой вариант. Во время игры делать инъекции двумя независимыми скриптами1. Бессмертие (как было так и остается в АА скриптах). Можно включать и выключать.2. "Убийство с одного удара" может записывать очень сильный урон врагам (в адрес урона) на инструкции где-то повыше инструкции инъекции бессмертия. Можно включать и выключать.Тогда получаем привычное [enable] и [disable] поведения для АА скриптов без гемора со сравнениями. Ссылка на комментарий Поделиться на другие сайты Поделиться
ArxLex Опубликовано 24 января, 2014 Поделиться Опубликовано 24 января, 2014 Может примерно как то так? Написал по памяти, могут быть ошибки...[ENABLE]alloc(_MemHack, 128)label(_Back)label(_Exit)label(_Health)label(_InstantKill)registersymbol(iToggleHealth)registersymbol(iToggleInstantKill)_MemHack:cmp [iToggleHealth],1je _Healthjmp _InstantKill_Health:cmp [edi+13],#200jne _InstantKillmov [edi+505],#99999jmp _InstantKill_InstantKill:cmp [iToggleInstantKill],1jne _Exitmov [edi+505],0jmp _Exit_Exit:sub [edi+505],eaxjmp _BackiToggleHealth:dd 00iToggleInstantKill:dd 00..[DISABLE]..unregistersymbol(iToggleHealth)unregistersymbol(iToggleInstantKill) Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 24 января, 2014 Поделиться Опубликовано 24 января, 2014 MasterGH, по-моему единственный гемор - активация "глав-скрипта", а потом активация нужных опций. Т.к. сравнивать в АА скриптах практически нечего (если не считать сравнение ID (читай - отличить игрока от бота) и статус активации), если использовать шаблон doc9009, то там получается конструкция типа:if (GodMode == 0) { // выполняем оригинальный код} else { // выполняем опцию бессмертия}if (OneHitKill == 0) { // выполняем оригинальный код} else { // выполняем опцию убийства с одного удара}Плюсы: одна инструкция, два действияМинусы: надо добавить дополнительные 2 адреса/АА скрипта в главном окне CE - метки, а также включать "глав-скрипт", и после него - нужные опции.Минус реализации (написание трейнера (на любом языке программирования, а не инструментом CE "генерация трейнера")) в том, что если программист хочет избавить юзера от лишнего гемора с хоткеями, ему (программисту) придется сравнивать, включена ли какая-то опция, которая работает с "глав-скриптом", если да - включать "глав-скрипт", если нет - выключать его. Хотя по поводу генерации трейнера в СЕ - не знаю, возможно там тоже можно как-то повлиять на это.По поводу нахождения второй инструкции, которая работает со здоровьем (игрока или противника или всех вместе взятых), то не всегда удается найти вторую инструкцию (хотя может это только мой баг рук). По-моему, в FarCry 3 всего одна инструкция, которая работает со здоровьем как игрока, так и ботов.Я не профи во взломе и программировании, я просто изложил свои мысли по этому поводу, опираясь на свои знания и замечания в различных ситуациях, не судите строго. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 24 января, 2014 Поделиться Опубликовано 24 января, 2014 >> MasterGH, по-моему единственный гемор - активация "глав-скрипта", а потом активация нужных опций.Все варианты которые я видел ранее до сегодняшнего дня имели "главный скрипт" (я его называл еще активирующим), который действительно приходилось активировать хотя бы один раз в начале игры. Его содержимое как и в примерах этой темы состояло из кучи прыгов, сравнений. Затем приходилось писать еще два скрипта, которые связывались с хоткеями. Они ставили бессмертие или убийство с одного раза в некоторый адрес, который использовал "главный скрипт". Пользователю приходилось сообщать, чтобы он нажал в трейнере комбинацию хоткеев в начале игры чтобы активировать главный скрипт один раз...------Так вот. Я предложил постом выше совершенно другой вариант без главного (активирующего) скрипта.Нужно два скрипта и выбрать два адреса рядом друг с другом для двух инъекций.1. Скрипт, инъекция которого значительно увеличивает урон только врагам. При повтором срабатывании возвращает как было.2. Скрипт, инъекция которого делает только своего героя бессмертным. При повтором срабатывании возвращает как было.Активирующего скрипта уже не нужно.Если брать за пример в пером посте, то:1) первый скрипт в eax врага должен записать его здоровье - это же будет максимальный урон для него.2) второй скрипт должен пропустить sub [edi+505],eax для героя за которогоиграем.Инъекции кода по идее должны быть на расстоянии не ближе 6 байт друг от друга, одна над другой. Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 24 января, 2014 Поделиться Опубликовано 24 января, 2014 У меня получается сделать 2 независимых скрипта только оперируя разными инструкциями. То есть, для бесконечного здоровья использовать одну инструкцию, а для убийства с одного удара - другую. Если я правильно понял фразу не ближе 6 байт друг от друга.Иначе я просто не понимаю как сделать, т.к. как что-то мне подсказывает, если в двух скриптах использовать одну инструкцию - опции будут друг друга "перекрывать", и насколько я знаю, альтернативное действие должно быть, иначе будет выполняться предыдущее действие.Например, если сделать так:newmem:cmp [edx+666],#1sub [edx+667],0jmp returnhereТо для игрока и для противника будет выполняться sub [edx+667],0. Или я не прав? Ссылка на комментарий Поделиться на другие сайты Поделиться
Bromvol Опубликовано 24 января, 2014 Поделиться Опубликовано 24 января, 2014 (изменено) Такое впечатление что мой скрипт никто толком и не глядел Я сделал скрипт который отвечает на множество уже поставленых вопросов. Странно что эти вопросы возникли. Ты бы указал которую игру ломаешь и дал ссылку на нее в личку, а то много вопросов, а дел нет, лишь одна теория!Я сократил скрипт и сделал немного другую логику выполнения кода, тоже с коментариями и тоже для игры Darksiders: Wrath of War NullAlex почитай внимательно и вникни в суть самого скрипта.У меня 1 скрипт делает две разных опции НЕЗАВИСИМО друг от друга так как ты этого и хотел.Вот собственно скрипт:[ENABLE]alloc(newmem,1024)label(returnhere)label(original)label(exit)label(1HK)label(UH)label(UH1HK)label(1HKaction)label(UHaction)label(en_1HK) //Метка включения Убийства с одного удараlabel(en_UH) //Метка включения Бесконечного здоровьяregistersymbol(en_1HK) //Регистрация переменной Убийства с одного удараregistersymbol(en_UH) //Регистрация переменной Бесконечного здоровьяnewmem:cmp [en_1HK],1 //Включено ли Убийство с одного удараje 1HK //Если да, то прыг на Убийство с одного удараcmp [en_UH],1 //Включено ли Бесконечное здоровьеje UH //Если да, то прыг на Бесконечное здоровьеjmp original //Если ничего не включено, то выполнять оригинальную инструкциюUH: //Бесконечное здоровьеcmp [en_1HK],1 //Проверяем включено ли Убийство с одного удараje UH1HK //Если да, то прыг на Убийство с одного удара и Бесконечное здоровьеcmp [ecx+0000000C],0 //Проверяем наш ли геройjne original //Если нет, то прыг на оригинальную инструкциюfild [ecx+000001dc] //А если нет, то читаем максимум здоровья глав герояfstp [ecx+00000100] //Пишем максимум здоровья в текущее значение здоровьяjmp original //Прыг на оригинальную инструкцию1HK: //Убийство с одного удараcmp [en_UH],1 //Проверяем включено ли Бесконечное здоровьеje UH1HK //Если да, то прыг на Убийство с одного удара и Бесконечное здоровьеcmp [ecx+0000000C],0 //Проверяем наш ли геройje original //Если да, то прыг на оригинальную инструкциюcmp [ecx+00000100],(float)1 //Проверяем текущее значение здоровья противникаjle original //Если равно или меньше 1, то прыг на оригинальную инструкциюmov [ecx+00000100],(float)1 //А если больше, то пишем в текущее значение 1 НРjmp original //Прыг на оригинальную инструкциюUH1HK: //Бесконечное здоровье и Убийство с одного удараcmp [ecx+0000000C],0 //Проверяем наш ли геройje UHaction //Если наш, то прыг на выполнение Бесконечного здоровьяjmp 1HKaction //А если нет, то прыг на выполнение Убийства с одного удараUHaction: //Выполнение Бесконечного здоровьяfild [ecx+000001dc]fstp [ecx+00000100]jmp original1HKaction: //Выполнение Убийства с одного удараcmp [ecx+00000100],(float)1jle originalmov [ecx+00000100],(float)1jmp originaloriginal: //Оригинальная инструкцияcomiss xmm0,[ecx+00000100]jmp exitexit:jmp returnhereen_1HK:dd 0en_UH:dd 0"DarksidersPC.exe"+2593C4:jmp newmemnopnopreturnhere:[DISABLE]"DarksidersPC.exe"+2593C4:comiss xmm0,[ecx+00000100]unregistersymbol(en_1HK)unregistersymbol(en_UH)dealloc(newmem)Это активирующий скрипт. Для него нужны еще 2 дополнительных скрипта.Вот 1 скрипт:[ENABLE]en_1HK:dd 1[DISABLE]en_1HK:dd 0Вот 2 скрипт:[ENABLE]en_UH:dd 1[DISABLE]en_UH:dd 0"Горячие" клавишы я назначил Num /(Вкл/Выкл Убийство с одного удара) и Num *(Вкл/Выкл Бесконечное здоровье).И собственно готовая таблица под эти опции для игры Darksiders: Wrath of War. Скачай себе игру (около 7 гиг) и посмотри что да как сам. А не нравиться тебе, то название игры, которую ломаешь в студию Может кто уже ломал и может больше сказать и показать.Тебе и так многое показали и рассказали. А как реализовывать на языках программирования это уже другая тема и зависит от твоих знаний, умений и фантазии DarksidersPC GHLRU.ct Изменено 24 января, 2014 пользователем Xipho Ники тех, к кому обращаешься, выделяй жирным шрифтом, чтобы они сразу это видели. Спасибо. )) ЗЫ. Плюс за помощь новичку и объяснения, и медалька за активность )) 2 Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 24 января, 2014 Поделиться Опубликовано 24 января, 2014 Bromvol, как-бы, вопрос с активирующим скриптом давно решен, я уже говорил в этой тебе об этом. Активирующий скрипт сделал по шаблону doc9009. Спасибо все-равно, и поздравляю с медалью и +1 к репе Ссылка на комментарий Поделиться на другие сайты Поделиться
Tiger Опубликовано 25 января, 2014 Поделиться Опубликовано 25 января, 2014 Tiger, спасибо большое за объяснение, уже более понятно стало, что делает аобскан, и как примерно с ним работать. Только осталось еще несколько вопросов, например, почему в отладчике берем ниже 2 строки? А не 3 и не 5? Или это не имеет значения, т.е. этими байтами мы будем искать нужные данные в памяти, и можно было взять как 2 строки байт, так и 10 (для верности)?Тут единственная задача выверить необходимое и достаточное количество байт, При котором будет происходить верное определение местоположения метки инжекта.Bromvol, как-бы, вопрос с активирующим скриптом давно решен, я уже говорил в этой тебе об этом. Активирующий скрипт сделал по шаблону doc9009. Спасибо все-равно, и поздравляю с медалью и +1 к репе Присоединяюсь к поздравлениям!Мне кажется отвечающий всем вашим запросам готовый работающий и самый короткий из представленных, за исключением байтов aobscan, давно уже выложен, посте этак в 3м. За неимением возможности протестировать, хотелось бы вас попросить допонить проверочные байты, провести тест и сообщить о результатахКак и обещал логика и построчное описание[ENABLE]aobscan(address_aob,29 87 05 05 00 00 XX XX XX XX XX XX XX XX XX XX) // функция поиска и установки метки (неполная строка проверочных байт)alloc(newmem, 2048) // выделяем страницу памяти, устатнавливаем меткуlabel(exit1) // метка для перехода1label(exit2) // метка для перехода2registersymbol(address_aob) // регистрируем глобальные метки и переменныеlabel(En_health) // метка для глобальной переменнойlabel(En_one_hit_kill) //метка для глобальной переменнойregistersymbol(En_health) // регистрируем глобальные метки и переменныеregistersymbol(En_one_hit_kill) // регистрируем глобальные метки и переменныеnewmem: // метка начала записи кода на выделенную страницуpushf // сохраняем регистр флагов процессораcmp [edi+13],#200 // выполняем проверку по IDjne exit1 // если нет (не наш герой), тогда идем к проверке активации "1 hit kill"cmp [En_health],00 // проверка активации "God mode"je exit2 // если не активна идем к оригинальной инструкцииxor eax,eax // обнуляем eax (mov eax,0)mov [edi+505],#100 // заполняем шкалу здоровья герояjmp exit2 // безусловный переход на оригинальную инструкциюexit1: // метка для перехода1cmp [En_one_hit_kill],00 // проверка активации "1 hit kill"je exit2 // если не активна идем к оригинальной инструкцииmov eax,[edi+505] // приравниваем получаемый урон к остатку жизнейexit2: // метка для перехода2popf // восстанавливаем регистр флагов процессораsub [edi+505],eax // выполняется оригинальная инструкцииret // возврат на точку вызова процедурыEn_health: // объявление глобальной переменной в области памяти (newmem)db 00 00 00 00 // заполнение байт значения нулями (значение переменной по адресу "En_health" будет равно "0")En_one_hit_kill: // объявление глобальной переменной в области памяти (newmem)db 00 00 00 00 // заполнение байт значения нулями (значение переменной по адресу "En_one_hit_kill" будет равно"0")address_aob: // метка начала записи в код приложенияcall newmem // вызов процедуры по метке (со страницы / с адреса ) newmemdb 90 // nop - компенсационные байты призванные уравновесить замену оригинальной инструкции кодом вызова процедуры[DISABLE]address_aob: // метка начала записи в код приложенияdb 29 87 05 05 00 00 XX XX XX XX XX XX XX XX XX XX // восстановление исходного кода приложения посредством записи байтunregistersymbol(address_aob) // арегистрация глобальных меток и переменныхunregistersymbol(En_health) // арегистрация глобальных меток и переменныхunregistersymbol(En_one_hit_kill) // арегистрация глобальных меток и переменныхdealloc(newmem) // высвобождаем страницу памяти, удаляем метку. Можно добавить адреса и вручную править их значения или же написать скрипт производящий перезапись по меткам (невозможно активироваать при отсутствии меток,)En_health: // метка начала записиdb 01 // запись байт (значение переменной по адресу "En_health" будет равно "1")[DISABLE]En_health: // метка начала записиdb 00 // запись байт (значение переменной по адресу "En_health" будет равно "0")[ENABLE] и аналогичный для второго адреса. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения