На чем написаны world of tanks
Разбор протокола World Of Tanks
Часть первая: инструментарий мелкосерийного изобретения велосипедов
Почему и зачем: длинная и необязательная преамбула
Хорошо, что опыта игрового модостроительства у меня было немного — так, пару кастомных прицелов для Deer Hunter 2005 и «нелицензионный» недоклиент VATSIM/FSD с сопутствущим «взломом» протокола последнего. Ещё лучше, что ни разу не приходилось с головой погружаться в сколь-нибудь трудоёмкую и длительную отладку и дизассемблирование. То есть, с IDA и OllyDBG я поверхностно знаком, но не как с ежедневными рабочими инструментами.
Итак, я уверен, что в обозримом будущем никаких планов по введению полноценного режима спектатора в WOT нет и не будет. Под полноценным режимом спектатора я понимаю множественные подключения игроков в сеанс боя изначально как невзаимодействующих на игру «привидений»-наблюдателей, а не на технике. Это тот самый режим, из-за отсутствия которого комментаторы на чемпионатах WOT вынуждены заходить в бой 15-м танком, убиваемым своими на базе. Это тот самый режим, из-за которого появились моды «командирского zoom» и «кинематографической камеры» — по сути, просто костыли. А нужен такой режим затем, чтобы командир роты занимался командованием, а не скакал впереди на лихом танке по-чапаевски, чтобы он видел ситуацию на карте в целом непрерывно, а не отвлекался на неё в пылу нападения из засады. В идеале, командиру даже не нужны красоты трёхмерного мира — достаточно одной большой карты на весь монитор с игровой ситуацией в реальном времени — HP, повреждениями модулей, членов экипажа, направлениями стволов и прицелов союзной техники, засвеченных в каждый момент вражеских юнитов и прочей вспомогательной информации.
WOT предоставляет широкие возможности модостроительства, но такая идея выходит за рамки классического «заменить пару swf-файлов на свои». Потребуется перехват и разбор самого игрового протокола для того, чтобы иметь возможность передать на командирский планшет своё видение игровой ситуации.
Обход шифрования 0x0A-й дорогой
Первые робкие попытки пролезть в протокол танков я предпринял ещё в 2011 году. Начинать это, как и везде в подобных задачах, стоит с хорошего сниффера (кстати, в случае с VATSIM/FSD на этом можно и остановиться — внезапно оказалось, что протокол там текстовый), и я, вооружившись Microsoft Network Monitor’ом, ринулся в бой. За отчётные 3 года в схеме входа ничего кардинально не поменялось, кроме количества игровых кластеров. Сервис авторизации у каждого кластера живёт на одном IP, к нему уходит один пакет с логином-паролем, и от него приходит один пакет — как минимум, с идентификатором конкретного игрового сервера из этого же кластера, на который клиенту надо переключиться, и с чьим IP происходит весь дальнейший обмен. Выглядит это всё приблизительно так
Помеченные октеты, судя по тому, что изменяются они мало и более-менее предсказуемо — заголовок пакета. После них идёт равномерный битовый шум, то есть там уже включается шифрование. Тут можно было вспомнить, что записи боёв в WOT шифруются BlowFish’ем, и что ключ шифрования не изменялся с того момента, как стал известен широкой публике, и покопаться глубже — но смысла в этом особого не вижу. Для задуманного гораздо важнее то, что ходит между клиентом и сервером в процессе игры, чем то, как он авторизуется при входе.
Итак, если трафик проходит потоковое шифрование, логично предположить, что где-то в глубинах программы есть функция наподобие SendToServer(), в которой есть вызов вроде EncryptBuffer() и в которой, в конечном счёте, выполнение доходит до конкретного sendto(). Наша задача, для начала — найти, где это происходит. Загружаем танки в OllyDbg и перед нажатием на кнопку «Войти» ставим логирующий брейкпоинт на sendto().
Через несколько десятков срабатываний, уже в ангаре, вызовы sendto() становятся более монотонными, в том плане, что адрес буфера для отправки данных не меняется:
Чтобы узнать, где шифруется этот буфер, я сначала пошёл по неправильному пути — начал изучать графы вызовов в IDA и отслеживать вручную возвраты из функций. Где-то на 15-й такой функции мне это надоело, я полностью заблудился в коде и поставил брейк на запись по адресу буфера.
Брейк сработал внутри вот такой чудесной функции по адресу 0x00BAF76F, чудесность которой состоит в том, что в неё передаются 3 параметра — два адреса буфера и ещё один — их одинаковая длина. Тот самый EncryptBuffer(ptr_src,ptr_dest,len), который нам нужен. Что там лежит в незашифрованном виде, мы пока смотреть не будем, об этом позже.
Это что касается отправки данных. Как быть с приёмом? Немного сложнее, но, в целом, так же, поэтому не буду утомлять вас большими и страшными скриншотами отладчика. Схема такая — ставим брейк на recvfrom(), смотрим адрес буфера, куда складывается принятый зашифрованный пакет. Ставим брейкпоинт на чтение с адреса буфера и тут нам в очередной раз повезло — брейк срабатывает на вызове функции по адресу 0x00BAFB79, которая занимается расшифровкой блоков по 8 байт и находится, в свою очередь, в теле функции по адресу 0x00BAFB30. А уже эта функция почти такая же чудесная, как и та, что мы нашли выше: она принимает 4 параметра — два адреса буфера, их длину и какой-то флаг.
Назовём её DecryptBuffer(ptr_src,ptr_dest,len,flag). Адреса буферов, как видно, совпадают. Что полностью логично, так как при потоковом шифровании стоит ожидать одинаковой длины блоков исходного и шифротекста.
Осталась одна тонкость. Если функцию EncryptBuffer() достаточно перехватывать непосредственно перед её вызовом (т.е. ставим INT3-брейкпоинт вместо CALL) вытаскивая память по адресу ptr_src длиной len, то в момент вызова DecryptBuffer() оба указателя покажут на один и тот же блок, который ещё пока зашифрован. Поэтому перехватывать эту функцию надо перед самым возвратом, который у неё происходит командой RETN 10 по адресу 0x00BAFBA8. В этот момент на стэке лежат те же параметры, за исключением того, что ptr_src равен нулю (это нововведение версии 0.8.11, в предыдущей указатели как-то оставались равны) и адрес возврата. И ptr_dest, конечно, показывает на расшифрованный буфер. Теперь, когда мы знаем, где в клиенте WOT сообщения ещё не зашифрованы и где уже расшифрованы, нужно их оттуда автоматически вытаскивать для дальнейшего анализа.
Что же там внутри?
Здесь матёрые гуру реверс-инжиниринга, в духе «There’s an emacs command to do that» подумают: «ага, ну теперь можно написать на питоне\эзотерическом языке вот такой скрипт\плагин для ольки\иды, который будет делать с этими данными всё что хочешь и даже за пивом сбегает». Но мы пойдём другим путём. Я хочу сразу ориентироваться на то, что ещё до того, как дело дойдёт до разработки командирского планшета, то есть даже для самого полноценного разбора протокола WOT мне понадобятся помощники и тестировщики, далёкие от мира программирования. Им нужен будет простой инструмент с понятным интерфейсом, выдающий легко читаемые данные.
Так что предвидя скептические ухмылки, я засел за Lazarus и набросал в нём специализированный win32-отладчик, основной функцией которого является поставить два INT3-брекпоинта в нужных местах и по их срабатыванию вытаскивать данные по адресу и длине буфера, лежащим на стеке по известным смещениям. Ещё он умеет вести txt.gz лог с hexdump’ами пакетов и записывать все прошедшие пакеты так, что их потом можно заново «проиграть» через парсер. Вот что получилось. Так WOT клиент только начинает входить в ангар.
А вот так он себя ведёт уже находясь в ангаре.
Какие выводы можно сделать, даже не смотря на пояснения к пакетам, которые я поленился убрать для этих скриншотов? Сразу несколько.
Во-первых, видно, что все пакеты начинаются либо с 0x48, либо с 0x58, либо с 0x78; какой-нибудь закономерности на этот счёт я ещё не уловил, кроме того, что пакеты с уже известной функцией свой значащий байт не меняют.
Во-вторых, почти в каждом пакете есть один или несколько счётчиков сообщений; например, в keep-alive и ответах на них этим занимается третий и четвёртый байт в заголовке, кроме того сам пакет содержит ещё счётчик сообщений общий (включая keep-alive) и какой-то специфический (считающий пакеты без учёта количества keep-alive); всё это имеет отношение к контролю доставки пакетов, который пришлось прикрутить к UDP, вероятно, для оценки потерь и пересылки BLOBов (об этом позже).
Размеры всех пакетов выравнены по границам 8 байт, что ненавязчиво указывает нам на размер блока всё того же BlowFish; пока я до этого догадался, прошло немало времени в попытках обьяснить странную «контрольную сумму» в конце, да ещё и переменной длины. В конце концов, получив в этом паддинге вместо простого мусора слово «Flags» я, наконец, прозрел.
Ну и в лучших хакерских традициях, в конце каждого пакета находится сигнатура мёртвой говядины; кто бы мог подумать где мы её найдём 🙂
После получения Session ID от сервера приезжает пакет, содержащий номер игрока в неожиданно текстовом формате (792067). А вот пакет, который начинается на 0x78 0x00 на первом скриншоте — особо интересен. Сочетание сигнатуры 0x80 0x20 вкупе с тем, что перед каждым строковым литералом в нём стоит 0x55 и байт длины строки, а после каждого 0x71 находится возрастающий номер, должно насторожить опытных питонщиков — это же, чёрт побери, Python Pickle со своим запихиванием всего подряд в мемо! Вот он такой:
В следующей части, если она заинтересует уважаемых обитателей Хабра, я расскажу о том, как в протоколе WOT передаются файлы, размеры которых намного больше реалистичного размера UDP пакета и MTU. И о том, что эти файлы оказывается сжатыми zlib’ом а внутри у них всё тот же Python Pickle с разными неожиданными вещами.
Спасибо за внимание!
UPD. Свежие новости! По агентурным данным из самого сердца КВГ, мой лёгкий намёк на потенциал коммерческого использования командирского планшета поднял «небольшой бугурт» (дословно), в результате чего кровавые модераторы в полнейшей панике наконец заметили и слили в мусорник тему проекта на официальном форуме танков, а мне было доверительным шёпотом посоветовано замылить данные своего аккаунта на скриншотах.
Я из Wargaming: что значит быть программистом?
Иван Петроченко, глава отдела разработки движка World of Tanks Blitz
Как начинали?
Делать игры мечтал с детства. По образованию я эколог. До этого была школа с экологическим уклоном.
В индустрии я уже больше десяти лет. Попал в нее относительно легко: разместил резюме, через день позвонили и позвали «разрабатывать под мобилки» в небольшую, известную в узких кругах компанию Incubus. Ничего удивительного — в 2004 году в Минске игроделов можно было по пальцам пересчитать и отечественный геймдев был в зачаточном состоянии. Со временем, конечно, ситуация поменялась.
Вторым местом работы стала TikGames. По меркам того времени это был уже игрок покрупнее и гораздо известнее — в компании успела поработать приличная часть моих нынешних коллег 😉
Затем была Dava Consulting, которая впоследствии вошла в состав «Гейм Стрим». Так в моей жизни появился World of Tanks Blitz.
Мне всегда нравилось делать игры. К этому лежит душа. Писать код для скучных приложений, наверное, не смог бы.
С чем работаете?
Платформа у нас не одна. Это и iOS, и Android, и Windows 10. Недавно добавилась Mac OS. Что касается языка, то это классика геймдева — всеми любимый C++. Это основа основ и 95% всей работы. Конечно, есть и другие скрипты, которые используются для автоматизации (Python и так далее).
Софт — Visual Studio для Windows, Xcode для Mac и iOS. C Android уже сложнее. Капризная платформа диктует свои правила. Используем то, что удобнее всего, однако идеальный софт еще не нашли.
А какое образование нужно?
Я, наверное, в очередной раз повторю то, что все и так знают. Чтобы создавать первоклассные игры, необязательно иметь три диплома и курсы разработчика за плечами. У нас работают как самоучки, превратившие сырой талант в блестящие результаты, так и те, кто целенаправленно планировал идти в индустрию еще на этапе получения образования.
Хороший геймдев-разработчик должен быть экспертом во многих областях. Современные игры даже среднего уровня основываются на большом количестве технологий (если не брать в счет проекты на высокоуровневых движках, например, на Unity). Нужно хорошо владеть теоретической частью (структура данных, алгоритмы), разбираться в трехмерной графике, знать особенности операционных систем (в случае World of Tanks Blitz их много, так как игра кросс-платформенная).
Это как с иностранными языками — чем больше ты языков знаешь, тем легче тебе даются новые. Если ты освоил 10 технологий, вероятнее всего, с 11-й сложностей не будет.
Известны случаи, когда в программирование приходили прямиком из строителей. Да, и такое бывает. Однако отмечу, что лучше начинать до 30 лет. Чем раньше, тем лучше. Слишком много специфики и нюансов, которые надо охватить. На это нужно время.
Что важно?
Если программист умеет быстро разбираться с незнакомыми технологиями, то он хороший специалист. В этой сфере очень высоко ценится способность адаптироваться. Это архиважно. Безусловно, основа (С++) постоянна. Однако нюансы меняются из года в год. Появляются новые стандарты, что хорошо видно на выставках и конференциях, где демонстрируются достижения мировой IT-индустрии.
Как только ты перестал развиваться, ты дрейфуешь где-то на среднем уровне, несмотря на наличие опыта. Консервация — это плохо. Необязательно посещать все специализированные мероприятия и не пропускать ни одной конференции. Это нужно, скорее, чтобы прочувствовать атмосферу и вдохновиться. Своеобразная моральная подпитка. Учиться и углублять знания можно не выходя из дома. Есть интернет с огромным количеством литературы, технических блогов, лекций.
Сейчас на самом деле передовое время. Та теория, которая была разработана 30–40 лет назад, находит отклик в аппаратных возможностях современных технологий. Появилась возможность реализовать то, что было придумано на бумаге.
Английский?
Без английского в программировании никуда. Вся полезная литература, весь «свежак», новейшие материалы выходят, к сожалению, не на русском. Но никто не говорит, что нужен продвинутый уровень владения языком. Достаточно понимать. Мне сложно представить программиста, не знающего хотя бы азов английского. Разве что специалисты по 1С, где нужно писать кириллицей.
Это скучно?
Нет. Программист — это не тот человек, который сидит и тихонько пишет код. Он придумывает. Особенно если мы говорим об игровой индустрии. Другое дело —проект какой-нибудь банковской системы: когда человек приходит на работу, ему дают программу, которую до него писали десять лет, и он продолжает над ней трудиться, минимально меняя код. Это беспощадная рутина. То же самое и с бухгалтерией — здесь по большому счету нечего изобретать.
В геймдеве динамика намного выше. Во-первых, редко когда игра существует в первозданном виде пять или более лет. Те же «Танки» постоянно обновляются.
А как в Беларуси?
Можно выучиться на гейм-дизайнера в университете (БГУИР) или закончить курсы, которых появляется все больше и больше. Однако огромную роль играет самообразование: интернета хватит с лихвой, надо просто захотеть. Когда приходят резюме, я даже не смотрю на пункт «Образование». Диплом есть почти у всех, ценится опыт и собственные проекты. Недавно на собеседование приходил кандидат, недавний выпускник, который написал свой игровой движок. Он показал, как все работает, объяснил механику. Вижу ли я в нем достойного специалиста в будущем? Конечно. Сразу понятно, что человек интересовался этим с детства, получил хорошие знания в интернете и будет развиваться.
Кого берете?
Людей с техническим складом ума, которые умеют решать новые задачи. Человека, который пришел с опытом работы в геймдеве, видно за версту — диалог выстраивается сам собой и идет по накатанной. Новичка в индустрии разговорить уже сложнее.
«Джуниору» к нам попасть сложно. Команда уже сформирована, необходимости в расширении у нас нет. Нужны люди, которые смогут углубить экспертизу.
Бывает, что в резюме написано одно, а при личной встрече оказывается, что это неправда. Преувеличено, присвоено и так далее. Это всегда узнается.
С чего начать?
Тому, кто очень хочет не только в программирование, но в IT в принципе, лучше начинать с техподдержки. А еще лучше — с QA (знаю реальные примеры). Это бывает, когда есть желание и соответствующий склад ума, но не хватает технической подкованности. Два-три года работы в индустрии в поддержке или тестировании обычно устраняют пробелы.
Совет молодым?
Посоветую никогда не забрасывать профессиональное развитие. Инструментов для поддержания хорошей формы хватает. Для ленивых: существуют сайты, где все представлено в легкой и увлекательной форме. Допустим, есть игра, к которой нужно написать искусственный интеллект. Результатом можно очень сильно вдохновиться.
Три причины, по которым мне пришлось бросить игру World of Tanks и в чем суть патента В. Кислого
реклама
Игроком игры World of Tanks я явлюсь с 2012 года, вернее уже являлся, видел, так сказать воочию, как игра менялась на протяжении девяти лет. И на мой взгляд игра изменилась только к худшему, причем за последние года просто катастрофическими темпами. В какой-то момент играть в нее стало просто невозможно, чаша терпения переполнилась, и я решил бросить эту игру. Расскажу про причины, которые побудили меня это сделать.
1. Патент Виктора Кислого и Ивана Михневича.
Суть этого патента заключается в так называемой «поддержке интереса к игре». Как всегда, компании Wargaming мало прибыли, которую они имеют, и хочется еще большего. И эта технология призвана, не допустить ухода игроков из игры и повысить доходы компании. Она напрямую определяет алгоритмы игры, правила баланса, пробитий, промахов, рикошетов и т.д., и случайности здесь нет никакой. Помогая этим одним игрокам, и угнетая других, тем самым стирая разницу в игре между игроками, которые плохо играют, например, только начали играть, и опытными игроками. По мнению Wargaming здесь все логично, игрокам не нравится постоянно выигрывать в легких боях или постоянно проигрывать. Если опытные игроки попадают в бой с неопытными новичками, то новички разочаруются, а опытным игрокам станет скучно, и они оба могут бросить игру. Статистика игроков не должна сильно различаться, не должно быть побед у одних игроков 90 %, а у других 40%.
2. Жадность компании Wargaming
Повторюсь, что я являюсь игроком этой игры с девяти летним стажем. И помню те времена, когда игра была размеренной, новая прокачиваемая и премиальная техника выходила с периодичностью позволяющей игрокам понять эту технику, изучить ее, привыкнуть к ней. Хоть как то поддерживалась историчность игры, не было этой несуразной, не имеющей к историчности никакого отношения, колесной и некоторой другой техники. Не нерфили, и не апали технику в интересах Wargaming так беспардонно и бесцеремонно, как сейчас. Wargaming раньше жил с перспективой на будущее, думал о последствиях, к которым могут привести его действия и решения. А сейчас у меня сложилось такое впечатление, что Wargaming живет только сегодняшним днем, заботясь только о сегодняшних сверхдоходах, вовлекая World of Tanks в полный игровой хаос. Как будто завтрашнего дня уже не наступит, и весь куш нужно срубить именно сегодня. Но завтрашний день неминуемо наступает, и чтобы опять срубить по максимуму, игру ввергают в еще больший хаос, и так дальше происходит падение в пропасть хаоса и безумия.
реклама
Или еще другой вариант как вынудить игроков донатить. Выпустить новый премиальный танк, например тяжелый танк Crysler K GF (яркий пример нагиба за деньги), который практически не имеет в броне слабых мест, а в лоб так вообще бронебойными снарядами не пробивается. И только при использовании подкалиберных (голдовых) снарядов появляется шанс с ним справиться, тем самым совсем ненавязчиво подталкивая игроков покупать за реальные деньги голдовые снаряды, ведь не у всех имеется много игрового серебра для их покупки. И у самого Crysler K GF «запилено» суперпробитие на голдовых снарядах, хотя пушка такая же, как и у Т32, но пробитие при использовании голдовых снарядов значительно выше. Что и подталкивает лишний раз их владельцев на покупку голды за реальные деньги. Опытные игроки начавшие играть давно, видя, как сейчас, некогда культовая игра, просто катится в пропасть хаоса и безумия просто уходят из нее навсегда. А новички, на которых Wargaming делает ставку, всячески заманивая их в игру, немного покуражатся и все равно уйдут из нее, потому что без опытных игроков игра будет неинтересна.
3. Читы (запрещенные модификации) в игре
Читы – это официально запрещенные модификации, которые тем или иным способом дают значительное преимущество игроку в бою перед другими игроками.
реклама
Или еще пример, остаюсь я в конце боя наедине с одним или двумя противниками, и не знаю их место нахождения. Так находятся союзники, которые начинают мне подсказывать место положения врага, и действительно он оказывается там. Как они это узнают, да очень просто, используют чит «поваленные деревья и разрушенные объекты на миникарте», который на миникарте отображает условными знаками эти места.
реклама
Можно конечно и дальше очень долго продолжать приводить разные примеры использования игроками читов, с которыми я лично сталкивался в боях, но думаю для понимания масштабности катастрофы в игре World of Tanks этого достаточно.
Скачиваются и устанавливаются читы вообще, без каких либо проблем, и это вызывает у меня большое разочарование в этой игре.
По моему мнению, точка невозврата игрой World of Tanks уже пройдена, и вернуть ей ту прежнюю популярность и любовь игроков уже невозможно.
Надеюсь, статья для вас была интересна, и вы сделаете правильный выбор игры для себя.
Пишите в комментариях, часто ли вы сталкивались в игре со случаями читерства, и что думаете о дальнейшей судьбе игры World of Tanks.
Почему первым языком программирования должен быть Python?
Профессия программиста становиться все более популярной. Это не только шанс получить высокооплачиваемую работу, зарабатывать достойные деньги на фрилансе, но и интересное, увлекательное занятие.
Как правило, человек, который решил освоить программирование «с нуля» становиться перед выбором «Какой язык программирования учить?».
Если, Вы четко знаете в какой области хотите применять в будущем свои знания (Web, создание игр, программирование под Android и т.п.), то можно воспользоваться инфографикой, с которой, уверен, многие уже знакомы.
Как видите, самый часто упоминаемый язык на этой инфографике — Python. И это вполне оправдано, поскольку Python является, действительно, простым языком, а программировать на нем — сплошное удовольствие. Свою первую программу Вы напишите в течении первых часов изучения этого языка.
Перечислять все достоинства этого языка я не буду, поскольку, это уже делалось многими авторами неоднократно. Назову лишь несколько, на мой взгляд, наиболее ценных особенностей Python для начинающего программиста.
— Простота. Это достоинство Python наиболее важно для начинающих программистов.
— Скорость разработки. Вы с легкостью сможете решать повседневные задачи не затрачивая большого количества времени. Для начинающего программиста важно видеть результаты своего обучения в виде готовой к использованию программы. Это мотивирует на дальнейшее изучение. Например, классический «Hello world» в Python выглядит следующим образом:
Для сравнения, посмотрим, как выглядит тот же «Hello world» на суперпопулярном языке Java:
class HelloWorld <
public static void main(String[] args) <
System.out.println(«Hello World!»);
>
>
— Широкие возможности использования языка Python. Благодаря огромному количеству библиотек, модулей и фреймворков, с помощью Python можно решать практически любые задачи.
Программы для ежедневного использования, в которых применяется Python: графический редактор GIMP, программа для работы с трехмерной графикой Blender, BitTorrent. Популярная игра World of Tanks написана с применением Python. Такие компании как Яндекс, Google, Instagram, Dropbox и др. используют Python.
Востребованность языка и уровень зарплат можно оценить, например, с помощью крупнейшего сайта вакансий и резюме HeadHunter http://hh.ua/. Введите в поиске на сайте запросы вида «Python developer», «python junior», «python django», и убедитесь в том, что Python востребован и высокооплачиваем.
В следующих постах, рассмотрим обучающую литературу по Python, а также полезные ресурсы, для закрепления навыков программирования.