Перейти к содержанию

Разбить скрипт на 2 опции


Рекомендуемые сообщения

Всем привет.

Интересует такой вопрос - как сделать из опции "Бесконечное здоровье" - "Убийство с одного удара"?

Допустим, я разобрал структуру, узнал как отличить игрока от противника. Но не получается сделать 2 независимые друг от друга опции. То есть, если я не хочу использовать бесконечное здоровье, а только убийство с одного удара, или наоборот. Как быть в этом случае?

Бесконечное здоровье


newmem:
cmp [edi+13],#200
je health
sub [edi+505],eax
jmp returnhere

health:
sub [edi+505],0
jmp returnhere

Убийство с одного удара:


newmem:
cmp [edi+13],#200
je one_hit_kill
mov [edi+505],0
jmp returnhere

one_hit_kill:
sub [edi+505],0
jmp returnhere

Ссылка на комментарий
Поделиться на другие сайты

Сделай еще одну проверку с коде:

label(pHealth)
registersymbol(pHealth)

newmem:
cmp [pHealth],0
je +(через сколько прыгаем)
cmp [edi+13],#200
je health
sub [edi+505],eax
jmp returnhere
health:
sub [edi+505],0
jmp returnhere

pHealth:
dd 0

[DISABLE]
unregistersymbol(pHealth)

По хоткею меняешь в СЕ метку pHealth (1 или 0)

Ссылка на комментарий
Поделиться на другие сайты

Так ведь таким образом мы просто привяжем часть скрипта к хоткею (если я правильно понял). Но мне надо разделить сами опции, т.е. чтобы при включении убийства с одного удара - не срабатывала бы опция "бесконечное здоровье", и наоборот - чтобы опция "бесконечное здоровье" не сбрасывала опцию убийства с одного удара, т.е. чтобы они друг друга не перезаписывали, и работали как вместе, так и отдельно друг от друга.

Ссылка на комментарий
Поделиться на другие сайты

я вижу тут две разные инструкции в первом скрипте

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:
pushf
cmp [edi+13],#200
jne exit1
cmp [En_health],00
je exit2
xor eax,eax
// mov [edi+505],#200 // можно заодно заполнить шкалу здоровья героя, как понимаю 200 HP это и есть максимум
jmp exit2
exit1:
cmp [En_one_hit_kill],00
je exit2
mov eax,[edi+505]
exit2:
popf
sub [edi+505],eax
ret

En_health:
db 00 00 00 00

En_one_hit_kill:
db 00 00 00 00

address_aob:
call newmem
db 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 опция. "скрывать вложения если неативна..." и хоткеи активации трейнера на родителя, опциональные на соответственно вторые два скрипта.

Ссылка на комментарий
Поделиться на другие сайты

Нет, 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 returnhere

Tiger, твой пример я не понял, если честно, т.к. не знаком с аобсканом, и не знаю большинство ассемблерных инструкций. Но разобраться в нем попробовал все-таки.


[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],eax
ret // не знаю для чего

En_health:
db 00 00 00 00 // что это делает?

En_one_hit_kill:
db 00 00 00 00 // тот же вопрос

address_aob:
call newmem
db 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 original
jmp one_hit_kill
jmp returnhere

health:
sub [edi+505],0
jmp returnhere

one_hit_kill:
mov [edi+505],0
jmpreturnhere

original:
sub [edi+505],eax
jmp returnhere

Если кого повеселил своим нубизмом - хорошо, но пожалуйста, пните в нужное русло, очень хочется понять как делается подобная опция...

Добавлено:

Все, понял как сделать. Нашел старенькую статью MasterGH, в которой описывается взлом на примере игры DMC.

Всем спасибо :)

Изменено пользователем NullAlex
Ссылка на комментарий
Поделиться на другие сайты

В той статье я не делал инъекцию в одну инструкцию, а делал в две. Одна работала только с игроком, а другая работала с игроком и ботами.

--------

Если делать инъекцию в одну инструкцию, то нужно выполнить множество сравнений. Вот логика в стиле 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 на форуме.

Ссылка на комментарий
Поделиться на другие сайты

