|
|
Stealing items from shop
Author: Vladimir Chebotarev aka ex-lend
Categories: RoM 2, Technical
При перетаскивании вещи клиент посылает серверу пакет типа:
22 XX XX YY ZZ QQ QQ WW WW RR RR, где:
XX XX - id юнита
YY - место, откуда (1 - тело, 2 - инвентарь, 4 - прилавок, 5-8 - полки)
ZZ - место, куда
QQ QQ - номер слота, откуда
WW WW - номер слота, куда
RR RR - количество
| |
Здесь надо заметить, что сервер не делает проверки при перетаскивании
с прилавка в инвентарь, это запрещено только с клиентской стороны. Таким образом, мы можем
перетаскивать вещи с прилавка бесплатно и без лишних усилий.
Посмотрим на код, генерирующий пакет перетаскивания вещи (allods2.exe):
.text:0041C087 mov eax, [ebp+var_8]
.text:0041C08A mov ecx, [eax+138h]
.text:0041C090 mov edx, [ebp+var_4]
.text:0041C093 mov ax, [ecx+4]
.text:0041C097 mov [edx+0Ah], ax
.text:0041C09B mov ecx, [ebp+var_4]
.text:0041C09E mov dx, [ebp+arg_4]
.text:0041C0A2 mov [ecx+0Eh], dx
.text:0041C0A6 mov eax, [ebp+var_4]
.text:0041C0A9 mov cl, [ebp+arg_0]
.text:0041C0AC mov [eax+0Ch], cl ; место, откуда
.text:0041C0AF mov edx, [ebp+var_4]
.text:0041C0B2 mov ax, [ebp+arg_C]
.text:0041C0B6 mov [edx+10h], ax
.text:0041C0BA mov ecx, [ebp+var_4]
.text:0041C0BD mov dl, [ebp+arg_8]
.text:0041C0C0 mov [ecx+0Dh], dl ; место, куда
.text:0041C0C3 mov eax, [ebp+var_4]
.text:0041C0C6 mov cx, [ebp+arg_10]
.text:0041C0CA mov [eax+12h], cx | |
Нетрудно модифицировать его таким образом, например, чтобы при перемещении с прилавка (4) куда-бы то ни было
пункт назначения был установлен в инвентарь (2).
Для защиты от этой ошибки необходимо ввести дополнительную проверку на сервере. Рассмотрим код обработки
пакета 22 (a2server.exe):
.text:00505A85 loc_505A85: ; CODE XREF: sub_504A96+F95
.text:00505A85 mov edx, [ebp+var_5C]
.text:00505A88 xor eax, eax
.text:00505A8A mov al, [edx+0Ch] ; место - откуда
.text:00505A8D cmp eax, 4 ; прилавок?
.text:00505A90 jnz short loc_505AD8
.text:00505A92 mov ecx, [ebp+var_54]
.text:00505A95 mov edx, [ecx+10h]
.text:00505A98 push edx
.text:00505A99 mov ecx, [ebp+var_C38]
.text:00505A9F call sub_502C50
.text:00505AA4 mov [ebp+var_6C], eax
.text:00505AA7 cmp [ebp+var_6C], 0
.text:00505AAB jnz short loc_505AB2
.text:00505AAD jmp loc_50864E
.text:00505AB2 ; ---------------------------------------------------------------------------
.text:00505AB2
.text:00505AB2 loc_505AB2: ; CODE XREF: sub_504A96+1015textj
.text:00505AB2 mov eax, [ebp+var_5C]
.text:00505AB5 xor ecx, ecx
.text:00505AB7 mov cx, [eax+12h]
.text:00505ABB push ecx
.text:00505ABC mov edx, [ebp+var_5C]
.text:00505ABF movsx eax, word ptr [edx+0Eh] ; номер слота - откуда
.text:00505AC3 push eax
.text:00505AC4 mov ecx, [ebp+var_54]
.text:00505AC7 push ecx
.text:00505AC8 mov ecx, [ebp+var_6C]
.text:00505ACB call sub_5446C7 ; вытащить вещи с прилавка в eax
.text:00505AD0 mov [ebp+var_60], eax
.text:00505AD3 jmp loc_505BDF | |
Функция по адресу 5446C7 перемещает вещь с заданного слота прилавка во временный объект и возвращает его, а
далее этот объект независимо от происхождения может быть перемещен
в любой пункт назначения.
Чтобы найти нужную нам вещь переберем все вещи на прилавке. Далее посмотрим ее происхождение.
Если вещь магазинная, вместо объекта с вещью надо вернуть 0 и не выполнять никакого перемещения.
Этот код надо вставить вместо вызова sub_5446C7:
push ebp
mov ebp, esp
push ecx
mov [ebp-0x04], ecx
mov eax, [ebp-0x04]
mov ecx, [eax+6Ch]
mov eax, [ebp+0x08]
push eax
call 0x547468 ; получим список вещей прилавка
lea ecx, [eax + 0x078]
mov eax, [ecx + 4] ; число вещей на прилавке
test eax, eax
jz ret0
mov edx, [eax + 8]
mov eax, [eax]
xor ecx, ecx
start:
test edx, edx
jz ret0
cmp ecx, [ebp + 0x0c] ; сравниваем индекс вещи с номером слота
jnz next
cmp dword ptr [edx + 0x14], 0 ; ключевой момент
jz ret0 ; магазинная вещь, выходим без перетаскивания
jmp done
next:
add ecx, 1 ; перейдем к следующему элементу связного списка
test eax, eax
jz ret0
mov edx, [eax + 8]
mov eax, [eax]
jmp start
ret0:
xor eax, eax
mov esp, ebp
pop ebp
retn 0Ch
done:
mov eax, [ebp+0x010]
push eax
mov ecx, [ebp+0x0C]
push ecx
mov edx, [ebp+0x08]
push edx
mov eax, [ebp-0x04]
mov ecx, [eax+6Ch]
call 0x547C5A ; вызовем извлечение вещи из инвентаря
; это все что было внутри
; старой sub_5446C7
mov esp, ebp
pop ebp
retn 0Ch | |
Discussion (0)
|