Исследование троянов в кнопочных телефонах
Данный документ представляет собой описание последовательности действий для выявления типичной вредоносной функциональности кнопочных телефонов: троянов, внедрённых главным образом для использования номера телефона жертвы с целью продажи платных регистраций в мессенджерах и других сервисах (но не ограничиваясь этим).
Оно изложено в виде последовательности действий, с помощью которых можно быстро определить:
Наличие подозрительного кода в прошивке устройства (характерные признаки, присущие подобному классу троянов, на основании опыта исследования множества прошивок)
Его примерную функциональность (также по отличительным особенностям, без глубокого анализа)
Домен, на который устройство подключается для выполнения команд и отправки данных (C&C)
Документ предназначен для начинающих исследователей в области информационной безопасности, которые не имеют опыта работы с прошивами кнопочных телефонов, но также будет полезен любому технически подкованному пользователю — я старался избегать специализированных терминов и по возможности использовать простой и понятный язык.
Table of Contents
Кнопочные телефоны для рынка РФ очень быстро делают за совсем скудные деньги китайцы, работающие без выходных по слишком много часов в сутки. Они вместе с импортёром-заказчиком прекрасно знают, что телефоны купят преимущественно малообеспеченные слои населения, и давно смирились с этим, поэтому единственная их цель — сделать хоть что-то и любыми способами продать подороже.
Продавать дороже получается редко: покупатель ценового сегмента <1000₽ не готов платить за хороший экран, качественный динамик или эргономичные кнопки, поэтому производители сконцентрировались на получении прибыли не только во время, но и после продажи телефона.
Поначалу зарабатывали на встраивании платных игр, сервисов СМС-подписок (анекдоты, гороскопы), дополнительных партнёрских услугах, спустя какое-то время начали встраивать невидимую периодическую отправку платных СМС на короткие номера. К текущему моменту получили распространение встроенные в прошивку трояны (замаскированный вредоносный код), нацеленные на использование номера телефона владельца, для продажи временных номеров для регистрации в различных интернет-сервисах разных регионов.
Работает схема так:
Покупатель телефона устанавливает SIM-карту и включает устройство
Спустя несколько часов или
дней телефон выходит в интернет и
передаёт информацию: регион SIM-карты,
оператор, идентификатор телефона, и
т.п.
В этот момент сервер узнает о
новом телефоне, но еще не знает его
номер.
Сервер отправляет команду для выяснения номера телефона SIM-карты. Это может быть либо USSD-код «узнай свой номер» (уникальный у каждого оператора), либо исходящая СМС с текстом и номером, указанным сервером.
Телефон выполняет команду, полученную с сервера:
В случае USSD: запрос выполняется, на сервер пересылается ответ с номером
В случае СМС чаще всего сообщение отправляется другому владельцу кнопочного телефона с подобным трояном, который перехватывает сообщение и пересылает на сервер вместе с содержимым и номером, либо же СМС может отправляться на специальный шлюз для приёма сообщений, подконтрольный злоумышленникам.
После завершения «идентификации» устройства и получения номера, телефон периодически подключается к серверу в интернете и проверяет наличие команд (раз в сутки или реже, задаётся сервером).
Авторы трояна публикуют номер телефона на сервисах получения СМС для регистрации. Как только его покупают, сервер отправляет телефону команду на установку фильтра пересылки СМС по номеру (или имени) отправителя или ключевому слову в теле сообщения.
Как только нужное СМС получено, его содержимое отправляется на сервер в интернете, при этом оно не сохраняется в памяти телефона, а пользователю не приходит уведомление о его получении (нет звукового сигнала, не выводится на экран).
Троян в телефоне самостоятельно
не выполняет никаких действий, кроме
периодического подключения к серверу.
Вся логика работы (схемы) заложена на
сервере, и может быть изменена для
отдельных устройств в любой
момент.
Злоумышленникам ничего не
мешает использовать троян для обхода
аутентификации на различных сервисах,
которые уже зарегистрированы на этот
номер телефона, входа в интернет-банк
по СМС, и т.п.
Чаще всего импортёр-заказчик не в курсе наличия вредоносного кода в прошивке. Когда выясняется, что телефон сам выходит в интернет раз в сутки, производитель уверяет, что сделано это для синхронизации времени через интернет, обновления стоимости сервиса СМС-подписок, либо для еще какой-либо «сервисной» цели.
Вот что пишет Алексей Рязанцев, автор книги «Китайцы: инструкция по применению», ранее заказчик и импортёр смартфонов, о внедрении платных СМС-подписок в их устройства:
Как у нас, так и у коллег
по отрасли программное обеспечение
создавалось в компаниях производителей
плат. И это был единственный путь, по
которому вредоносное ПО могло проникнуть
в наши устройства. Китайские производители
плат не дают исходных кодов и запрещают
делать самостоятельные модификации
программного обеспечения.
Мы выделили три пути, по
которым вирусы подсаживаются:
* это сознательно делают
поставщики плат, получив за это деньги
от заинтересованных лиц, которые
зарабатывают на подписках и трансляции
и рекламе
* это может делать отдельно
взятый инженер, которого подкупили. Но
случай кажется редким, так как он должен
работать над прошивкой конкретного
устройства для конкретного рынка;
*
загрузка вредоносного ПО происходит с
негласного согласия локальной торговой
марки или её представителей, которые
находятся в доле;
* вредители делают
собственную прошивку и перепрошивают
устройства в стране продажи. Процесс
трудоёмкий и вряд ли возможная выгода
стоит трудозатрат.
Вначале мы предполагали,
что платная подписка ошибочно досталась
нам от игр, которые делались для китайского
рынка. Но случайностью это не было.
[…]
Таким образом расследование
привело нас из Санкт-Петербурга в
Санкт-Петербург. Более того, в прекрасно
знакомую мне компанию. Короткие номера,
на которые шла подписка контента,
принадлежали ей. Правда, выяснилось,
что сама компания пересдаёт эти номера
другим юридическим лицам, которые
пересдают их дальше. И просьба отключить
эти номера для минимизации ущерба лишь
единожды закончилась успешно и только
после вмешательства представителей
оператора связи, которые номера обещали
лично отключить.
Дешевые кнопочные телефоны в основном базируются на двух платформах:
Spreadtrum 6531 (DA/E)
Mediatek MT6260/6261
Определить платформу можно по тому, как устройство идентифицирует себя при подключении к компьютеру USB-кабелем (USB VID/PID).
Первая часть номера устройства - это код производителя:
1782:xxxx — Spreadtrum
0e8d:xxxx
— MediaTek
Чтобы извлечь прошивку, в случае Mediatek достаточно только подключить устройство кабелем. Для Spreadtrum также потребуется либо найти загрузочную (boot) клавишу или комбинацию (чаще всего 0, 1, 5, центральная, левая софт-клавиша), либо воспользоваться USB-OTG-кабелем или переходником (пины ID и GND должны быть замкнуты, чтобы устройство вошло в режим прошивки).
Я использую кабель USB-A-папа — USB-A-папа и переходник USB-A-мама - MicroUSB OTG.
ПО для Spreadtrum:
ПО для Mediatek:
Извлечение на примере Spreadtrum, Digma A172:
Вынуть батарею телефона
Запустить
spreadtrum_dump:
sudo
./spd_dump fdl nor_fdl1.bin 0x40004000 read_flash 0x80000003 0
0x400000 dump.bin
Вставить батарею телефона
Подключить телефон к компьютеру OTG-кабелем
Дамп прошивки занимает
около 30 секунд.
0x400000
— размер флеш-памяти (4
МБ). Скорректируйте размер,
если прошивка кажется неполной (или
если программы для распаковки выдают
ошибки).
ПО для Spreadtrum:
https://gitlab.com/suborg/uniflash (скрипт stoned.py)
ПО для Mediatek:
Основной (пользовательский) код в Spreadtrum хранится в разделе usr/user.bin, в Mediatek — в разделе ALICE.
Программы распаковки Spreadtrum
принимают на вход дамп прошивки и выдают
готовый к анализу файл.
Для распаковки
дампа Mediatek необходимо вручную найти
границу раздела ALICE и отрезать данные
до него (см. инструкцию в репозитории
по ссылке).
Распаковка на примере Spreadtrum, bzpwork:
bzpwork dump.bin .
Код трояна чаще всего имеет следующие особенности, которые упрощают его выявление в прошивке:
Домен в формате xxx.yyy.com, при этом yyy.com не резолвится (не имеет IP-адреса), вероятно, чтобы избежать автоматического обнаружения и индексации поисковыми сканерами
Домен обфусцирован или зашифрован: xor, rc5, base64
Пути URI, запросы, параметры либо находятся в прошивке в открытом виде, либо обфусцированы base64
В запросах передается IMEI, серийный номер телефона, время и другая информация
В простейшем случае достаточно получить все данные, похожие на текстовые строки, утилитой GNU strings, и поискать характерные символы запросов: “/”, “?”, “GET”, “POST” “HTTP/”, и самостоятельно оценить рядом находящиеся соседние строки на подозрительность.
Платформа: Spreadtrum 6531
Телефон подключается к интернету раз в сутки, что видно по выписке мобильного оператора. Производитель заверяет, что это сделано для обновления встроенного сервиса СМС-подписок Funbox.
Произведём поиск строк, обозначенных выше.
Спустя несколько нерелевантных результатов видим заголовки HTTP-запроса, формируемые параметрами, типичными для функции sprintf, и некие URL’ы, без домена:
&Fq-hgF !h}# YCTJ /app/challenge /app-v3/verify /app-v3 Content-Length: %d Cache-Control: no-cache Content-Type: application/octet-stream Connection: Close Accept: */* User-Agent: UNTRUSTED/1.0 HTTP/1.1 POST %s %sHost: %s %s%s%s%s%s%s timeout count out ~L l I}# h
Загрузим код (файл usr.bin или user.bin) в декомпилятор IDA Pro (процессор: ARM, адрес загрузки: 0x8000000 для этого примера, все остальное по умолчанию), найдем соответствующие строки. Они являются частью функции sub_82E7384.
Часть функций и переменных на скриншоте переименована для удобочитаемости.
Выполним поиск cross-ref (перекрёстных ссылок) на переменную backdoor_domain.
В функции sub_82E77A4 можем видеть, как в эту переменную используют несколько функций. Присмотримся к двум последним: одна, вероятно, копирует данные из другой переменной, а далее переменная используется в качестве аргумента вызова функции, вместе с длиной и неким параметром.
Содержание функции backdoor_xor_domain — простого «скользящего» XOR:
В переменной, обозначенной как backdoor_domain_data (источник данных, которые копируются в backdoor_domain) находятся следующие байты:
76 68 70 34 76 7E 7B 70 68 53 0F 41 4C 49
Алгоритм XOR для расшифровки домена в виде Python-кода:
xorkey = 23
domain = bytearray(b"\x76\x68\x70\x34\x76\x7E\x7B\x70\x68\x53\x0F\x41\x4C\x49")
for i in range(len(domain)):
domain[i] ^= xorkey
xorkey += 1
print(domain)Таким образом мы выяснили, что домен api.mbfnws.com
Используется для передачи методом POST неких данных
Обфусцирован с непонятной целью
api.mbfnws.com имеет IP-адреса, при этом mbfnws.com — нет
$ host api.mbfnws.com
api.mbfnws.com is an alias for taurus-appapialb-29623e7-1841973452.us-east-1.elb.amazonaws.com.
taurus-appapialb-29623e7-1841973452.us-east-1.elb.amazonaws.com has address 23.22.214.115
taurus-appapialb-29623e7-1841973452.us-east-1.elb.amazonaws.com has address 18.210.180.210
$ host mbfnws.com
(пусто)
Подделка под модель Nokia 106 DS 2018 (TA-1114), приобретена на Ozon за 900₽.
Платформа: Spreadtrum 6531
Как и в случае с Digma, проведем аналогичный поиск строк HTTP-запросов в прошивке. Выделим все строки длиннее 10 символов, начинающиеся на “/”
$ strings -10 usr.bin | grep '^/'
/25888<<<<.
/*********
/ipget/aW1zaT00NjAwMjAxMDE0ODAwMDEmY2lkPTEwMA==
/god/apollo/ctrl
/god/apollo/task
/god/apollo/succ
/logic/god/task
/behavior/god/info
/behavior/god/verify
/behavior/god/ussdInfo
/god/zeus/rrp
/god/zeus/drp
/god/logic
/STM:%d-%d-%d-%d-%d-%d
/Mount/Mmc/PCM/testfile_%d_%d.wav
/|/t/k/c/Z/R/I/A/8/0/(/
Сразу бросается в глаза путь, закодированный в base64, из-за символов паддинга (заполнения) “==”.
Открываем прошивку в декомпиляторе (процессор: ARM, адрес загрузки: 0x8000000 для этого примера, все остальное по умолчанию), и ищем ссылки на строки.
Сразу же под этой строкой находятся другие подозрительные текстовые обрывки. Если присмотреться к ним внимательней, становится понятно, что это формат строки к функции sprintf:
Домен mpruj0.ol6c7q.com
Используется для передачи или получения неких данных на подозрительный URL
Обфусцирован с непонятной целью, состоит из набора бессмысленных цифр и букв
mpruj0.ol6c7q.com имеет IP-адрес, при этом ol6c7q.com — нет
$ host mpruj0.ol6c7q.com
mpruj0.ol6c7q.com has address 8.8.8.8
$ host ol6c7q.com
(пусто)
Несмотря на красные флаги, домен ссылается на публичный DNS-сервис Google 8.8.8.8, а значит не может использоваться для управления трояном.
Продолжаем поиск. Перейдя по ссылкам на другие URL’ы, видим такую картину:
Домены twxagh.n9a7.com, psgtuu.n9a7.com, lypzhe.n9a7.com не зашифрованы и не обфусцированы, аналогично обладают всеми свойствами подозрительных, при этом ссылаются на действующие адреса.
$ host twxagh.n9a7.com
twxagh.n9a7.com is an alias for d35e502fj5y6yo.cloudfront.net.
d35e502fj5y6yo.cloudfront.net has address 65.9.95.77
d35e502fj5y6yo.cloudfront.net has address 65.9.95.120
d35e502fj5y6yo.cloudfront.net has address 65.9.95.20
d35e502fj5y6yo.cloudfront.net has address 65.9.95.65
$ host psgtuu.n9a7.com
psgtuu.n9a7.com is an alias for d29olfsr3fp1tm.cloudfront.net.
d29olfsr3fp1tm.cloudfront.net has address 3.161.119.87
d29olfsr3fp1tm.cloudfront.net has address 3.161.119.114
d29olfsr3fp1tm.cloudfront.net has address 3.161.119.15
d29olfsr3fp1tm.cloudfront.net has address 3.161.119.74
$ host lypzhe.n9a7.com
lypzhe.n9a7.com is an alias for d2mrrsy7no9wbe.cloudfront.net.
d2mrrsy7no9wbe.cloudfront.net has address 65.9.95.31
d2mrrsy7no9wbe.cloudfront.net has address 65.9.95.72
d2mrrsy7no9wbe.cloudfront.net has address 65.9.95.78
d2mrrsy7no9wbe.cloudfront.net has address 65.9.95.85
$ host n9a7.com
(пусто)
Напомню, цель данного документа — поверхностный, но быстрый анализ прошивки на наличие вредоносной функциональности.
На данном этапе есть два
варианта дальнейшего развития
исследования: продолжить
анализ прошивки в декомпиляторе, либо
заменить домен трояна
api.mbfnws.com
(в случае Digma) на подконтрольный
исследователю, настроить на сервере
перенаправление (проксирование)
запросов на оригинальный адрес, и
записать дампы трафика для
дальнейшего анализа, оставив
телефон лежать включёнными
и с SIM-картой на пару
недель.
Если применить
сначала второй, а затем вернуться в
первому, анализ получится
выполнить быстрее и
меньшими усилиями, с
использованием записанных данных —
можно будет понять формат, тип и содержание
данных без глубокого анализа функций
прошивки, а также посмотреть, какие
команды отправляет сервер, и как телефон
передаёт их результат.
Троян передаёт большое количество шифрованных данных, сложных для анализа статически, поэтому решено было найти функцию шифрования и проводить анализ по записанным дампам трафика.
Трафик шифруется алгоритмом шифрования RC5 с ключом “@taurus!Aa\x0A\x00”, пакет начинается с ключевого (магического) слова TAUR, содержимое кодируется в формат BSON (binary JSON).
Примеры запросов и ответов, программа для их декодирования находятся в приложении.
Пример пересылки трояном текста СМС-сообщения и ответа сервера:
{'0': '54ea07856de7', # идентификатор телефона, который присвоил сервер
'1': 3,
'2': 'DDRR HG K1801J E301 A172 ', # Модель
'3': '354069128633259', # IMEI 1
'4': '354069128633267', # IMEI 2
'5': '250997298944952', # IMSI
'6': '',
'7': '25099', # MCC MNC (идентификатор сети)
'8': '',
'9': b'Beeline', # Название сети
'10': b'',
'11': b'RUS_Beeline', # Ещё какое-то
'12': b'',
'111': '',
'112': '',
'113': '',
'114': '',
'123': '',
'124': '',
'133': '',
'134': '',
'143': '',
'144': '',
'153': b'\x00\x00',
'154': b'\x00\x00',
'163': b'\x00\x00',
'164': b'\x00\x00',
'100': 1,
'13': 24,
'14': '20250406 053332',
'15': 1743906776,
'150': 0,
'16': 0,
'17': 0,
'18': 0,
'19': 0,
'20': 0,
'21': 0,
'221': 0,
'23': 5,
'301': 'Y',
'302': 10002,
'303': 2,
'304': 13,
'24': 0,
'61': 2,
'6101': '265656<696>656', # Отправитель СМС
'6102': ' в приложении билайн https://mybee.page.link/MT', # Текст фрагмента СМС
'6103': 1,
'6111': '265656<696>656', # Отправитель СМС
'6112': 'Вы вышли в интернет. Стоимость каждых 5 МБ — 5 руб. При исчерпании ',
# Второй фрагмент СМС
'6113': 1,
'600': 'CO_1743906',
'611': 2}
Ответ:
{'609': 0}
Типичный запрос на /app-v3:
{'0': 'd1e9bc5fca1e',
'1': 3,
'2': 'DDRR HG K1801J E301 A172 ',
'3': '354069125406915',
'4': '354069125406923',
'5': '250016985076497',
'6': '',
'7': '25001',
'8': '',
'9': b'M\x00T\x00S\x00 \x00R\x00U\x00S\x00\x00\x00',
'10': b'\x00\x00',
'11': b'M\x00T\x00S\x00 \x00R\x00U\x00S\x00\x00\x00',
'12': b'\x00\x00',
'111': '',
'112': '',
'113': '',
'114': '',
'123': '',
'124': '',
'133': '',
'134': '',
'143': '',
'144': '',
'153': b'\x00\x00',
'154': b'\x00\x00',
'163': b'\x00\x00',
'164': b'\x00\x00',
'100': 1,
'13': 24,
'14': '20240630 062757',
'15': 1719610688,
'150': 0,
'16': 0,
'17': 0,
'18': 0,
'19': 0,
'20': 0,
'21': 1,
'221': 0,
'23': 0,
'301': 'Y',
'302': 10002,
'303': 0,
'304': 181,
'24': 0,
'261': 0,
'500': 2}
Типичный ответ:
{'0': 'd1e9bc5fca1e',
'21': 1,
'20': 0,
'25': 84064,
'15': 1719888876,
'181': '',
'18': 0,
'301': 'Y',
'306': 'Mobifun_iappgame_2017_@qq.com_iappg',
'307': '18616840789_8617091357772',
'308': 1,
'302': 10002,
'221': 0,
'222': 120,
'30': 0,
'3001': '',
'3002': '',
'3003': 0,
'3004': '',
'3005': 0,
'3006': 0,
'501': '',
'502': '',
'503': '',
'261': 0,
'262': 0,
'263': 0,
'3007': 0,
'600': 'CO_17198888763131',
'601': '',
'602': 300,
'604': ''}
ПЕРЕДАВАЕМЫЕ параметры (с сервера на телефон)
0: строка, идентификатор устройства для сервера, 12 байт
15: int32, установка времени на устройстве (unix time)
18: int32, назначение неизвестно
181: строка, длина до 150 символов, назначение неизвестно
20: int32, назначение неизвестно
21: int32, флаг использования “mkey”
25: int32, задержка до следующего соединения с сервером (секунды, 3600-432000)
301 строка, 'Y' / ‘N’, флаг использования "hwkey"
302 int32, всегда 10002, hwver
306: строка, строка для шифрования xor данных в nvram (rolling xor 0x2F)
307: строка, схожа с 306, но назначение неизвестно
30xx: сервер отправляет команду на отправку СМС (ответ сервера)
{'0': 'd1e9bc5fca1e',
'21': 0,
'20': 0,
'25': 129017,
'15': 1718443249,
'181': '',
'18': 0,
'301': 'Y',
'306': 'Mobifun_iappgame_2017_@qq.com_iappg',
'307': '18616840789_8617091357772',
'308': 1,
'302': 10002,
'221': 1,
'222': 120,
'30': 1,
'3001': '+79876580338', # Номер отправки СМС
'3002': 'R,RR,RRR bb867522-0a00-4e13-9c48-5ca374e80098', # Сообщение
'3003': 1,
'3004': '0',
'3005': 3,
'3006': 0,
'501': '',
'502': '',
'503': '',
'261': 0,
'262': 0,
'263': 0,
'3007': 1,
'600': '',
'601': '',
'602': 0,
'604': ''}
Владелец номера +79876580338, скорее всего, использует такой же телефон, которому сервер установил команду пересылать всё, что начинается с ключевого слова “R,RR,RRR” на сервер.
x = номер SIM (0-3)
30: int32, 1 = отправляем СМС
30x1: строка, номер телефона (+79...)
30x2: строка, текст СМС, до 140 символов
30x3: int32, назначение неизвестно (тип кодирования СМС?)
30x4: строка, 1 байт, незначение неизвестно (esm_class?)
30x5: int32, таймер отправки (задержка перед отправкой), 3-14400 секунд (3 по умолчанию)
30x6: int32, назначение неизвестно (возможно важный параметр)
30x7: int32, назначение неизвестно, 0-4 (тип сообщения?)
50x: вывод сообщения на экран. Сервером не использовался.
501: строка
502: binary до 140 символов
503: int32 0-1 (decode wide char?)
Данные, передающиеся на lypzhe.n9a7.com:
На psgtuu.n9a7.com:
На twxagh.n9a7.com:
Каждый домен использует уникальные ключи шифрования XOR, отдельно для запроса и ответа от сервера.
Функция “zeus” скачивает программный код с сервера в виде файла, сохраняет его во внутреннюю скрытую память телефона и выполняет при следующем включении. Таким образом реализуется система плагинов — дополнительной функциональности трояна, позволяющей реализовать любые сценарии извлечения «пост-продажной прибыли».
ValdikSS <iam@valdikss.org.ru>