MasterGH, да, я нашел вторую инструкцию, и сделал для нее убийство с одного удара, а для первой - бесконечное здоровье.

doc9009, большущее спасибо за статью! Удалил кучу кода, даже вторая инструкция уже больше не нужна :)

Ссылка на комментарий
Поделиться на другие сайты

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 //а если нет, то присваеваем текущему значению здоровья 1
jmp 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 //а если нет, то присваеваем текущему значению здоровья 1
jmp original //прыг на оригинальную инструкцию

original: //оригинальная инструкция
comiss xmm0,[ecx+00000100]
jmp exit

exit:
jmp returnhere

e_1HK: //значение включения Убийства с одного удара
dd 0 //присваеваем 0

e_UH: //значение включения Бесконечного здоровья
dd 0 //присваеваем 0

e_UH1HK: //значение включения Убийства с одного удара и Бесконечного здоровья
dd 0 //присваеваем 0

e_original: //значение включения оригинальной инструкции
dd 0 //присваеваем 0

006593C4:
jmp newmem
nop
nop
returnhere:
[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
Ссылка на комментарий
Поделиться на другие сайты

По поводу проверочных байтов:

1) внимательно на картинку под спойлером и исправь ***xx xx xx*** на числа, как показано в зеленых рамочках на картинке под спойлером ниже

2) скинуть мне в личку ссылку на игру и подождать в ответ готовой таблицы с пояснением алгоритма.

Изображение:

image.jpg

post-3-0-65234800-1390535090_thumb.jpg


Коротко про aobscan
aobscan(переменная_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 newmem
nop

[DISABLE]
адрес: -> переменная_aob:
***
***
unregistersymbol(переменная_aob)
[ENABLE]

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

Пример:


aobscan(переменная_aob, XX XX XX XX набор_сверяемых_байт)
registersymbol(переменная_aob)
newmem:
***
***
ret
переменная_aob+4:
call newmem
nop
[DISABLE]
переменная_aob+4:
***
***
unregistersymbol(переменная_aob)
[ENABLE]


PS

Cтарайся сохранять флаги процессора, которые ты изменяешь командой cmp x,y и другими махинациями... "залез - верни, как было". puchf- сохранил / popf-восстановил

xor eax,eax 

- кроме коррекции флагов еще и обнуляет eax и длина инструкции всего два байта, для теста на "0" используй

test eax,eax

она только флаги меняет eax останется с исходным значением.

Алгоритм понят абсолютно верно, за исключением того , что я изменял только входные данные, не трогая инструкцию, но все что работает имеет право на существование).

Со временем научишься сокращать вырезая "бесполезняк" и лишние лейблы с джампами, которые ты сделал, чтобы пошагово понять логику. Смысл в том, что после инжекта (настоятельно рекомендую использовать вызов функции и аборт, нежели прижок туда и обратно.) весь твой код между newmem: и строчкой call newmem / jmp newmem распологается на выделенной странце, по строкам которой можно лазать вверх и вниз, исспользуя ее собственные адреса newmem+4 / newmem+2с и т.д. создавать метки, выделять место под хранение данных (как и адреса в основном коде программы).

  • Плюс 2
Ссылка на комментарий
Поделиться на другие сайты

Tiger, спасибо большое за объяснение, уже более понятно стало, что делает аобскан, и как примерно с ним работать. Только осталось еще несколько вопросов, например, почему в отладчике берем ниже 2 строки? А не 3 и не 5? Или это не имеет значения, т.е. этими байтами мы будем искать нужные данные в памяти, и можно было взять как 2 строки байт, так и 10 (для верности)?

Данная инструкция ищет в оперативной памяти зарезервированной приложением (игрой) совпадения с цепочкой указанных байт, данных цепочек может быть несколько, но как правило в оборот идет первая совпавшая; отсюда, чем длинее цепочка тем лучше, до разумных пределов
Ссылка на комментарий
Поделиться на другие сайты

Мне кажется вот наиболее простой вариант. Во время игры делать инъекции двумя независимыми скриптами

1. Бессмертие (как было так и остается в АА скриптах). Можно включать и выключать.

