нашёл в клиенте конструктор покупки (адрес 0x00577380) и функцию отправки пакетов (0x005770F0). Выяснил, что конструктор собирает пакет вида 1d 00 ... | dword слота | count (15 байт), где dword — номер слота товара в магазине. Внутри он также обращается к коллекции «предпокупки» — то, что лежит в корзине окна магазина перед покупкой (нашёл функции begin/end/next для перебора).
Пробовал три подхода:
Собрать пакет руками и отправить через нативный send. Сервер покупку принимает, деньги списываются, присылает ответ с данными предмета (опкод 0x020C: instance-id, item_id, счётчик). Но предмет в инвентаре появляется только после перезахода в игру.
Вызвать конструктор и подменить номер слота уже в готовом пакете (в хуке send, перед отправкой). Результат тот же: сервер принимает, ответ приходит, рендера нет.
Подменить товар в корзине перед вызовом конструктора, чтобы он честно собрал пакет от нужного товара. Это направление ещё не проверено до конца: во время теста корзина была пуста, и конструктор уводил покупку на слот 0
проблема:
конструктор строит не только пакет, но и какое-то внутреннее состояние покупки. Перед работой он читает два поля shop-объекта ([ecx+0x30] и [ecx+0x34]). Похоже, после настоящей покупки через UI там лежит указатель на выбранный товар, а без выбора — мусор.
когда я подменяю пакет на лету, пакет говорит «покупаем слот 14», а внутреннее состояние клиента построено от другого товара (или от пустой корзины). Ответ сервера 0x020C клиент сверяет со своим состоянием, не находит совпадения — и молча выбрасывает пакет.
Вопросы:
Верно ли я понимаю, что пакет и внутреннее состояние покупки строятся из одного источника (корзины магазина), и без совпадения ответ сервера просто игнорируется? Как это надёжно проверить?
Как лучше отследить, что делает обработчик пакета 0x020C: бэктрейсы из recv дают мусор, нормального трейса не выходит. Ставить хуки на весь код после диспетчера пакетов? Искать обработчик по опкоду в таблице?
Может, кто-то уже разбирал — интересует структура shop-объекта (поля +0x30/+0x34) и корзина магазина.
нашёл в клиенте конструктор покупки (адрес 0x00577380) и функцию отправки пакетов (0x005770F0). Выяснил, что конструктор собирает пакет вида 1d 00 ... | dword слота | count (15 байт), где dword — номер слота товара в магазине. Внутри он также обращается к коллекции «предпокупки» — то, что лежит в корзине окна магазина перед покупкой (нашёл функции begin/end/next для перебора).
Пробовал три подхода:
Собрать пакет руками и отправить через нативный send. Сервер покупку принимает, деньги списываются, присылает ответ с данными предмета (опкод 0x020C: instance-id, item_id, счётчик). Но предмет в инвентаре появляется только после перезахода в игру.
Вызвать конструктор и подменить номер слота уже в готовом пакете (в хуке send, перед отправкой). Результат тот же: сервер принимает, ответ приходит, рендера нет.
Подменить товар в корзине перед вызовом конструктора, чтобы он честно собрал пакет от нужного товара. Это направление ещё не проверено до конца: во время теста корзина была пуста, и конструктор уводил покупку на слот 0
проблема:
конструктор строит не только пакет, но и какое-то внутреннее состояние покупки. Перед работой он читает два поля shop-объекта ([ecx+0x30] и [ecx+0x34]). Похоже, после настоящей покупки через UI там лежит указатель на выбранный товар, а без выбора — мусор.
когда я подменяю пакет на лету, пакет говорит «покупаем слот 14», а внутреннее состояние клиента построено от другого товара (или от пустой корзины). Ответ сервера 0x020C клиент сверяет со своим состоянием, не находит совпадения — и молча выбрасывает пакет.
Вопросы:
Верно ли я понимаю, что пакет и внутреннее состояние покупки строятся из одного источника (корзины магазина), и без совпадения ответ сервера просто игнорируется? Как это надёжно проверить?
Как лучше отследить, что делает обработчик пакета 0x020C: бэктрейсы из recv дают мусор, нормального трейса не выходит. Ставить хуки на весь код после диспетчера пакетов? Искать обработчик по опкоду в таблице?
Может, кто-то уже разбирал — интересует структура shop-объекта (поля +0x30/+0x34) и корзина магазина.
Тебе же уже отвечали на этот вопрос. Еще раз. Пакет «купить у торговца» — это только запрос от клиента к серверу. Он не создаёт вещь на клиенте. Ты руками шлешь пакет, он уходит на сервер. Сервер проверяет условия, списывает деньги и добавляет предмет в своё состояние / БД. После этого сервер шлет на клиент:
- подтверждение покупки,
- обновление денег,
- обновление инвентаря / добавление предмета.
Если ты шлёшь пакет руками, ты воспроизводишь только одну часть диалога — запрос. А нормальная покупка — это целая цепочка: открытие торговца, выбор товара, запрос, подтверждение, синхронизация инвентаря. Сервер может обработать запрос и списать деньги, но:
- может не прийти ответный пакет,
- или клиент его отбрасывает, потому что нет активной торговой сессии,
- или не совпал sequence/session/transaction id,
- или клиент не ждёт этот ответ, потому что покупка была инициирована не через обычный UI,
- или античит/логика сервера не отправляет повторное обновление.
В итоге на сервере предмет уже лежит, а локальный инвентарь клиента остался старым. При перезапуске игра делает полную синхронизацию: запрашивает у сервера актуальный инвентарь, деньги и персонажа. Тогда предмет и появляется.
Тигрь дал тебе лучший совет - захукать функцию отвечающую за покупку предмета. Не посмотреть на нее и сделать руками пакет, а именно захукать.
Если не умеешь хукать, тогда снимай все пакеты в данной цепочке, а не только отвечающий за покупку. Снимаешь пакеты, далее изучаешь что каждый из них делает. Воспроизводишь на своей стороне именно последовательность пакетов, в порядке, котором их шлет клиент и обрабатываешь их в порядке, в котором клиент получает ответы от сервера.
Последний раз редактировалось rule-z; 14.10.2026 в 22:38.