Winhack и с чем его едят

В 2008-2009 гг дота набрала сурьезную популярность, и встал вопрос — как следить за ней? Формат карт варкрафта подразумевает разворачивание событий от старта и до самого конца, без необходимости что-то сохранять в процессе. Кликнул в XY, отдал приказ X в юнита Y — ничего из этого дублировать в реплей не нужно, но и узнать о событии аналогично нельзя. А хотелось как-то автоматизировать процесс получения инфы о КДА, героях, артефактах. Тогда и придумали использовать для этого функцию SyncStored*. (* = Integer/String/etc, формат данных).

Технически, эта функция передает всем игрокам в игре некое значение для сохранения в gamecache. Gamecache предназначался для для хранения инфы, которую следует передавать вдоль кампаний. Соответственно, если нужно было передать, что Майев имеет 3й уровень со вторым блинком и первым ножиком, то только SyncStored* позволял рассказать об этом. Внутри реплея оставалась специфическая запись, по которой и переносились персонажи с прежними параметрами. Формат реплеев варкрафта был полностью разобран еще в 2004 году, поэтому проблем с созданием первых парсеров не возникло никаких.

DotA
В доте данные синхронизирует игрок на самом высоком слоте. Если синего в игре нет, то передает данные следующий по цвету, вплоть до 10-го игрока. Как только обнаружится хоть один живой игрок, в реплей будет записана необходимая информация. Это позволяет избежать ситуации, что одна и та же инфа будет отсылаться каждым игроком — и вместо одной строчки «пикнул героя ID=XXXX» в реплее появится десять копий.


Сохранение инфы о том, какой мод был активирован

Сохранение инфы, что подобрана руна, пропал пустой ботл и появился ботл с руной

Вскоре появились системы автоматических хостов — Ghost bot. Они тоже основывались на данных, синхронизируемых игроками. В то время мало кому приходило в голову проверять на прочность защиту — в конце концов, кому могут быть интересны виртуальные цифры? Перед кем ты выпендришься, что победил, если платформы, существовавшие на тот момент, были комнатами в гарене без какой-либо статистики? Плюс они, как правило, были по инвайтам или тест-играм, и мало кого интересовало мнение парсера об игре. Заниматься исследованием безопасности было просто некому, да и не за чем.

Первый тред, который я нашел, описывающий проблему, появился весной 2009 года на одном из самых активных тогда порталов wc3c. После перевода на новый патч варкрафта, который позволил перенести хранение данных о заклинаниях из gamecache в hashtable (да, в gamecache хранили не только инфу для парсеров, но и реальные игровые данные), встал вопрос о целесообразности работы с gamecache вообще. Hashtable не умел транслировать данные в реплей, он был просто крайне удобным хранилищем данных «здесь и сейчас». Но близзарды не поправили, да и не планировали, возможность отправки SyncStored* клиентом. Т.е. любой, даже не самый верхний слот, мог отправить подобный пакет, используя минимальные знания устройства TCP/IP и имея на руках любой сниффер трафика, передав так любые возможные данные.

На практике
Пусть в дотку сели поиграть игроки Aркадий, Bасилий, Cашок и Дениска. Cашок — наш кулхакер, узнавший про уязвимость и обложившийся программками для перехвата и модификации трафика, либо же техническими помощниками по внедрению кода в поток. В варкрафте сервер — всему голова, поэтому Aракдий даже ни о чем не задумывается и заканчивает игру со счетом 20-0. Но парсер ему говорит, что, на самом деле, счет у него 0-20, а у Cашка — 20-0. Если включить реплей в варкрафте, естественно, Аркадий увидел бы 20-0. Но так получилось, что все данные, которые он синхронизировал с клиентами, были перезаписаны (берется последнее полученное значение), и там стата от Сашки. Может, и нужно бы минуснуть пару зубов особо умному недорослю, но откуда Аркадий может знать, кто это подстроил?