2. "Убийство с одного удара" может записывать очень сильный урон врагам (в адрес урона) на инструкции где-то повыше инструкции инъекции бессмертия. Можно включать и выключать.

Тогда получаем привычное [enable] и [disable] поведения для АА скриптов без гемора со сравнениями.

Ссылка на комментарий
Поделиться на другие сайты

Может примерно как то так? Написал по памяти, могут быть ошибки...


[ENABLE]
alloc(_MemHack, 128)
label(_Back)
label(_Exit)
label(_Health)
label(_InstantKill)
registersymbol(iToggleHealth)
registersymbol(iToggleInstantKill)
_MemHack:
cmp [iToggleHealth],1
je _Health
jmp _InstantKill
_Health:
cmp [edi+13],#200
jne _InstantKill
mov [edi+505],#99999
jmp _InstantKill
_InstantKill:
cmp [iToggleInstantKill],1
jne _Exit
mov [edi+505],0
jmp _Exit
_Exit:
sub [edi+505],eax
jmp _Back
iToggleHealth:
dd 00
iToggleInstantKill:
dd 00
..
[DISABLE]
..
unregistersymbol(iToggleHealth)
unregistersymbol(iToggleInstantKill)

Ссылка на комментарий
Поделиться на другие сайты

MasterGH, по-моему единственный гемор - активация "глав-скрипта", а потом активация нужных опций. Т.к. сравнивать в АА скриптах практически нечего (если не считать сравнение ID (читай - отличить игрока от бота) и статус активации), если использовать шаблон doc9009, то там получается конструкция типа:


if (GodMode == 0) {
// выполняем оригинальный код
} else {
// выполняем опцию бессмертия
}

if (OneHitKill == 0) {
// выполняем оригинальный код
} else {
// выполняем опцию убийства с одного удара
}

Плюсы: одна инструкция, два действия

Минусы: надо добавить дополнительные 2 адреса/АА скрипта в главном окне CE - метки, а также включать "глав-скрипт", и после него - нужные опции.

Минус реализации (написание трейнера (на любом языке программирования, а не инструментом CE "генерация трейнера")) в том, что если программист хочет избавить юзера от лишнего гемора с хоткеями, ему (программисту) придется сравнивать, включена ли какая-то опция, которая работает с "глав-скриптом", если да - включать "глав-скрипт", если нет - выключать его. Хотя по поводу генерации трейнера в СЕ - не знаю, возможно там тоже можно как-то повлиять на это.

По поводу нахождения второй инструкции, которая работает со здоровьем (игрока или противника или всех вместе взятых), то не всегда удается найти вторую инструкцию (хотя может это только мой баг рук). По-моему, в FarCry 3 всего одна инструкция, которая работает со здоровьем как игрока, так и ботов.

Я не профи во взломе и программировании, я просто изложил свои мысли по этому поводу, опираясь на свои знания и замечания в различных ситуациях, не судите строго.

Ссылка на комментарий
Поделиться на другие сайты

>> MasterGH, по-моему единственный гемор - активация "глав-скрипта", а потом активация нужных опций.

Все варианты которые я видел ранее до сегодняшнего дня имели "главный скрипт" (я его называл еще активирующим), который действительно приходилось активировать хотя бы один раз в начале игры. Его содержимое как и в примерах этой темы состояло из кучи прыгов, сравнений. Затем приходилось писать еще два скрипта, которые связывались с хоткеями. Они ставили бессмертие или убийство с одного раза в некоторый адрес, который использовал "главный скрипт". Пользователю приходилось сообщать, чтобы он нажал в трейнере комбинацию хоткеев в начале игры чтобы активировать главный скрипт один раз...

------

Так вот. Я предложил постом выше совершенно другой вариант без главного (активирующего) скрипта.

Нужно два скрипта и выбрать два адреса рядом друг с другом для двух инъекций.

1. Скрипт, инъекция которого значительно увеличивает урон только врагам. При повтором срабатывании возвращает как было.

2. Скрипт, инъекция которого делает только своего героя бессмертным. При повтором срабатывании возвращает как было.

Активирующего скрипта уже не нужно.

