Pull to refresh

Еще более секретные Telegramмы

Reading time 7 min
Views 36K

Все привыкли считать телеграм надежной и безопасной средой для передачи сообщений любого сорта. Однако, под капотом у него крутится совершенно обычная комбинация а- и симметричного шифрований, а это ведь совсем не интересно. Да и в конце концов, зачем вообще явно доверять свои сообщения третьей стороне?
КДПВ за авторством Antonio Prohías
TL;DR — изобретаем приватный скрытый канал через блокирования пользователями друг друга.


Скрытый канал


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


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


Цветок в окне


Цветочно-оконные каналы телеграма


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


Что же такого может изменять некто Алиса в телеграме, что доступно для просмотра некоему Бобу? Да много чего: аватарки, имена пользователя, время последнего посещения и многое другое. Однако, обычно они доступны всем сразу, что ограничивает приватность возможного диалога — любой, обладающий знанием метода передачи, сможет прослушивать посылаемые сообщения. Как ни странно, это ограничение можно обойти без использования криптографии.


В черном-черном списке


У каждого пользователя есть свой уникальный черный список, и, если читатель бывал в нем хоть раз, то должен был заметить, изменение даты последнего посещения обидчика на "last seen a long time ago" наравне с пустым аватаром. На самом деле, пользователь мог быть в сети хоть секунду назад и сменить сотню котиков в своем профиле, но Telegram API просто не возвращает приложению эти данные. Таким образом он защищает вашу личную жизнь от нежеланных лиц, взамен давая им понять, что они заблокированы.


Что же в итоге общего между цветком в окне и нахождением в списке блокировки? И то, и другое можно проверить в определенный момент времени, получив один бит информации в зависимости от того, в черном ли ты списке или нет. Дополнительным бонусом идет тот факт, что телеграм, скорее всего, не хранит в своих логах (а если и хранит, то недолго лишь в целях журналирования) историю блокирования друг друга пользователей.


Организовываем биты


Возможность передачи и получения битов — это, конечно, хорошо, но все-таки нужно описать полноценный механизм ее эксплуатации. Телеграм не высылает пользователям уведомления в момент их добавления в черный список, поэтому прием каждого бита должен быть инициирован получателем (Бобом) и не зависеть от отправителя (Алисы). Отсюда же следует, что Алиса и Боб должны выполнять запросы с одной частотой, чтобы каждому такту отправителя соответствовал один такт получателя.


Сам алгоритм обмена на каждом такте выглядит при этом так:


  • A проверяет отправляемый бит и, если требуется послать сигнал, то, в зависимости от его значения:
    • A -> T: заблокировать Б;
    • A -> T: разблокировать Б.
  • Б получает бит:
    • Б -> T: запрос пользователя A;
    • T -> Б: доступная Б информация об А;
    • Б: проверяет, есть ли в полученной информации статус:
      • Б: если есть -> он не заблокирован и получен 0
      • Б: если нет -> он заблокирован и получен 1

Большинство современных пользовательских процессоров обладают хорошими встроенными генераторами частоты (как минимум, системными часами), поэтому такты можно синхронизировать с их помощью, не используя сам канал передачи данных. Стоит лишь заметить, что запросы к API телеграма являются сетевыми и не спешат работать быстро, чему не помогают факт его блокировки на территории РФ и необходимость использовать прокси. Но длина такта должна в среднем превышать время, необходимое на совершение этих запросов, поэтому частота и скорость передачи данных крайне малы.


Кодируем сообщения


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


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


Поэтому мы, находясь в 21 веке, будем кодировать тексты одним из самых эффективных доступных телеграфистам столетие назад методов — кодом Бодо. Точнее, его последней вариацией ITA-2 за авторством Мюррея, чтобы совершать меньше вызовов API на часто встречаемых символах. Можно пожаловаться на отсутствие русского языка, но в моем представлении транслит является более простым выходом, чем жертвоприношение дополнительных символов всяким Ю и Щ.


Осталось лишь определить начало и конец каждого сеанса передачи данных, чтобы принимающая сторона среди большого потока могла выделить передаваемые ей сообщения. До начала передачи Боб находится либо в черном списке, либо за его пределами. Тогда Алиса сигнализирует о начале передачи, сменив это состояние на один такт на противоположное. В конце же передачи она просто разблокирует Боба. Он продолжает получать нулевые символы пока не накопит достаточное количество, чтобы надежно констатировать конец передачи.


