Как разобрать сетевой протокол мобильной MMORPG
За годы игры в одну мобильную ММОRPG у меня накопился некоторый опыт по ее реверс-инжинирингу, которым я хотел бы поделиться в цикле статей. Примерные темы:
- Разбор формата сообщений между сервером и клиентом.
- Написание прослушивающего приложения для просмотра трафика игры в удобном виде.
- Перехват трафика и его модификация при помощи не-HTTP прокси-сервера.
- Первые шаги к собственному («пиратскому») серверу.
Требуемые инструменты
Для возможности повторения шагов, описанных ниже, потребуются:
- ПК (я делал на Windows 7/10, но MacOS тоже может подойти, если пункты ниже там доступны);
- Wireshark для анализа пакетов;
- 010Editor для парсинга пакетов по шаблону (не обязательно, но позволяет быстро и легко описывать формат сообщений);
- само мобильное устройство с игрой.
Разбор формата сообщений между сервером и клиентом
Для начала, нам необходимо видеть трафик мобильного устройства. Сделать это достаточно просто (хотя я очень долго доходил до этого очевидного решения): на нашем ПК создаем точку доступа Wi-Fi, подключаемся к ней с мобильного устройства, выбираем в Wireshark нужный интерфейс — и весь мобильный трафик у нас перед глазами.
Зайдя в игру и подождав некоторое время, чтобы запросы, не связанные с самим игровым сервером, прекратились, можно наблюдать следующую картину:
На данном этапе мы уже можем использовать фильтры Wireshark, чтобы видеть только пакеты между игрой и сервером, а также только с полезной нагрузкой:
tcp && tcp.payload && tcp.port == 44325
Если встать в тихом месте, вдали от других игроков и NPC, и ничего не делать, можно увидеть постоянно повторяющиеся сообщения от сервера и клиента (размером 76 и 84 байт соответственно). В моем случае минимальное количество разнообразных пакетов посылалось на экране выбора персонажа.
Периодичность запроса от клиента очень похожа на пингование. Возьмем несколько сообщений для проверки (3 группы, сверху — запрос с клиента, под ним — ответ сервера):
Первым делом бросается в глаза идентичность пакетов. 8 дополнительных байт у ответа при переводе в десятичную систему очень похожи на метку времени в секундах: 5CD008F816 = 155713765610 (из первой пары). Сверяем часы — да, так и есть. Предыдущие 4 байта совпадают с последними 4 байтами в запросе. При переводе получаем: A4BB16 = 4217110 , что также очень похоже на время, но уже в милисекундах. Оно примерно совпадает со временем с момента запуска игры, и скорее всего так и есть.
Осталось рассмотреть первые 6 байт запроса и ответа. Легко заметить зависимость значения первых четырех байт сообщения (назовем этот параметр L ) от размера сообщения: ответ от сервера больше на 8 байт, значение L тоже увеличилось на 8, однако размер пакета больше на 6 байт значения L в обоих случаях. Также можно заметить что два байта после L сохраняют свое значение как в запросах от клиента, так и от сервера, а учитывая, что их значение отличается на один, можно с уверенностью сказать, что это код сообщения C (связанные коды сообщений скорее всего будут определены последовательно). Общая структура понятна достаточно, чтобы написать минимальный шаблон для 010Editor:
- первые 4 байта — L — размер полезной нагрузки сообщения;
- следующие 2 байта — C — код сообщения;
- сама полезная нагрузка.
struct Event < uint payload_length ; ushort event_code ; byte payload[payload_length] ; >;
Значит, формат сообщения пинга клиента: послать локальное время пинга; формат ответа сервера: послать то же время и время отправки ответа в секундах. Вроде не сложно, да?
Попробуем разобрать пример посложнее. Стоя в тихом месте и спрятав пакеты пинга, можно найти сообщения телепорта и создания предмета (craft). Начнем с первого. Владея данными игры я знал какое значение точки телепорта искать. Для тестов я использовал точки со значениями 0x2B , 0x67 , 0x6B и 0x1AF . Сравним со значениями в сообщениях: 0x2B , 0x67 , 0x6B и 0x3AF :
Непорядок. Видны две проблемы:
- значения не 4-х байтовые, а разного размера;
- не все значения совпадают с данными из файлов, причем в данном случае разница равна 128.
- непонятное 0x08 перед ожидаемым значением;
- 4-х байтовое значение, на 4 меньшее L (назовем его D . Это поле появляется далеко не во всех сообщениях, что немного странно, но там, где оно есть, зависимость L — 4 = D сохраняется. С одной стороны, для сообщений с простой структурой (как пинг) оно не требуется, но с другой — выглядит оно бесполезным).
Ожидаемые значения 14183 и 14285 тоже не соответствуют действительным 28391 и 28621, но разница тут уже намного больше 128. Проведя много тестов (в том числе и с другими типами сообщений) выяснилось, что чем больше ожидаемое число, тем больше разница между значением в пакете. Что было странно, так это то, что значения до 128 оставались сами собой. Поняли, в чем дело? Очевидная ситуация для тех, кто уже сталкивался с этим, а мне, по незнанию, пришлось два дня разбирать этот «шифр» (в конечном итоге во «взломе» помог анализ значений в бинарном виде). Описанное выше поведение называется Variable Length Quantity (значение переменной длины) — представление числа, в котором используется неопределенное количество байт, где восьмой бит байта (бит продолжения) определяет наличие следующего байта. Из описания очевидно, что чтение VLQ возможно только в порядке Little-Endian. По совпадению все значения в пакетах в таком порядке.
Теперь, когда мы знаем как получить исходное значение, можно написать шаблон для типа:
struct VLQ < local char size = 1; while(true) < byte obf_byte; if ((obf_byte & 0x80) == 0x80) < size++; >else < break; >> FSeek(FTell() - size); byte bytes[size]; local uint64 _ = FromVLQ(bytes, size); >;
И функцию преобразования массива байтов в целочисленное значение:
uint64 FromVLQ(byte bytes[], char size) < local uint64 source = 0; local int i = 0; local byte x; for (i = 0; i < size; i++) < x = bytes[i]; source |= (x & 0x7F) * Pow(2, i * 7); // Бинарный сдвиг > return source; >;
Но вернемся к созданию предмета. Опять появляется D и снова 0x08 перед меняющимся значением. Последние два байта сообщения 0x10 0x01 подозрительно похожи на количество предметов крафта, где 0x10 имеет роль, схожую с 0x08 , но по-прежнему непонятную. Зато теперь можно написать шаблон для этого события:
struct CraftEvent < uint data_length ; byte marker1; VLQ craft_id ; byte marker2; VLQ quantity ; >;
Который будет выглядеть вот так:
И все равно это были простые примеры. Посложнее будет разобрать событие движения персонажа. Какую информацию мы ожидаем увидеть? Как минимум координаты персонажа, куда он смотрит, скорость движения и состояние (стоит, бежит, прыгает и т.д.). Так как строк в сообщении не видно, состояние, скорее всего, описывается через enum . Путем перебора вариантов, попутно сравнивая их с данными из файлов игры, а также через множество тестов, можно найти три XYZ вектора при помощи вот такого громоздкого шаблона:
struct MoveEvent < uint data_length ; byte marker; VLQ move_time ; FSkip(2); byte marker; float position_x ; byte marker; float position_y ; byte marker; float position_z ; FSkip(2); byte marker; float direction_x ; byte marker; float direction_y ; byte marker; float direction_z ; FSkip(2); byte marker; float speed_x ; byte marker; float speed_y ; byte marker; float speed_z ; byte marker; VLQ character_state ; >;
Зеленая тройка оказалась координатами местоположения, желтые тройки, скорее всего, показывают куда смотрит персонаж и вектор его скорости, а последнее одиночное — состояние персонажа. Можно заметить постоянные байты (маркеры) между значениями координат ( 0x0D перед значением X , 0x015 перед Y и 0x1D перед Z ) и перед состоянием ( 0x30 ), которые подозрительно похожи по смыслу на 0x08 и 0x10 . Проанализировав много маркеров из других событий оказалось, что он определяет тип следующего за ним значения (первыми тремя битами) и семантическмй смысл, т.е. в примере выше если поменять местами вектора, сохранив при этом их маркеры ( 0x120F перед координатами и т.д.), игра (теоретически) должна нормально распарсить сообщение. С учетом этой информации, можно добавить пару новых типов:
struct Packed < VLQ marker ; // Маркер тоже оказался VLQ! local uint size = marker.size; // Некоторые сообщения не содержат значения смещения (в списках, например) и там приходится использовать вот такой вычисленный размер структуры switch (marker._ & 0x7) < case 1: double v; size += 8; break; // Из анализа других событий case 5: float v; size += 4; break; default: VLQ v; size += v.size; break; >>; struct PackedVector3 < Packed marker ; Packed x ; Packed y ; Packed z ; >;
Теперь наш шаблон сообщения движения значительно сократился:
struct MoveEvent < uint data_length ; Packed move_time ; PackedVector3 position ; PackedVector3 direction ; PackedVector3 speed ; Packed state ; >;
Еще один тип, который может нам понадобиться в следующей статье, это строки, которым предшествует Packed -значение их размера:
struct PackedString < Packed length; char str[length.v._]; >;
Теперь, зная примерный формат сообщений, можно написать свое прослушивающее приложение для удобства фильтрации и анализа сообщений, но это уже тема для следующей статьи.
Upd: спасибо aml за подсказку, что описанная выше структура сообщений является Protocol Buffer, а также Tatikoma за ссылку на полезную соответствующую статью.
перехват TCP потока
перевожу сокет в режим получения всех пакетов в сети
sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
.
WSAIoctl(sock, SIO_RCVALL.
.
слушаю сокет, получаю ip пакеты. пакеты идущие с не нужного мне ip адреса/порта отбрасываю
далее необходимо реализовать tcp-стек. для этого использую уже готовый класс от безымянного автора
все работает. достаю из стека собранные пакеты, расшифровываю их, получаю нужную мне информацию
но в итоге столкнулся с проблемой, которую никак не могу побороть.
в случае если параллельно с работой сниффера я включаю к примеру закачку файла какого со скорость 100-2000 кб в секунду, то сниффер умирает. умирание заключается в следующем один или несколько пакетов от сервера каким-то образом теряются. не доходят то сокета(после долгих часов отладки пришел к такому выводу). тсп стек перестает собирать пакеты, буфер tcp пакетов в стеке заполняется до отказа, и происходит завершение работы программы.
и теперь собственно сами вопросы:
1. правильно ли я реализую перехват TCP потока? на сколько оправдан/неоправдан этот метод?
2. отчего может происходить пропуск пакета(ов) на сокете? наткнулся на информацию, что у каждого сокета есть некий буффер, в котором скапливаются несчитанные пакеты. подозреваю дело в этом буффере. можно ли его увеличить? информации по этому поводу к сожалению не нашел
пробовал повышать приоритет потока вплоть до realtime. результат был заметен — чтобы убить программу с потоком сниффера приоритета realtime надо гораздо сильнее нагрузить сеть
3. есть ли какие альтернативы реализации вручную tcp стека? можно ли было сделать как-то иначе?
4. стал пробовать переделывать с чистых сокетов на использование pcap библиотеки. но почитав документцию, посмотрев примеры понял что будет в принципе то же самое — настройка фильтра на перехват tcp пакетов, затем прогон всех пакетов через tcp-стек. или я не прав?
пожулуй все
спасибо за внимание
#1
16:01, 29 ноя 2006
Ну реализовывать tcp стек не надо.
Можно попробовать либу libpcap для перехвата.
#2
11:08, 30 ноя 2006
но как настроить фильтры pcap на перехват tcp потока? я пробовал примерно такой фильтр ставить, tcp && src port 45665
пакеты перехватываются, но опять же это лишь та же последовательность пакетов, которую я получаю через сокеты. и эти данные надо пропускать через tcp стек
как с помошью средствт pcap реализовать tcp-стек? может быть, я неправильный фильтр задаю? смотрел примеры к winpcap, искал в гугле информацию по этому поводу, ничего полезного не нахожу. может быть не то ищу?
#3
21:23, 30 ноя 2006
В данном случае проблема действительно в переполнении буфера приёма.
Правильное решение, гарантирующее отсутствие потерь пакетов:
Вклиниться между сервером и клиентом. Т.е. сначала пакет получает перехватчик, обрабатывает и только затем отдаёт клиенту. Если что-то потерялось, то сервер всё равно перешлёт заново, т.к. клиент тоже не получит этих пакетов и не подтвердит их приём.
Чтобы, что-то посоветовать, необходима информация о конфигурации сети. Клиент, сервер, перехватчик запущены на отдельных компах, или например клиент и перехватчик запущены на одном компе?
Простое решение увеличить размер буфера приёма у перехватчика:
Чревато тем, что если клиент константно обрабатывает пакеты от сервера быстрее чем перехватчик, то никакого буфера не хватит.
Увеличить буфер можно, например, через вызов WSARecv. Этой функции надо передавать НЕСКОЛЬКО структур WSABUF (dwBufferCount>1). Либо вызвать её несколько раз (сокеты естественно асинхронные). Вообщем смысл в том, что нужно не допускать ситуации, когда при обработке текущего пакета у сокетов нет буфера, куда читать следующий пакет. Т.е. пока читается (обрабатывается, анализируется) текущий пакет, в сокетах уже ожидает заполнения следующий буфер.
С WinPCap ситуация будет действительно аналогичная RAW сокетам.
#4
15:55, 1 дек 2006
Спасибо за ответ.
> Чтобы, что-то посоветовать, необходима информация о конфигурации сети. Клиент, сервер, перехватчик запущены на отдельных компах, или например клиент и перехватчик запущены на одном компе?
Сервер запущен в интернете. клиент и перехватчик запускаются на одной машине.
> Вклиниться между сервером и клиентом. Т.е. сначала пакет получает перехватчик, обрабатывает и только затем отдаёт клиенту.
Подскажите, каким образом можно организовать такую работу с сокетом?
> Простое решение увеличить размер буфера приёма у перехватчика:
Попробую так сделать.
> С WinPCap ситуация будет действительно аналогичная RAW сокетам.
В этом не уверен. В документации pcap написано, что настраиваемые фильтры pcap(фильтроваться будет по src ip и src port) работают быстрее, чем вызов recv для каждого постороннего udp и tcp пакета. Проверить еще не успел, на выходных обязательно выясню это.
#5
19:15, 1 дек 2006
moridin
>Подскажите, каким образом можно организовать такую работу с сокетом?
1. Использовать библиотеку WinpkFilter (http://www.ntndis.com/w&p.php?id=7) Масса примеров и документации.
Это позволит вклиниться между сетевой картой и приложением на самом низком уровне. Необходима реализация TCP стека.
2. Использовать Winsock Layered Service Provider (LSP).
http://www.microsoft.com/msj/0599/LayeredService/LayeredService.aspx
http://www.codeproject.com/useritems/Windows_WinSock2_LSP.asp
http://www.inf.tsu.ru/library/DiplomaWorks/CompScience/2006/ishina/diplom.pdf
Это позволит вклиниться непосредственно между клиентом и библиотекой сокетов. Т.е. перехватчик будет обрабатывать вызовы, например функции recv вызванной клиентом. Т.е. сначала результат recv получит перехватчик, а затем он отдаст результат клиенту. Реализация TCP стека не требуется.
4. Подменить ws2_32.dll своей вызывающей настоящую Ws2_32.dll.
5. Пропатчить exe клиента чтобы он линковался со специальной dll вместо Ws2_32.dll (модификация метода 4).
Короче многое можно на эту тему придумать.
Снифферы и не только. Выбираем инструмент для перехвата и анализа трафика
Анализ трафика — важнейший этап тестирования на проникновение (или даже взлома). В передаваемых по сети пакетах можно обнаружить много интересного, например пароли для доступа к разным ресурсам и другие ценные данные. Для перехвата и анализа трафика используются снифферы, которых человечество придумало великое множество. Сегодня мы поговорим о самых популярных снифферах под винду.
Теория
Чтобы перехватывать трафик, анализаторы могут использовать перенаправление пакетов или задействовать так называемый Promiscuous mode — «неразборчивый» режим работы сетевого адаптера, при котором отключается фильтрация и адаптер принимает все пакеты независимо от того, кому они адресованы. В обычной ситуации Ethernet-интерфейс фильтрует пакеты на канальном уровне. При такой фильтрации сетевая карта принимает только широковещательные запросы и пакеты, MAC-адрес в заголовке которых совпадает с ее собственным. В режиме Promiscuous все остальные пакеты не отбрасываются, что и позволяет снифферу перехватывать данные.
Теоретически можно собирать вообще все пакеты в сегменте локальной сети, где установлен сниффер, однако в этом случае данных для последующего анализа будет слишком много, да и файлы журналов быстро распухнут до совершенно неприличных размеров. А можно настроить приложение таким образом, чтобы оно отлавливало трафик только определенных протоколов (HTTP, POP3, IMAP, FTP, Telnet) или анализировало лишь первые 100 байт каждого пакета, где обычно и содержится самое интересное: адрес целевого хоста, логины и пароли. Современные снифферы могут слушать в том числе и зашифрованный трафик.
Нередко анализаторы трафика применяются в «мирных» целях — для диагностики сети, выявления и устранения неполадок, обнаружения вредоносного ПО или чтобы выяснить, чем заняты пользователи и какие сайты они посещают. Но именно при исследовании безопасности сетевого периметра или тестировании на проникновение сниффер — незаменимый инструмент для разведки и сбора данных. Существуют снифферы для различных операционных систем, кроме того, подобное ПО можно установить на роутере и исследовать весь проходящий через него трафик. Сегодня мы поговорим о наиболее распространенных популярных анализаторах трафика для платформы Microsoft Windows.
Wireshark
- Производитель: Wireshark Foundation
- Сайт:https://www.wireshark.org
- Лицензия: бесплатно
Об этой программе знает, наверное, каждый, кто хотя бы раз сталкивался с задачей анализа трафика. Популярность Wireshark вполне оправданна: во‑первых, данный продукт бесплатен, во‑вторых, его возможностей вполне хватает для решения самых насущных вопросов, касающихся перехвата и анализа передаваемых по сети данных. Продукт пользуется заслуженной популярностью у вирусных аналитиков, реверс‑инженеров, системных администраторов и, безусловно, пентестеров.
Этот анализатор имеет русскоязычный интерфейс, умеет работать с большим количеством сетевых протоколов (перечислять здесь их все лишено смысла: полный список можно найти на сайте производителя). В Wireshark можно разобрать каждый перехваченный пакет на части, просмотреть его заголовки и содержимое. У приложения очень удобный механизм навигации по пакетам, включая различные алгоритмы их поиска и фильтрации, есть мощный механизм сбора статистики. Сохраненные данные можно экспортировать в разные форматы, кроме того, существует возможность автоматизировать работу Wireshark с помощью скриптов на Lua и подключать дополнительные (даже разработанные самостоятельно) модули для разбора и анализа трафика.
Помимо Ethernet, сниффер умеет перехватывать трафик беспроводных сетей (стандарты 802.11 и протокол Bluetooth). Тулза позволяет анализировать трафик IP-телефонии и восстанавливать TCP-потоки, поддерживается анализ туннелированного трафика. Wireshark отлично справляется с задачей декодирования протоколов, но, чтобы понять результаты этого декодирования, надо, безусловно, хорошо разбираться в их структуре.
К недостаткам Wireshark можно отнести то, что восстановленные потоки не рассматриваются программой как единый буфер памяти, из‑за чего затруднена их последующая обработка. При анализе туннелированного трафика используется сразу несколько модулей разбора, и каждый последующий в окне программы замещает результат работы предыдущего — в итоге анализ трафика в многоуровневых туннелях становится невозможен.
В целом Wireshark — не просто популярный, но очень добротный продукт, позволяющий отследить содержимое гуляющих по сети пакетов, скорость их передачи, найти «проблемные места» в сетевой инфраструктуре. Но в отличие от коммерческих приложений здесь нет удобных инструментов визуализации. Кроме того, с помощью Wireshark не так уж и просто, например, выловить из трафика логины и пароли, а это одна из типичных задач при тестировании на проникновение.
CommView
- Производитель: TamoSoft
- Сайт:https://www.tamos.ru/products/commview/
- Лицензия: платный, покупка лицензии или подписка
Среди существующих ныне снифферов CommView — один из самых старых и заслуженных ветеранов, об этом продукте «Хакер» писал еще в 2001 году. Проект жив и по сей день, активно развивается и обновляется: последняя на текущий момент версия датирована 2020 годом. Несмотря на то что продукт платный, производитель предлагает скачать триал, который позволяет посмотреть работу приложения на практике — пробная версия сниффера перехватывает трафик в течение пяти минут, после чего просит денег.
Программа имеет русскоязычный интерфейс, что может стать определяющим фактором при выборе сниффера для пользователей, не владеющих английским. Главное преимущество CommView — возможность гибко настроить правила фильтрации пакетов: можно выбрать отдельные протоколы, которые будет отслеживать приложение, сортировать пакеты по ряду признаков, например по размеру или заголовку. Ассортимент поддерживаемых протоколов также весьма велик: сниффер умеет работать с самыми распространенными прикладными протоколами, а также выполнять реконструкцию TCP-сессии и UDP-потока. При этом CommView позволяет анализировать трафик вплоть до пакетов протоколов самого низкого уровня — TCP, UDP, ICMP, а также просматривать «сырые» данные. Программа показывает заголовки перехваченных пакетов, собирает подробную статистику IP-трафика. Сохраненные данные можно экспортировать в 12 различных форматов, начиная с .txt и .csv и заканчивая файлами других анализаторов вроде Wireshark.
Помимо трафика на сетевой карте, CommView может мониторить соединения по VPN, а также трафика, проходящего через модемы — аналоговые, мобильные, ADSL, ISDN и другие, для чего в систему устанавливается специальный драйвер. Есть возможность перехвата VoIP-трафика и сессий SIP-телефонии. В состав приложения входит генератор пакетов, с помощью которого можно отправить на заданный Ethernet-интерфейс пакет указанной длины, с произвольными заголовками и содержимым. Есть также довольно удобный просмотрщик лог‑файлов, позволяющий открывать файлы журналов в отдельном окне сниффера и выполнять поиск по их содержимому.
Тулза, вне всяких сомнений, крайне удобная и полезная, если бы не «кусачие» цены на лицензию. Для профессионального пентестера покупка такого инструмента наверняка будет оправданна, но ради того, чтобы разок «глянуть сеть», можно поискать альтернативные — более дешевые или бесплатные решения.
Intercepter-NG
Это тоже очень старый и убеленный сединами инструмент — впервые «Хакер» написал о нем еще в 2012 году. C тех пор разрабатываемый нашими соотечественниками проект не только не исчез с просторов интернета, как многие его конкуренты, но даже активно развивался и совершенствовался — последняя актуальная редакция сниффера датирована 2020 годом. Существует версия программы для Android в виде .APK-файла и даже консольная версия этого инструмента для Unix.
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Перехват и модификация TCP / IP трафика на лету с помощью Trudy
Существует несколько отличных инструментов для перехвата сетевого трафика. Так, Scapy и Wireshark — прекрасные решения для организации пассивного сниффинга, а Scapy, к тому же, способен отправлять дополнительные пакеты.
В случае, если вам необходимо перехватить траффик в позиции посредника (Man-in-the-Middle), вы можете использовать такие популярные инструменты, как Fiddler, Burp Suite или OWASP ZAP. Это хорошие решения, однако, они ориентированы только на протоколы HTTP(S). Но какое программное обеспечение использовать, если вам нужно модифицировать общий не-HTTP-трафик?
Так, например, если вам необходимо проанализировать трафик системы обмена сообщениями Telegram, который использует свой собственный протокол MTProto, работающий прямо поверх TCP/IP-пакетов (другими словами, HTTP или HTTPS вообще не используется), то в данном случае упомянутые выше инструменты не подойдут.
Одним из инструментов со схожими функциональными возможностями является Ettercap. Он предоставляет простой интерфейс фильтрации, позволяющий изменять передаваемые данные. К сожалению, Ettercap требует, чтобы фильтры были написаны на его собственном языке, что существенно ограничивает количество пользователей, способных полноценно использовать его для своих нужд.
Двумя другими инструментами, на которые вы также можете обратить свое внимание, являются: Mallory и Trudy. Программное обеспечение Mallory можно найти на github ( https://github.com/intrepidusgroup/mallory ), и о нем упоминали еще в далеком 2010 году на конференции Black Hat USA ( https://www.youtube.com/watch?v=0ZquG1p0eKA ). С тех пор много воды утекло, и в настоящее время данный проект, похоже, заброшен. Поэтому в рамках данной статьи мы основное внимание уделим второму программному инструментарию — Trudy, автором которого является @kelbyludwig, а исходный код данного программного обеспечения также доступен на github ( https://github.com/praetorian-code/trudy ).
Перехват и модификация трафика с помощью Trudy
Программное обеспечение Trudy может перехватить и модифицировать любой трафик TCP, а его создатели, когда работали над реализацией проекта, скорее всего, были вдохновлены программным обеспечением Mallory, упомянутым чуть выше. Как говорится в документации, Trudy является «прозрачным прокси-сервером (transparent proxy), который может изменять и сбрасывать трафик для произвольных TCP-соединений». Весь трафик направляется через Trudy, который применяет так называемые модули для его модификации.
Модули Trudy представляют собой ориентированные на конкретную функциональность предварительно запрограммированные части кода, которые пользователь может модифицировать для получения необходимого ему результата. Также Trudy предоставляет интерфейсы для этих модулей ( https://github.com/praetorian-code/trudy/blob/master/module/module.go ). Поскольку Trudy написан на Go, то все модули и их интерфейсы также должны быть написаны на Go. Для маршрутизации трафика и правильной настройки среды доступна подготовленная виртуальная машина.
Настройка виртуальной машины для подмены трафика
Виртуальная машина устанавливает все необходимое программное обеспечение и сам Trudy. Затем она направляет весь трафик в Trudy и из него, используя утилиту iptables. Trudy получает весь трафик, модифицирует его на основе используемого модуля, а затем отправляет трафик обратно в Интернет (более детально смотрите на рисунке 1).
Рисунок 1. Trudy получает весь трафик, модифицирует его на основе используемого модуля, а затем отправляет трафик обратно в Интернет.
Модули Trudy
Использовать модули Trudy довольно просто. Trudy вызывает определенные методы в фиксированном порядке, каждый из которых предназначен для одного конкретного действия:
- Deserialize () — преобразует необработанную полезную нагрузку в известную структуру данных (например, HTTP).
- Drop () — если возвращено значение «true», весь пакет отбрасывается.
- DoMangle () — если возвращено значение «true», вызывается метод Mangle ().
- Mangle () — изменяет полезную нагрузку.
- DoIntercept () — если возвращено значение «true», данные отправляются в интерпретатор Trudy.
- DoPrint () — если возвращено значение «true», вызывается метод PrettyPrint().
- PrettyPrint () — печатает данные в формате, удобном для человеческого восприятия.
- Serialize () — преобразует данные обратно в необработанную полезную нагрузку, если они ранее были «десериализованы».
- BeforeWriteToClient (p pipe.Pipe) — функция, которая вызывается перед отправкой данных клиенту.
- BeforeWriteToServer (p pipe.Pipe) — функция, которая вызывается перед отправкой данных северу.
- AfterWriteToClient (p pipe.Pipe) — функция, которая вызывается после отправки данных клиенту.
- AfterWriteToServer (p pipe.Pipe) — функция, которая вызывается после отправки данных северу.
Пример изменения (подмены) трафика с помощью Trudy
Предлагаем вашему вниманию простой пример модуля, который искажает весь входящий трафик, полученный с IP-адреса «139.59.129.86» через порт 80. Он делает это путем перезаписи всей полезной нагрузки TCP / IP в нули. Основная часть модуля использует функции DoMangle () и Mangle () (более детально смотрите на рисунке 2).
Рисунок 2. Основная часть модуля Trudy, который подменяет на нули весь входящий трафик, полученный с IP-адреса «139.59.129.86» через порт 80, использует функции DoMangle () и Mangle ()
Так, как видно на примере, функция DoMangle () ограничивает подмену указанным IP-адресом, а Mangle () выполняет всю фактическую работу по превращению этого трафика в нули.
После настройки Trudy по этому примеру модуля, мы можем попытаться получить доступ к сайту с указанным IP-адресом через обычный браузер. Запрос будет отправляться нормально, но ответ будет перезаписан нулями. Браузер явно не сможет разобрать ответ и, в конечном итоге, истечет время ожидания.
Мы можем подтвердить это с помощью WireShark. На рисунке 3 показан измененный ответ. Зона, отмеченная синей линией, — полезная нагрузка TCP / IP, полная нулей, как и ожидалось. При этом заголовки TCP / IP (часть битов вне синей рамки), остались нетронутыми.
Рисунок 3. Проверка результатов работы модуля Trudy, выполненная с помощью WireShark.
Весь модуль вы можете найти здесь: https://bit.ly/3gdtqHW
В дополнение к описанной выше функциональности, он выводит информацию о событиях на консоль, чтобы вы имели представление о том, что происходит.
Подобным образом вы можете легко использовать Trudy для множества других задач по перехвату и модификации трафика TCP / IP в эфире.
Появились вопросы или нужна консультация? Обращайтесь!
Вечный параноик, Антон Кочуков.