Думаю, многие олды сейчас разделятся на два лагеря: одни будут считать Агент адварью, другие с теплотой вспомнят сей мессенджер, в котором они встретили свою вторую половинку. Для меня он тоже имеет место в воспоминаниях, это была первая программа для общения, с помощью которой я оставался «на коротке» с родителями. Поэтому вооружившись современными языками программирования и минимальным знанием того, как бинарные протоколы вообще работают, отправился восстанавливать Агент.

Разработка протокола и сервера

Реверс-инженеринг начался именно с воспоминаний. Об этой идее два года назад я рассказал своему другу Михаилу @synzr, а он не оказался против вместе со мной отреверсить протокол, с помощью которого программа и общается с сервером.

Первый ресурс, куда мы пошли смотреть - официальная документация к протоколу, любезно выложенная самими Мэйлру, а отправной точкой стали пара клиентов на J2ME и Windows. Вообще, протокол официально называется MMP, но сами Мэйлру активно использовали аббревиатуру MRA (Mail.Ru Agent) или MRIM (Mail.Ru Instant Messenger).

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

Деталей уже не вспомню, к сожалению, но долгое время я не мог разобраться со списком контактов, так как они попросту переусложнены. Хотя если и знать, как оно работает, то на самом деле в них не так и трудно разобраться. Далеко сразу забегать не буду, сразу объясню что да как.

Протокол состоит в основном из UL и LPS. UL - это 32-битный unsigned int с всегда фиксированной длинной в 4 байта. LPS состоит сразу из двух частей: UL с длинной строки и сама строка без завершающего нуля. Из этих двух разных кирпичиков и собирается пакет.

Заголовок состоит из одиннадцати UL'ов.

Примерное значение

Описание

0xDEADBEEF

Магический заголовок. Разделяет пакеты между друг другом. Всегда "мёртвая говядина"

0x00010008

Версия протокола

0x8

Очередь пакета. В некоторых версиях генерируется случайно

0x1001

Сама команда. В примере - `MRIM_CS_HELLO`

0x4

Размер данных без заголовка

N/A

IP адрес клиента. В документации он так и описан, но де-факто не используется

N/A

Порт клиента, с которого произошёл коннект к серверу. В документации он так и описан, но де-факто не используется

Неиспользуемое заполняется нулями. Размер заголовка всегда равен 44 байтам. А, ну и порядок байт у них Little Endian. Это главное, что нужно о протоколе знать.

За пару дней мы реализовали самые базовые команды: Приветствие (MRIM_CS_HELLO, отправляет частоту "пинга"), вход в аккаунт, контакты, взаимодействие с ними, поиск и сообщения. Всё это проверялось на Агенте 4.10, в котором был очень скудный функционал.

Первые попытки
Первые попытки

Интересно то, что в том самом файле заголовка команда для входа и для контактов обозначены как MRIM_CS_LOGIN2 и MRIM_CS_CONTACT_LIST2, т.е. была ещё у них и первая версия. Значительно позже я начал разбираться в этом вопросе, и оказалось, что это действительно так. Агент появился в 2004 году, и к его реализации... очень много вопросов. И в нём пришлось разбираться самому — официальная документация была очень старой и неполной.

Во-первых, первая версия не умела в мессенджер. Вообще. Там были только ссылки на меилрушные сервисы. Он появился только в 1.5 в самом зачаточном виде.

Агент 1.5. Скриншот от пользователя drel69
Агент 1.5. Скриншот от пользователя drel69
Контакты в Агенте 2.0
Контакты в Агенте 2.0

Контакты появились только в 2.0. В их реализации плохо всё. Там страшный бинарный формат.

1. 2560 байт зарезервировано для групп

2. Внутри блока групп - 128 байт информации о ней

3. Контакты идут после 2560 байт

4. Длина контактов тоже фиксирована - 256 байт

В группе идёт флаг группы, пробел, и его название. На 128 байте всегда байт 0xA

В контакте ещё хуже. Там примерно такой формат:

{Флаги пользователя} {Индекс группы} {Почта пользователя} {Длинна ника в HEX}{Ник}

Последние 4 байта контакта - серверный флаг. 0001, значит, контакт авторизован. И наоборот, нули, значит нет.

