Jump to content
V3ct0r

Как добавить к крыльям эффект полета

Recommended Posts

Как добавить к крыльям эффект полета

 

ca6c40f2764a.png

 

Привет! В данной статье я расскажу как сделать, чтобы персонаж летал на обычных крыльях.

 

Вам понадобится:

  1. Отладчик OllyDBG;
  2. Базовые знания ассемблера;
  3. Умение переводить числа из десятичной системы счисления в шестнадцатиричную и обратно;
  4. Терпение и внимательность.

 

Для примера, заставим нашего персонажа летать на fae6dc23ee0e.png Ангельских крыльях (ID: 937) 

 

0. Все модификации производятся на стороне клиента. Я буду работать с Game.exe из английского клиента TOP версии 1.38, поэтому, скорее всего, у Вас будут отличаться адреса инструкций;

 

1. Запустите клиент, откройте OllyDBG и присоединитесь к процессу Game.exe (команда File -> Attach -> В списке процессов выбрать Game.exe -> Attach);
3a5f684532e2.png

 

2. Далее перейдите в модуль Game.exe (команда View -> Executable Modules или ALT + E -> В списке модулей выбрать Game.exe);

d582d5663305.png

 

3. Выполните анализ кода (контекстное меню -> Analysis -> Analyse code или CTRL + A);

64cecc7c29b5.png

 

4. Найдите функцию, которая отвечает за обновление позы персонажа при перемещении крыльев в 1-ю ячейку инвентаря. Например, с помощью команды контекстное меню -> Search for -> Command или CTRL + F. Затем в окошко поиска вводим:

CMP EAX, 80

В моем Game.exe она выглядит следующим образом:

004A34B0  /$ 8B81 0C0D0000  MOV EAX,DWORD PTR DS:[ECX+D0C]
004A34B6  |. 3D 80000000    CMP EAX,80
004A34BB  |. 7C 11          JL SHORT 004A34CE
004A34BD  |. 3D 8C000000    CMP EAX,8C
004A34C2  |. 7F 0A          JG SHORT 004A34CE
004A34C4  |. 3D 87000000    CMP EAX,87
004A34C9  |. 74 03          JE SHORT 004A34CE
004A34CB  |. B0 01          MOV AL,1
004A34CD  |. C3             RETN
004A34CE  |> 32C0           XOR AL,AL
004A34D0  \. C3             RETN

Если перевести эту функцию в C-код, то она будет выглядеть примерно так:

// Проверка на крылья
int CheckWings(int id)
{
	if (id >= 128 && id <= 140 && id != 135)
	{
		return 1; // В 1-й ячейке инвентаря крылья перерожденя
	}
	
	return 0; // 1-я ячейка пуста или в ней лежит какой-то другой предмет
}

Наша с Вами задача заключается в изменении этой функции, а именно условия, где сравнивается ID предмета из 1-ой ячейки инвентаря с ID крыльев. Давайте добавим в него нашли крылья:

if (id >= 128 && id <= 140 && id != 135 || id == 937)

Тогда наша функция на ассемблере будет выглядеть вот так:

; RET_0 - адрес инструкции XOR AL, AL
; RET_1 - адрес инструкции MOV AL, 1
MOV EAX,DWORD PTR DS:[ECX+D0C]
CMP EAX, 0x03A9 ; 0x03A9 = 937 - ID Ангельских крыльев
JE SHORT RET_1 ; Прыжок на return 1, если ID == 937
CMP EAX,80
JL SHORT RET_0 ; Прыжок на return 0
CMP EAX,8C
JG SHORT RET_0 ; Прыжок на return 0
CMP EAX,87
JE SHORT RET_0 ; Прыжок на return 0
MOV AL,1 ; return 1
RETN
XOR AL,AL ; return 0
RETN

