Часть 1. Исправление спидхака
Первая часть написана exc!ton (Vladimir Chebotarev aka ex-lend). Благодаря ей можно понять как внедрять любые фичи в Аллоды 2. Отдельное спасибо ZZYZX за помощь с восстановлением заголовков статьи. Данные принципы разработки действуют и на «Хэте Тангара«.
Статья рассчитана на людей, знакомых с программированием на Ассемблере.
Здесь я попытался показать, как добавлять собственный код в произвольное место исполняемых файлов при помощи add_dll на примере исправления спидхака.
Принцип работы add_dll
add_dll записывает по заданному RVA в исполняемом файле 6 байт — инструкцию безусловного перехода (jmp) или вызова (call) подпрограммы из библиотеки (dll).В случае безусловного перехода (самый полезный режим) после собственного кода нужно выполнить затёртые вызовом команды и вернуть управление в исходную программу, например, через mov edx, 0xADDRESS / jmp edx.
Спидхак
Багом спидхака называется многократный выход из здания без входа в него. Из-за ошибки игры персонаж в этом случае многократно копируется в список персонажей и обрабатывается опять же много раз вместо одного. Поэтому при попытке атаки будет наноситься во много раз больший урон. Чтобы исправить этот баг необходимо было найти обработку пакета выхода из здания и вставить проверку на нахождение в здании в этот момент.
Пример исправления
Для сборки dll потребуется Microsoft Visual Studio 2003/2005/2008 или Microsoft Visual C++ Toolkit 2003 (мало весит, зато без среды разработки).
В директории сборки должны быть следующие файлы:
- a2server_orig.exe — оригинальный a2server.exe
- add_dll.exe
Откройте server_utils.cpp — исходный код библиотеки:
void __declspec(naked) add_player_to_map() { __asm { push ebp mov ebp, esp sub esp, 0x0C mov eax, [ecx + 0x4C] // unit test eax, 8 jz aptm_already_on_map mov edx, 0x052C40F jmp edx aptm_already_on_map: mov edx, 0x052C47B jmp edx } } #define DLL_PROCESS_ATTACH 1 #define DLL_PROCESS_DETACH 2 int __stdcall DllMain(void *hModule, unsigned long ul_reason_for_call, void *lpReserved) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: break; case DLL_PROCESS_DETACH: break; } return 1; } |
-
Откройте server_utils.def — определение библиотеки и список экспортируемых подпрограмм:
LIBRARY server_utils EXPORTS add_player_to_map @1
Здесь задаётся номер подпрограммы add_player_to_map in dll (1).
-
Откройте server_utils.mapping — список адресов экзешника в exe-файле, которые будут переписаны при помощи вызовов dll
0 1 52C409 // fix speedhack ////////// 0: jmp, 1: call
По адресу 0x52C409 в исполняемый файл записывается вызов подпрограммы из dll номер 1 с использованием команды jmp (0).
-
Откройте compile.bat — скрипт для компиляции и прикрепления dll
@echo off if exist "%VS90COMNTOOLS%vsvars32.bat" ( call "%VS90COMNTOOLS%vsvars32.bat" ) else ( if exist "%VS80COMNTOOLS%vsvars32.bat" ( call "%VS80COMNTOOLS%vsvars32.bat" ) else ( if exist "%VS71COMNTOOLS%vsvars32.bat" ( call "%VS71COMNTOOLS%vsvars32.bat" ) else ( if exist "%VS70COMNTOOLS%vsvars32.bat" ( call "%VS70COMNTOOLS%vsvars32.bat" ) else ( if exist "%ProgramFiles%\Microsoft Visual C++ Toolkit 2003" ( call "%ProgramFiles%\Microsoft Visual C++ Toolkit 2003\vcvars32.bat" ) ) ) ) ) cl /c server_utils.cpp /nologo if errorlevel 1 goto error link server_utils.obj /nologo /dll /def:server_utils.def /out:server_utils.dll if errorlevel 1 goto error copy /y a2server_orig.exe a2server.exe add_dll a2server.exe server_utils.dll server_utils.mapping echo Successfully completed! goto exit :error echo Shit happens :exit
После успешного выполнения скрипта появляются файлы server_utils.dll и a2server.exe.