С выходом Агента 4.2 это безобразие заменили на более элегантный формат, который я описал в своей документации. Но суть в том, что данные теперь нормально разделяются через маски. Они передаются через строку и довольно просто объясняются - u это UL, а s это LPS. В версии 4.10 у групп маска us, а у контактов uussuus. В группах: флаги и название, а у контактов это флаги, индекс группы, почта контакта, имя, флаг авторизации, статус, и номер телефона. В новом крупном обновлении Агента эти маски просто обновляются, а в блоке контакта добавляются дополнительные пункты.

В Агенте 5.0, например, появились Икс-статусы, и соответственно, к маске добавились sssus: uri статуса, заголовок статуса, его описание, маска доступных функций (с помощью них агент определяет, что умеет клиент) и юзер-агент клиента.

В 5.5 добавился функционал микроблога, и к маске контактов добавилось uuusss: 64-битный айди поста в двух UL, время в Unix-time, текст, и два зарезервированных LPS. Суть, думаю, понятна.

В версии Агента 5.1 появилась поддержка Юникода. Но это не простой UTF-8, если бы. Там использовался UTF-16LE, где каждый символ всегда равнялся двум байтам, будь-то это кириллица или латиница.

Агент 5.0
Агент 5.0

За ним пошла реализация передачи файлов, микроблога, аватарок, и отдельных моментов и поведения некоторых клиентов. В зачаточном виде осталась реализация групповых чатов (конференций). Для реализации некоторых функций пришлось реверсить клиенты, шуршать интернет, или подглядывать в чужие реализации (например, в Miranda NG и myagent-im).

Агент 6.3
Агент 6.3

Патчер и установщик

Потом, нам надоело постоянно копаться в реестре и файле hosts, просто чтобы всё перебросить на наш сервер. Поэтому вместе с юзером n0cha3 сделали патчер, который подменяет мёртвые айпишники и доменные имена на наши собственные.

В Windows это делается довольно просто. Через DLL хукается функция gethostbyname для получения домена из WinSocks, и её аргументы просто заменяются на собственные. Кашпировскому, кстати, такой модифицированный файл не понравился, и он его считает трояном.

Наш установщик
Наш установщик

Вместе со встроенным установщиком лезло всякое г... Нерабочий Спутник@Mail.ru или Guard@Mail.ru. Без моего участия ещё два моих товарища, @Eversiege и motionarium сделали кастомный установщик на основе Inno Setup, в котором всё было заранее пропатчено, вырезано лишнее, и добавлено немного нашего контента. Дизайн установщика делал chelka0.

Запуск на публику

Под новый год 2026 года запустили в публичный доступ проект Renaissance. Открыли сайт, исходники сервера на GitHub и выложили документацию (более полная, чем то, что нам давали сами Mail.ru).

Довольно быстро скриншоты рабочего Агента разошлись в Твиттере. Как я упоминал в начале статьи, люди разделились на два лагеря: на ненависть и на любовь.

Недопонимание юзеров
Недопонимание юзеров
Любовь юзеров
Любовь юзеров

Сайт постарались сверстать в том же духе, что и оригинал. Вместо гетеросексуальных пар мы вставили наших друзей-гиков: встретились на "Электрозаводской" и пофоткались на профессиональную камеру, взяв с собой прикольные девайсы.

Сайт mrim.su
Сайт mrim.su
Процесс обработки
Процесс обработки

Что по итогу?

В ретроспективе протокол Агента — это буквально то, на чём даже сейчас построены продукты VK. Недавнее расследование по поводу MAX это и подтвердило, пакеты составляются схожим образом, как и в MRIM, только данные уже составляются через MessagePack. Там тоже есть версия протокола, команды и последовательность:‑)

Разбирать его было интересно. На удивление, это довольно простой протокол, в сравнении с тем же OSCAR: всего лишь два типа данных и минимальный набор команд для работы клиентов. Если вы смогли осилить MRIM, то и всё остальное будет даваться легко.

Некоторые решения меня, поражают до сих пор. Ясно было видно, что Агент пытался со старым протоколом идти в ногу со временем, и на некоторых командах была сотня костылей.

Если вдруг стало интересно, то вы можете зарегистрироваться на нашем сервере. Если хотите поднять его на локалке, то все исходники и инструкции выложены на GitHub, там же можно покопаться в протоколе. Вэлком!