Здесь мы сталкиваемся с проблемой: новая функция занимает больше байт, чем оригинальная! Что делать? В конце модуля есть так называемый Code Cave - область, заполненная нулевыми байтами. Именно туда мы и поместим нашу новую функцию. Найти эту область очень просто: крутите ползунок в окне кода до тех пор, пока не увидите инструкции вида:

DB 00
DB 00
DB 00
DB 00

bb883a70885d.png

 

Итак, помещаем нашу функцию в Code Cave, я поместил ее по адресу 0x005FF850:

08657b620363.png

 

Обратите внимание, что адреса инструкций RET_0 и RET_1 у меня получились 0x005FF875 и 0x005FF872 соответственно. Не забудьте их исправить в функции.

 

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

 

Давайте воспользуемся вторым способом. Идем на начало оригинальной функции (в данном гайде это 0x004A34B0) и пишем следующий код, заменяя оригинальный:

jmp <адрес модифицированной функции>
retn

У меня получилось вот так:

a809db5c4f73.png

 

Протестируем наши изменения. Зайдите в игру и поместите Ангельские крылья в 1-й слот инвентаря. Персонаж должен взлететь:

819a9e6929d9.png

 

5. Как видно из скриншота, значок GM провалился в персонажа, давайте это исправим. Найдите следующий код, например, продолжая искать инструкцию CMP EAX, 80:

004A3F7F   . 8B86 0C0D0000  MOV EAX,DWORD PTR DS:[ESI+D0C]
004A3F85   . 3D 80000000    CMP EAX,80
004A3F8A   . 7C 16          JL SHORT 004A3FA2
004A3F8C   . 3D 8C000000    CMP EAX,8C
004A3F91   . 7F 0F          JG SHORT 004A3FA2
004A3F93   . 3D 87000000    CMP EAX,87
004A3F98   . 74 08          JE SHORT 004A3FA2
004A3F9A   . D905 30936000  FLD DWORD PTR DS:[609330]
004A3FA0   . EB 06          JMP SHORT 004A3FA8
004A3FA2   > D905 70136000  FLD DWORD PTR DS:[601370]

На скриншоте ниже в оранжевой рамке я выделил "ориентиры" - вызовы функций SetYaw() и UpdatePitchYawRoll() из библиотеки MindPower:

faba838aa06f.png

 

Как видите, здесь точно такое же условие, как и в прошлой функции, и нам надо его изменить. Обратите внимание на адреса 0x004A3FA2 и 0x004A3F9A:

  • 0x004A3F9A - код, который выполнится при соблюдении условия (в 1-й ячейке инвентаря находятся крылья);
  • 0x004A3FA2 - код, который выполнится, если условие не соблюдается (в 1-й ячейке инвентаря нет крыльев).

 

Так как новое условие будет занимать больше места, чем оригинальное, идем в Code Cave и записываем его. Я запишу по адресу 0x005FF87A:

8528b54e02c2.png

 

Далее необходимо задействовать новый код. Идем по адресу 0x004A3F85 и выполняем прыжок на новое условие:

jmp <адрес нового условия> ; в данном гайде - 0x005FF87A

8a0e522c0f09.png

 

Идем в игру и убеждаемся, что значок GM встал на свое место:

bf88afffce4a.png

 

6. Если вы прикажете персонажу перемещаться, то увидите, что он будет бегать, а не летать. Исправим и это. 

 

Найдите код, примерно похожий на этот:

004A44FE  |. 0F944424 1C    SETE BYTE PTR SS:[ESP+1C]
004A4503  |. 3D 80000000    CMP EAX,80
004A4508  |. 7C 46          JL SHORT 004A4550
004A450A  |. 3D 8C000000    CMP EAX,8C
004A450F  |. 7F 3F          JG SHORT 004A4550
004A4511  |. 3D 87000000    CMP EAX,87
004A4516  |. 74 38          JE SHORT 004A4550
004A4518  |. 83FF 01        CMP EDI,1
004A451B  |. 74 05          JE SHORT 004A4522
004A451D  |. 83FF 04        CMP EDI,4
004A4520  |. 75 07          JNZ SHORT 004A4529
004A4522  |> BF 2A000000    MOV EDI,2A
004A4527  |. EB 27          JMP SHORT 004A4550
004A4529  |> 83FF 05        CMP EDI,5
004A452C  |. 74 05          JE SHORT 004A4533
004A452E  |. 83FF 06        CMP EDI,6
004A4531  |. 75 07          JNZ SHORT 004A453A
004A4533  |> BF 2B000000    MOV EDI,2B
004A4538  |. EB 16          JMP SHORT 004A4550
004A453A  |> 83FF 02        CMP EDI,2
004A453D  |. 75 07          JNZ SHORT 004A4546
004A453F  |. BF 2C000000    MOV EDI,2C
004A4544  |. EB 0A          JMP SHORT 004A4550
004A4546  |> 83FF 10        CMP EDI,10
004A4549  |. 75 05          JNZ SHORT 004A4550
004A454B  |. BF 2D000000    MOV EDI,2D
004A4550  |> 83F9 06        CMP ECX,6

На скриншоте я опять оставил "ориентиры":

f87f2f2c8022.png

 

И опять то же самое условие, которое нужно изменить. В принципе, процесс редактирования условия схож с предыдущим пунктом, только у нас другие адреса для положительного и отрицательного исхода:

  • 0x004A4518 - код, который выполнится при соблюдении условия (в 1-й ячейке инвентаря находятся крылья);
  • 0x004A4550 - код, который выполнится, если условие не соблюдается (в 1-й ячейке инвентаря нет крыльев).

 

Точно так же идем в Code Cave и пишем новое условие. Я напишу по адресу 0x005FF8AD:

7cab785f2dbd.png

 

Заставляем программу использовать новый код, вместо старого. Идем по адресу 0x004A4503 и делаем прыжок:

jmp <адрес нового условия> ; в данном гайде - 0x005FF8AD

8a1c6ae53f83.png

 

Идем в игру и тестируем:

e53b7b85f609.png

 

Ура! Теперь персонаж летает на Ангельских крыльях!

 

7. Сохраните проделанные изменения. В контекстном меню выберите команду Copy to executable -> All modifications. 

83baeffef114.png

 

На вопрос "Copy selection to executable file?" отвечайте "Copy all". Появится окошко, просто закрывайте его крестиком. Тут программа задаст новый вопрос типа: "Файл Game.exe был изменен! Сохранить изменения?", отвечаете "Да" и в диалоге выбора файла, вводите название для измененного Game.exe.

 

8. На этом редактирование Game.exe завершено! Зайдите в игру и убедитесь что все работает как задумано.

 

В результате мы с Вами заставили персонажей летать на Ангельских крыльях с ID 937! :smile:

  • Like 1

Share this post


Link to post
Share on other sites

Интересный ход решения задачи, но не проще было бы в исходниках поправить пару строк?

Share this post


Link to post
Share on other sites
В 12.07.2016 в 15:31, Waka~ сказал:

Интересный ход решения задачи, но не проще было бы в исходниках поправить пару строк?

А сколько нынче людей используют собственно скомпилированный клиент-сервер?

  • Haha 1

Share this post


Link to post
Share on other sites
В 12.07.2016 в 13:31, Waka~ сказал:

Интересный ход решения задачи, но не проще было бы в исходниках поправить пару строк?

 

Меня просили писать побольше гайдов на тему патчинга .exe файлов, и, как подметил @e1mer, исходники пока еще нигде не используются, так как требуют сперва изучения

Share this post


Link to post
Share on other sites
On 6/28/2019 at 5:27 AM, johan said:

Does this work in game 2.0?

 

Гайд написан для версии игры 1.3x. Адреса и инструкции в Game.exe 2.0 отличаются, но принцип редактирования должен быть тот же.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×