исходный код world of tanks
Исходный код world of tanks
It’s the full source code of the site (and related tools) WotClans. It tracks the performance of clan players on the World of Tanks (for consoles) game, by Wargaming.
To understand the choosen architeture it’s relevant to understand some of the history of the site, and the costs constraints that were applied everywhere.
The site started because I wanted to easily track my performance, and of my some of my clan, without entering the pages on WoTInfo to every player.
I setup an agreement with Stan (WoTInfo owner) that kindly allowed me to query their pages, and I did so for many years. You can still find code that parses his pages, altought I now calculate my own WN8 values.
The other major constraint for the site was cost of running it. I live in Brazil, and altought (for my country standards) I’m rich enough to dedicate my time to the site, and foot the bill, I can’t pay much for hosting, even on Amazon or Azure. So I payed for the cheapest hosting I could find, on SmarterASP.
Their service, despise being cheap, is very good. But this site needs a lot of database and some continuing running proccesses, and that makes it not cheap.
But it happens that I own a (small!) company in Brazil and, with the agreement of my partners, I started to use spare CPU time and Database space on our backup server.
So, the basic was configured: On my own servers I keep the main database, and the data collector and calculations proccesses; and on the remote site I keep only static files containing the data to be displayed.
Latter, when I started to compute my own WN8, I had to use a database on the remote server to keep the player data, as it would be a problem keep more than 50k files on the file system.
The site, now, is not so cheap to run, but thanks to the great support of the community I’m receiving donations enought to cover most of the hosting costs.
It holds everything!
I will soon(tm) provide a link to the daily backups and some explanation on it.
It’s just a key store from the player ID to a compressed json that represents overall, last month and last week data for the player.
It’s updated by the FetchPlayers (and the WotClansBot, sometimes) by using an administrative API on the site.
Why not? Altought this is more like a «full disclosure» iniciative more than giving away control of the project, feel free to contact me. There are a few places that I would love to have some help:
Can I copy your project, database, and open up my version of it with beer, hookers and ads?
Sure! By all means! It’s MIT licensed.
There are comments in Spanish on the code!
Actually they are in Portuguese, my usual language. They will be translated, eventually.
Your code sucks! Will you improve it?
Nah! It has a purpose, a reason, and works very fine giving the constraints of cost in running and maintening the site. But of course I will improve it, and suggestions on how to inprove, refactor and so on are wellcome.
I love you! Thanks! Can I use snippets of your code?
I love you too! And sure, You can!
About
The source code for the World of Tanks Console Site and Discord Bot
Разбор протокола 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. Свежие новости! По агентурным данным из самого сердца КВГ, мой лёгкий намёк на потенциал коммерческого использования командирского планшета поднял «небольшой бугурт» (дословно), в результате чего кровавые модераторы в полнейшей панике наконец заметили и слили в мусорник тему проекта на официальном форуме танков, а мне было доверительным шёпотом посоветовано замылить данные своего аккаунта на скриншотах.
Пакеты модов
version 0.4, 2017-05-04
Содержание
Общая информация
Структура пакета
Пакет представляет собой zip-архив со следующими свойствами:
Внимание: архивы с компрессией в текущей версии World of Tanks не поддерживаются, поэтому, при создании архивов необходимо установливать опцию «уровень сжатия» в значение «без сжатия».
Внутри себя пакет содержит:
Пример структуры пакета:
Установка пакета
При необходимости, пакеты могут быть организованы в подкаталоги, что позволяет авторам сборок модификаций выполнять группировку файлов:
Рекомендации по именованию пакетов
Для имени пакета (в дальнейшем package_id ) рекомендована следующая схема формирования:
( com.example ) или же просто его никнеймом ( noname )
Данное имя используется в файле meta.xml (смотрите раздел 5), а также как часть имени файла пакета.
Пример имён пакетов:
Имя файла пакета формируется следующим образом:
Файл метаданных meta.xml
Необязательный файл meta.xml содержит опциональные поля, описывающие модификацию.
Пример заполнения:
New cool Crosshair with feature1. N
Значения из полей и используются для определения порядка монтирования пакетов. Значения полей и в будущем будут использоваться в системе управления модификациями.
Загрузка пакетов
Порядок загрузки
Внимание: в данный момент использование файла load_orders.xml затруднено (смотрите раздел 9.4).
Совместное использование пакетов и res_mods
С точки зрения клиента игры, корень виртуальной системы формируется из:
Пути указаны в порядке уменьшения приоритета. То есть, файлы из /res_mods/ / имеют наивысший приоритет вне зависимости от содержания load_order.xml
Разрешение конфликтов при загрузке
В общем случае, система пакетов не допускает ситуации, когда в каталоге res/ внутри разных пакетов находятся одинаковые файлы. Такая ситуация cчитается конфликтом.
Для управления обработкой конфликтов можно использовать:
Пакеты, перечисленные в этом файле, не считаются конфликтующими и загружаются без анализа на пересечение имен файлов.
Версии пакетов сравниваются посимвольно согласно таблице ASCII. Поведение совпадает с функцией strcmp():
Исполнение Python-кода
Рекомендованные пути для файлов модификаций
Файлы конфигурации
Для хранения файлов конфигурации модификаций рекомендованно использовать путь
Файлы журналов
Временные файлы
Для хранения временных файлов модификации рекомендованно использовать следующий путь:
Иные файлы модификации
Для хранения внутри пакета контента, к которому необходимо получить доступ из клиента игры, рекомендованно использовать следующий путь:
Работа с файлами внутри пакетов
Типовые операции
Чтение файла из пакета
def read_file(vfs_path, read_as_binary=True):
vfs_file = ResMgr.openSection(vfs_path) if vfs_file is not None and ResMgr.isFile(vfs_path): if read_as_binary: return str(vfs_file.asBinary) else: return str(vfs_file.asString) return None
Получение списка элементов в каталоге
result = [] folder = ResMgr.openSection(vfs_directory)
if folder is not None and ResMgr.isDir(vfs_directory): for name in folder.keys(): if name not in result: result.append(name)
return sorted(result)
Копирование файла из пакета в каталог
import os import ResMgr
def file_copy(vfs_from, realfs_to)
realfs_directory = os.path.dirname(realfs_to) if not os.path.exists(realfs_directory): os.makedirs(realfs_directory)
vfs_data = file_read(vfs_from) #смотрите 8.1.1 if vfs_data: with open(realfs_to, ‘wb’) as realfs_file: realfs_file.write(vfs_data)
Известные проблемы
Регистрозависимость имён файлов
На данный момент, при монтировании файлов в виртуальную файловую систему:
Использовать для /res_mods только имена файлов и каталогов в нижнем регистре.
Работа с файлами GNU Gettext
В качестве временного решения, вы можете использовать пакет net.openwg.vfsgettext :
Переопределение порядка монтирования пакетов
Временное решение Нет известного решения. Решение ожидается в скором времени.
Рабочие бонус коды и промо коды на сентябрь 2021 World of Tanks бесплатно
Промо-коды и бонусы для WoT на сентябрь 2021
Бонусы для игры World of Tanks в сентябре 2021 года раздает официальная компания Wargaming или ее партнеры с целью завлечения новых игроков. Некоторые бонусы поощряют активный гейминг уже старый игроков. Коды всегда бесплатны и не требуют ничего взамен. У поклонника WoT есть отличный шанс получить игровую валюту, классный танк или другие подарки абсолютно легально и бесплатно.
Большинство из действующих бонусов помогают новичкам влиться в игровую систему и начать побеждать. Но другим геймерам не стоит отчаиваться, ведь для них тоже есть коды, благодаря которым есть шанс получить топовую технику. Не стоит забывать и про премиум аккаунты. Благодаря ему танкист начнет зарабатывать больше золота и серебра за матчи, следовательно, продвижение по игре будет происходить быстрее.
Бонусы для новичков в сентябре 2021 года
Большинство кодов было выпущено Wargaming с целью привлечения в игру новых танкистов. Ведь геймеру будет приятнее выходить в бой если он точно будет знать, что его ожидает приятная награда. Те бонусы, которые будут описаны ниже, подходят только для новых игроков. Зарегистрированные аккаунты не могут воспользоваться ими. Но любой из опытных игроков может создать для себя второй профиль, чтобы воспользоваться приятным бонусом.
Ни в коем случае нельзя забывать про инвайт ссылки. С помощью них геймер получит не только долгожданный приз, но и приятный бонус в виде внутриигровой валюты. Далее будут описаны лучшие бонус-коды на сентябрь 2021 года.
За активацию игрок получает 4 классных танка и 400 тысяч серебра. С таким кодом практически не останется недовольных игроков, ведь каждый из них получит то, что ему надо.
Данный бонус-код активирован достаточно давно и пока что не собирается пропадать. С помощью него в игру пришли тысячи новых танкистов. У многих сложилось мнение, что компания Варгейминг просто забыла о его существовании. Но они могут вспомнить и аннулировать предложение, поэтому спешите воспользоваться кодом.
За ввод кода игрок получит хороший стартовый набор для выхода в бой. Главной особенностью считается советский танк третьего уровня Т-127, который останется у геймера навсегда. Данная машина не славится хорошими характеристиками, но при этом уважается среди игроков World of Tanks. На первых уровнях танкист точно будет одерживать победу над врагами.
Но и это далеко не все бонусы. Новичок получит доступ к 4 классным танкам вместе с экипажем. Вот их названия:
Но стоит отметить, что на каждой из этих машин можно покататься не более 10 боев.
Стандартный код, которых очень много. За его активацию новичок получит танк T2 Лайт, неделю премиум аккаунта и 500 золотых монет. Последние можно потратить на любые вещи во внутриигровом магазине.
Еще по названию можно понять, что данный код изначально предназначался для совсем другой игры от той же компании. Но приятный бонус за его активацию получат и игроки WoT. Им выдадут недельный премиум аккаунт.
Как правильно активировать бонусы во время регистрации
Это сделать максимально просто. Для начала новичку необходимо пройти по инвайт ссылке. После данного действия откроется окно, где необходимо создать свой аккаунт. На этом этапе игрок должен ввести почтовый ящик, придумать пароль и ник. Немного ниже имеется поле для ввода кода. Именно туда его необходимо скопировать. Не стоит записывать его вручную, так как высок риск ошибиться и не получить бонусы.
Все подарки за ввод кода игрок получит при первой авторизации.
Бонус-коды для действующих игроков
Постоянных игроков также необходимо поддерживать и проявлять дополнительный интерес к игре. Именно поэтому для них были созданы другие бонусы. В начале осени 2021 года каждый игрок может воспользоваться кодами от официального представителя или партнеров. Если выбор пал на второй вариант, то перед открытием бонуса нужно сделать что-то на сайте партнера. Чаще всего это покупки товаров, оформление подписок или подключение дополнительных услуг.
Существуют и многоразовые бонусные коды. Их можно активировать по несколько раз. Бонусы там будут небольшие, но зато очень приятные.
Постоянные игроки в сентябре 2021 года могут активировать следующие коды:
Но и это еще далеко не все. Геймеры могут ввести эти коды, чтобы получить приятные бонусы:
За его активацию геймеры получат в аренду топовый шведский танк Lansen C. Она дается на 3 дня, но зато без ограничения по количествам боев. Геймер может кататься на танке на протяжении 24 часов. Дополнительно будет активирован премиум аккаунт на 3 дня, чтобы опробовать новый танк было веселее.
У игрока появляется возможность бесплатно заполучить средний танк T2 Light и неделю премиума. Если же у геймера в ангаре имеется такая машина, то она автоматически конвертируется при активации кода в 750 золотых монет. Это идет своеобразная компенсация за повторение, так как два одинаковых танка никому не нужны.
На данный момент все перечисленные коды активны и их не собирают аннулировать. За них можно получить хорошие танки, голду или премиум доступ на несколько дней или неделю. Но не стоит затягивать с активацией, так как со временем они могут стать недоступны.
Активация бонусы для старого игрока: как это сделать
Для этого игроку необходимо перейти на официальный сайт Wargaming и ввести свой пароль с логином. После этого он попадет в личный кабинет WoT. Далее нужно нажать один раз на свой никнейм, после чего появится поле «Активировать код». Именно оно и нужно. Копируйте в него желаемый код, нажимайте на кнопку подтверждения и наслаждайтесь приятными бонусами в любимой игре.
Подарки от World of Tanks каждый месяц
О такой фишке знают далеко не все, но она имеет место быть. Дело в том, что Варгейминг каждый месяц дает подарки активным игрокам или тем, кто давно не заходил в свой профиль. Бонусы можно получать ежемесячно в один и тот же день. Например, первый подарок был забран 12 июня, следовательно, следующий появится 12 июля.
Как получить такой бонус
Для получения заслуженных подарков нужно перейти по ссылке https://worldoftanks.ru/prizebox/ru/. Игрок окажется на главной странице с призами, где большими буквами написано слово «К подаркам». Кликаем по нему. Далее нужно выбрать тот приз, который подходит именно к вашему статусу. Бонусы доступны для новичков и про.
Для опытных игроков в сентябре 2021 года ввели пятикратный опыт с техники, и возможность получить приятные бонусы при покупке внутриигровой валюты. Всего нужно задонатить на сумму от 7 долларов.
Бонусы – это отличая возможность вернуть былой интерес к игре. Особенно актуальными коды становятся для новичков, которые только-только ступают в игровой мир World of Tanks. Они смогут получить топовую технику уже с самого старта, что является большим плюсом.