На временной шкале


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


Высокие технологии


После нескольких часов попыток использовать официальную библиотеку для взаимодействия с API, я плюнул и написал все необходимое на питоне с использованием более человечного Telethon'а. Автор даже представляет API в синхронном стиле, что почему-то стало жуткой редкостью. Кодирование сообщений с помощью ITA-2 пришлось писать самому на коленке, так как ничего готового толком не нашел.


Синхронизация частоты происходит на системные часы (и да, программа спит! в промежутках), которые достаточно точны, если учитывать необходимое время на выполнение запросов к API, которое стабильно больше десятой доли секунды. Саму скорость передачи пользователь может задать по желанию какую угодно, однако я использую принцип "не больше запроса в секунду", чтобы избежать как ошибок, так и заморозки за спам однотипными запросами. Телеграм, вообще, оказался очень придирчив к использованию своего API, замораживая доступ к аккаунту через него на сутки даже при просто совершении трех авторизаций (притом успешных) подряд, а также случайных кратковременных блокировках по непонятным причинам.


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


Пример использования


Для использования надо получить свой api_id и api_hash у телеграма по этой инструкции и выставить полученные значения в файле 'covertele.py'. В аргументах командной строки указываются желаемое действие, свой идентификатор, идентификатор получателя, а также передаваемое сообщение, если он является отправителем. Выглядит все это как-то так:


У Алисы:                                    У Боба:

Enter your phone number: XXX        |       Enter your phone number: XXX
Enter auth code: YYY                |       Enter auth code: YYY
Started message transmission...     |       Listening for the message...
---++ ('O', '9')                    |       ---++ ('O', '9')
--+-+ ('H', '#')                    |       --+-+ ('H', '#')
+++++ (1, 1)                        |       +++++ (1, 1)
--++- ('N', ',')                    |       --++- ('N', ',')
--+-- (' ', ' ')                    |       --+-- (' ', ' ')
++-++ (0, 0)                        |       ++-++ (0, 0)
--+-+ ('H', '#')                    |       --+-+ ('H', '#')
-++-- ('I', '8')                    |       -++-- ('I', '8')
--+-- (' ', ' ')                    |       --+-- (' ', ' ')
--+++ ('M', '.')                    |       --+++ ('M', '.')
++--- ('A', '-')                    |       ++--- ('A', '-')
-+-+- ('R', "'")                    |       -+-+- ('R', "'")
++++- ('K', '(')                    |       ++++- ('K', '(')
+++++ (1, 1)                        |       +++++ (1, 1)
+-++- ('F', '!')                    |       +-++- ('F', '!')
--+++ ('M', '.')                    |       --+++ ('M', '.')
--+++ ('M', '.')                    |       --+++ ('M', '.')
Done, exiting...                    |       ----- ('', '')
                                    |       ----- ('', '')
                                    |       Automatically decoded: OH, HI MARK!..

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


Если кому-то захочется, можно также использовать простой предоставляемый API:


from covertele import TelegramBlockingAPI
from cochannel import CovertChannel

friend = input("Введи имя друга для передачи данных:")
# Для работы канала с телеграмом нужно создать сначала интерфейс взаимодействия
# По умолчанию, для авторизации используется стандартный ввод-вывод, за обходом читай исходный код
id = input("Введите свой идентификатор:")
api = TelegramBlockingAPI(id)

# С помощью созданного интерфейса создается непосредственно канал
friend = input("Enter your friend's id:")
channel = CovertChannel(api, friend)

# Дальше можно использовать channel.receive() и channel.send() для непосредственного обмена данными
channel.send("Bork, bork!")
print(channel.receive)

# Если нужно обрабатывать код на ошибки автоматически, можно использовать их аналоги с суффиксом _raw
codes = channel.receive_raw()
for code in codes:
check(code)
channel.send_raw([19, 24, 24, 13])

За пределами телеграма


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


P.S. Отдельная благодарность моей пассии за любовь кидать меня в ЧС.


Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+48
Comments 35
Comments Comments 35

Articles