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

Commandos: Behind Enemy Lines (как найти причину вылета?)


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

В общем тема эта неоднократно поднималась на форуме - написали скрипт, включили, игра зависла :( Что делать? Отлаживать. Обычно бряк в начале инЪекции показывает прчиину ошибки - изменили регистр, но забыли его вытолкнуть из стека в конце использования, фильтр "свой\чужой" работает некорректно, да мало ли..

Но вот вопрос - а как отлаживать "плавающий крах" игры? т.е. такой, который приводит к вылету только при тысячном прохождении бряка, а может вообще не выкинуть, и визуально в игре алгоритм действий приводящий к краху игры неочевиден? Я тут вчера помучился, исправил некоторые ошибки в скрипте, но всё равно игра нет-нет да вылетит. Может кто поможет каким советом? Игра см. название темы. Скрипт, убирающий врагов с карты (пишущий запредельную величину координаты X):


[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048) //2kb should be enough
label(returnhere)
label(originalcode)
label(exit)
label(NoEnemies)
label(restrore_regs)

newmem:

push ebx
cmp dword ptr [eax+13C],1 //into a car? туточки было подозрение что вылет связан с двигающейся по карте машиной, но фильтр "кто-то сидит в машине" не помог
je restrore_regs

cmp [eax+1с],0 //фильтр свой\чужой\машина без водителя (у своих и пустых машин нолик, у врагов некое число)
je restrore_regs
jmp NoEnemies

restrore_regs:
pop ebx //со своими и машинами ничего не делаем (регистр ebx не использовался никак, вырезал лишний код)
jmp originalcode

NoEnemies:
pop ebx
mov ecx,(float)99999 //отправляем врагов в ссылку на Север (нет, это X, значит на Восток)

originalcode:
mov [eax+08],ecx
mov edx,[esi+2C]



exit:
jmp returnhere



"comandos.exe"+35A2D:
jmp newmem
nop
returnhere:




[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)

"comandos.exe"+35A2D:
mov [eax+08],ecx
mov edx,[esi+2C]
//Alt: db 89 48 08 8B 56 2C

Что делал сам? Убирал весь чит, кроме mov ecx,(float)99999 - вылет похоже именно из-за этой строки. Уменьшал 99999 вплоть до нуля - вылет. В конце концов вообще отказался от скрипта, внёс в таблицу все адреса, выскакивающие на инструкции "comandos.exe"+35A2D, и заморозил таймером (без скрипта), координаты оставил какие были - и всё равно вылет! т.е. дело не в инЪекции, а в самом факте заморозки. Что тут можно сделать, что и как ещё проверить?

Возьмем в качестве примера 4 миссию. В самом начале миссии включаю скрипт - вылет. Включаю его в той же миссии, но не сразу - нет вылета! Что такого в этой миссии? Поезд ездит по рельсам по кругу не переставая, грузовичок выезжает. Пробовал морозить этот поезд с грузовиком на старте, ничего не вылетает. Морожу ВСЁ - вылет. Морожу всё спустя пару секунд после старта - нет вылета. Всю голову сломал, логики не вижу...

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

1) Сначала для спокойствия возможно стоит убедится нет ли проблемы с записью в память по другим адресам - может быть у игры стоит защита от изменения данных и нужно её изучать...

2) Попробуй найти пример работы со спрайтами на C++, скомпилируй его посмотри какие трудности в изменении координат спрайтов и какие ошибки могут возникать при этом.

Ориентируйся на рисование спрайта по этому примеру кода:


D3DXVECTOR3 pos;
pos.x=10.0f;
pos.y=20.0f;
pos.z=0.0f;
sprite->Begin(D3DXSPRITE_ALPHABLEND);
sprite->Draw(texture,NULL,NULL,&pos,0xFFFFFFFF);
sprite->End();

Я думаю эта информация может помочь. Попробуй сделать pos глобальной переменной в которую по циклу записывается перемещение спрайта по дисплею слева-направо и наоборот, затем скомпилируй и попробуй вмешаться в эту запись с помощью CE замораживая адрес. Обычно в анимацию ещё вмешивается параметр времени. Смотрим сколько времени прошло и затем меняем координату и затем рисуем - перемещения по времени. А если ты меняешь координату и происходит рисование по таймеру за какими-то пределами, то может это ведёт к каким-то ошибкам. В общем тестируй, смотри.

3) По поводу ошибок.

