Мотивация
В связи с испорченным местными властями отпуском приходится занимать свое время чем-нибудь интересным. Например, подлечить старую игрушку, косяки которой не позволяют нормально поиграть на современных ОС, либо поменять несколько байтов для получения разных extra-возможностей just for fun. Подопытным будет игра из далекого 2000 года под названием Hogs of War. Если кто не знает, то это turn-based стратегия, где вам дается команда хрюшек, с помощью которых вы должны ни много ни мало, завоевать мир. В процессе игры в зависимости от результатов можно модифицировать каждую хрюшку, например повысив её в звании. В 2009 Atari объявила о продолжении игры в виде разработки HOW2, но по последним данным проект свернули из-за недостатка финансирования. Ничего приятного.
Цель этой части: исправление бага, при котором блокируется весь рабочий стол, если произошел appcrash по какой-либо причине и подготовка приложения для работы в экранном режиме для упрощения отладки.
Хочу всех предупредить: все нижеследующее вы делаете на свой страх и риск. Автор не несет ответственности за любого рода убытки, понесенные в результате воспроизведения описанных действий. Все описанные действия выполнил кот автора.
Инструменты
Для отладки использовались IDA, MSDN, ida_patcher, DxWnd. Обо все более подробнее далее.
Подготовка
Итак, никакого опыта такой отладки нет, поэтому на первых порах придется все делать на интуитивном уровне. Для начала открываем в отладчике бинарный файл, а это у нас warhogs.exe. Возможная причина бага: приложение просто не может по-другому стартовать корректно, либо не может функционировать корректно. В отладчике пробегаемся по импортированным функциям как-либо связанными с окнами Windows, встречая там, конечно-же CreateWindowEx, а так же EnableWindow. Если первый вызов прозрачен, хоть и встречается несколько раз, то второй, пожалуй, настораживает. Переходим в точку вызова функции EnableWindow (всего их 2) и видим следующий код:
Нас интересуют следующие команды:
.text:0044D0A0 and edx, 0FFh
.text:0044D0A6 push edx; bEnable
.text:0044D0A7 push ecx; hWnd
.text:0044D0A8 call ds:EnableWindow
Которые подсказывают что для каких-то окон эта функция вызывается в виде EnableWindow(TRUE, ...);, а для каких-то EnableWindow(FALSE, ...);. Прыгаем по зависимостям вверх (лучше именовать функции, в логике которых вы полностью уверены) и обнаруживаем, что функция EnumFunc используется как callback-функция при вызове EnumWindows, после которой следует вызов функции SystemParametersInfo с кодом 0x61. Недолгое гугление позволяет выяснить что таким способом авторы пытались выключить комбинацию Alt-Tab. Нам это не интересно, поэтому лечим байты по смещению .text+0x0044D0A0, исправляем инструкцию and edx, 0FFh на or edx, 0FFh, что позволит вызывать функцию EnableWindow всегда с первым параметром не равным нулю. Второй reference к функции EnableWindow происходит при закрытии приложения, что говорит о том, что авторы восстанавливают перемирие после того как натворили делов. Здесь ничего не правим.
Конечно же, хочется сразу применить патч и посмотреть на результат, но не тут-то было! Для начала придется сгенерировать diff-файл, который будет выглядеть так:
This difference file has been created by IDA Pro
warhogs.exe
0004C4A1: E2 CA
Затем необходимо сторонней утилитой применить патч к исполняемому файлу. Это делается с помощью скомпилированного исходника ida_patcher.c. Параметры у получившегося консольного приложения следующие: -i <binary_file_to_patch>, -p <.diff file>. Внимание, никаких предупреждений не последует, так что лучше заранее следать backup.
Запускаем приложение, пробуем Alt-Tab, переключается, но warhogs.exe сразу уходит в appcrash. В принципе, не удивительно зачем они нагородили в коде столько костылей. Но есть и приятный бонус, теперь после appcrash рабочий стол не заблокирован, можно спокойно продолжать работать!
Теперь необходимо сделать так, чтобы приложение запускалось в экранном режиме. После небольшого изучения информации было найдено 2 пути для выполнения следующего действия: 1 — изменение кода приложения (изменение кода работы с Direct3D 7), и 2 — использование стороннего приложения под названием DxWnd, которое позволит forcibly запустить warhogs.exe в экранном режиме.
Выбираем второй путь, т.к. он более простой. DxWnd перехватывает вызовы к Direct3D.
Пробуем — получается! Переключение между окнами безболезненное, warhogs работает стабильно в экранном режиме, IDA спокойно отлаживает warhogs.exe пошагово. Все готово для углубления во внутренности движка, что