Если брать за пример в пером посте, то:

1) первый скрипт в eax врага должен записать его здоровье - это же будет максимальный урон для него.

2) второй скрипт должен пропустить sub [edi+505],eax для героя за которогоиграем.

Инъекции кода по идее должны быть на расстоянии не ближе 6 байт друг от друга, одна над другой.

Ссылка на комментарий
Поделиться на другие сайты

У меня получается сделать 2 независимых скрипта только оперируя разными инструкциями. То есть, для бесконечного здоровья использовать одну инструкцию, а для убийства с одного удара - другую. Если я правильно понял фразу

не ближе 6 байт друг от друга
.

Иначе я просто не понимаю как сделать, т.к. как что-то мне подсказывает, если в двух скриптах использовать одну инструкцию - опции будут друг друга "перекрывать", и насколько я знаю, альтернативное действие должно быть, иначе будет выполняться предыдущее действие.

Например, если сделать так:


newmem:
cmp [edx+666],#1
sub [edx+667],0
jmp returnhere

То для игрока и для противника будет выполняться sub [edx+667],0. Или я не прав?

Ссылка на комментарий
Поделиться на другие сайты

Такое впечатление что мой скрипт никто толком и не глядел :mad: Я сделал скрипт который отвечает на множество уже поставленых вопросов. Странно что эти вопросы возникли. Ты бы указал которую игру ломаешь и дал ссылку на нее в личку, а то много вопросов, а дел нет, лишь одна теория!

Я сократил скрипт и сделал немного другую логику выполнения кода, тоже с коментариями и тоже для игры Darksiders: Wrath of War :-DNullAlex почитай внимательно и вникни в суть самого скрипта.

У меня 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 original

1HKaction: //Выполнение Убийства с одного удара
cmp [ecx+00000100],(float)1
jle original
mov [ecx+00000100],(float)1
jmp original

original: //Оригинальная инструкция
comiss xmm0,[ecx+00000100]
jmp exit

exit:
jmp returnhere

en_1HK:
dd 0

en_UH:
dd 0

"DarksidersPC.exe"+2593C4:
jmp newmem
nop
nop
returnhere:

[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 гиг) и посмотри что да как сам. А не нравиться тебе, то название игры, которую ломаешь в студию :-D Может кто уже ломал и может больше сказать и показать.

Тебе и так многое показали и рассказали. А как реализовывать на языках программирования это уже другая тема и зависит от твоих знаний, умений и фантазии ;)

DarksidersPC GHLRU.ct

Изменено пользователем Xipho
Ники тех, к кому обращаешься, выделяй жирным шрифтом, чтобы они сразу это видели. Спасибо. )) ЗЫ. Плюс за помощь новичку и объяснения, и медалька за активность ))
  • Плюс 2
Ссылка на комментарий
Поделиться на другие сайты

Bromvol, как-бы, вопрос с активирующим скриптом давно решен, я уже говорил в этой тебе об этом. Активирующий скрипт сделал по шаблону doc9009. Спасибо все-равно, и поздравляю с медалью и +1 к репе :)

Ссылка на комментарий
Поделиться на другие сайты

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) // метка для перехода1
label(exit2) // метка для перехода2
registersymbol(address_aob) // регистрируем глобальные метки и переменные

label(En_health) // метка для глобальной переменной
label(En_one_hit_kill) //метка для глобальной переменной
registersymbol(En_health) // регистрируем глобальные метки и переменные
registersymbol(En_one_hit_kill) // регистрируем глобальные метки и переменные

newmem: // метка начала записи кода на выделенную страницу
pushf // сохраняем регистр флагов процессора

cmp [edi+13],#200 // выполняем проверку по ID
jne 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: // метка для перехода1
cmp [En_one_hit_kill],00 // проверка активации "1 hit kill"
je exit2 // если не активна идем к оригинальной инструкции
mov eax,[edi+505] // приравниваем получаемый урон к остатку жизней

exit2: // метка для перехода2
popf // восстанавливаем регистр флагов процессора
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 // вызов процедуры по метке (со страницы / с адреса ) newmem
db 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
Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.