Держи в уме как работает программа на WinAPI + directX. Т.е. в программе за один кадр (если так предустановлено) идёт расчёт данных, затем рисование графики. Во время ошибки в отладчике нужно посмотреть стек, куда он ведёт - в областью рисования графики или в область рассчётов. Ставь бряк на чтение адреса, исследуй ветку кода. Измени значение адреса, опять исследуй ветку кода с ошибкой. Держи в уме где ошибка могла начаться и где закончилась и две ветки кода. Сравнивай их и ищи источник вылета.

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

Тут ещё не стоит забывать, что игра использует DirectX 5 (1998 год как никак), а у него наверняка огромные отличия от девятки. И нет, по другим адресам всё пишется, One hit kill делается, бессмертие, перетаскивание своих солдат мышкой (опять таки, перетаскивание тоже меняет координаты, правда только одного солдата за раз - работает).

Меня в первую очередь волнует вопрос - как поставить бряк и снять показания регистров во время ошибки? Если ошибка возникает через раз. Ладно, сейчас ещё что-то попытаюсь придумать.

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

Тут ещё не стоит забывать, что игра использует DirectX 5 (1998 год как никак), а у него наверняка огромные отличия от девятки. И нет, по другим адресам всё пишется, One hit kill делается, бессмертие, перетаскивание своих солдат мышкой (опять таки, перетаскивание тоже меняет координаты, правда только одного солдата за раз - работает).

Меня в первую очередь волнует вопрос - как поставить бряк и снять показания регистров во время ошибки? Если ошибка возникает через раз. Ладно, сейчас ещё что-то попытаюсь придумать.

Инжекть свою DLL и веди логи.

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

Глюк оказался в некоторых типах солдат-патрульных, перемещающихся группами за своим командиром. Глючат не все патрули, а только некоторые. Что там с ними не так и чем они отличаются от точно таких же патрулей с другим ID не представляю, с виду структуры солдат одинаковые. Пока отфильтровал их и не стал убирать с карты, вроде не сильно они мешают игру проходить с читом, главное других убрать)) Игра пока перестала вылетать, но тестил мало.. завтра ещё попинаю, может что понятно станет.

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

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

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

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

Мучился я мучился и случайно сделал своего солдата бессмертным - без включенного скрипта бессмертия! Как сделал не понял, повторить не смог( Начал изучать структуру игрока дальше и нашёл флаг невидимости :) За этот флаг отвечала коротенькая процедура, видимо в игре чит на невидимость всё же есть, но неизвестно как его включать без инЪекций. Если невидимость глючить не будет, на убирание врагов с карты можно забить)

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

  • 7 месяцев спустя...

Перешёл к взлому Commandos 2. Ломаю время прохождения миссии. Удивительно, но никак не могу найти этот таймер :-D Сложность в том, что таймер появляется только в конце прохождения карты и его приходится искать вслепую :( Но всё равно никак. Поиск неизвестного застревает на тысяче адресов и дальше все адреса увеличиваются, ничего похожего на таймер по циферкам не видно.

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

Upd: снапшоты в VirtualBox помогли вычислить таймер :) 1 секунда игры = DWORD 25. Время считается инструкцией inc [ecx+10]. Похоже что речь идёт о фреймах... 25 кадров в секунду...

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

  • 2 недели спустя...

Добавил в свою таблицу для Commandos 2 чит на 5 звёзд за скрытность.

Чит на 5 звёзд за посещённые зоны добавлять лениво. Кому любопытно подскажу. В игре имеется массив байт по числу комнат на карте (на всех картах разное число комнат, разная длина массива). Каждый такой байт принимает значение либо 0x4E (куда мы не заходили), либо 0x53 (где мы уже были). Почему именно 0x4E и 0x53? Да потому что это буквы "N" (NO, нет) и "S" (Si, да по испански) :-D . Далее можно выйти на такую функцию


mov eax,[esp+04] ; номер комнаты, куда мы сейчас зашли
test eax,eax
jnge 0058711A
cmp eax,[ecx+0000009C] ; eax сравнивается с числом комнат на карте (длина массива байт)
jnl 0058711A ; если больше, прыжок на выход ret
mov ecx,[ecx+000000A4] ; в ecx - адрес начала массива байт, соответствует первой комнате (обычно это улица)
mov byte ptr [ecx+eax],53 ; ставим признак того что мы тут побывали (буква S)
ret 0004

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

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

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

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