Согласно информации испытателей (я никогда не тестил так досконально), SyncStored* сперва пингует всех клиентов в игре, выбирая того, с кем пинг минимален. Ему отсылается информация, что "Вот такие данные нужно синхронизировать, я себе уже поставил". Он, в свою очередь, ищет ближайшего к себе, игнорируя тех, кто уже поставил подпись о получении. И так — пока не дойдет до сервера, который подтвердит инфу и отошлет её тем, кто ещё не получил. Весь процесс занимает миллисекунды.

Если у Сашка пинг до Дениски был меньше, чем до Аркадия, Аркадий получит пакет от имени Дениски. Даже при наличии собственного анализатора пакетов на стороне сервера Аркадий может неверно определить автора подставы. Впрочем, это мало чего решает — варкрафт уже получил пакет и, как сервер, отдаст его всем клиентам, записав в реплей стату 0-20. В реплей при этом не пишется, кто прислал пакет — считается, что он по умолчанию от хоста (не разбирал внутренности реплея, но очень похоже на то).

Проще говоря, сохранение статы, доверенное в доте изначально только верхнему слоту, может производиться любым игроком при наличии небольших знаний и пары программ. Отследить трудно из-за цепочек получателей, отловить из игры невозможно — согласно логике близзард, функция и создана для локального применения, поэтому безопасность не имеет значения.

Окей, Сашок умеет переписывать статистику. Но ведь не ей единой, правда? В реплей пишутся пикнутые герои, артефакты, события разрушения вышек — опять же SyncStored*. Всё это Сашок тоже может подделать, указав в реплее, что Дениска вообще разбил 100500 вышек и собрал 6 рапир. Но всё это ерунда, ведь кого волнует статистика, если победа — это все равно победа?

Это волнует Ghostbot-ов. Как и во всем остальном, варкрафт никак не сообщает, что кто-то победил. Линейный принцип развертки делает подобные записи излишними. Поэтому в доте используются сообщения о том, кто победил или подходит к тому. Например, при атаке по трону есть целых несколько событий: «у трона осталось 75% хп», 50%, 25%, 10%. Каждое из них может сработать строго один раз — потом триггер выключается. Наконец, при смерти трона выключается отслеживание смерти обоих тронов и записывается 1, если победили сенты, или 2, если победили скуржи. А значит, эти данные тоже можно подделать, сделав систему автоматического определения победителя несостоятельной.


Сохранение инфы: 1 — победа сентов, 25 и 13 — длительность игры, мин и сек

На небезызвестной в СНГ помойке бот настроен так, что, при получении данных об «у трона осталось 10% хп», он уже засчитывает победу врагам пострадавшего трона. Если вашему трону оставили менее 450 хп, но вы отбились и имеете шансы пропушить в ответ до победы, вы все равно проиграете — потому что кривые руки даже могила не исправит. В принципе, можно уже подделкой этого события дурить ботов. Но местные Сашки, предпочитающие в 2015 году кулхацкать сайты школьников, идут по еще более наглой дороге, заспамливая бота сообщением «мы (сенты/скуржи) победили». Через минуту такого ддоса бот сдается и засчитывает победу.

Решение
Подобные абузы, будучи вычисленными еще в 2009 году, заставили кодеров ботов внести коррективы в несколько библиотек, и боты нормальных платформ — RGC / Ohsystem — нормально посылают неподтвержденную информацию лесом. Так был исправлен баг с возможностью отправки данных теми, кто их отправлять вовсе не должен.

Исправить вред, наносимый подставными данными, невозможно — все парсеры настроены на работу именно с gamecache, да и никаких альтернатив в целом нет. Варкрафт — линейная стратегия, где необходимости хранить что-то независимо просто не было нужды.

Итак, вся суть винхака — это втирание всякой дичи доверчивым ботам. Лечится прямыми руками тех, кто занимается обновлением ботов или их модификацией. Его можно отбить — достаточно наличия пряморуких специалистов.

PS. Старые парсеры могут неадекватно реагировать на появление в реплее кода, который морально устарел, и ломаться. Так можно обеспечить себе алиби, поломав реплеи у всех игроков разом.

14 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.