Revitalizace starých nepodporovaných zařízení s pomocí AI – AverMedia Game Capture HD II

Stručně: Reverse engineering AverMedia Game Capture HD II (C285). Uvnitř je malý Linux na SoC Texas Instruments DM368 – žádný uzavřený hardware. Odmítání vstupu 640×480 nebylo technické omezení, ale pouhý whitelist ve vendorské aplikaci encode. Přes sériovou konzoli, dump nezašifrovaného systému a root shell (init=/bin/sh v bootargs) jde box otevřít a nahradit původní firmware vlastním, který plně napsalo AI. Výsledkem je otevřený síťový capture box s RTSP streamem, libovolným rozlišením od 640×480 po 1080p a 60 snímky/s tam, kde originál nabízel jen mrtvý cloud a zmizelou mobilní aplikaci.

Je úžasné sledovat, co dnes AI umožňuje. Za jeden den zvládne skoro kdokoliv množství práce, na které před patnácti lety muselo být celé vývojové oddělení výrobce a trvalo to měsíce. Nemyslím tím, že by AI tu práci udělala za vás – jak uvidíte dál, spoustu času jsem strávil tím, že jsem jí vyvracel nesmysly. Ale posun v tom, co je pro jednoho člověka o víkendu dosažitelné, je obrovský.

Zkoušel jsem si to na krabičce, která mi z té doby zbyla: AverMedia Game Capture HD II, modelové označení C285. Je to slušný kus hardwaru – uvnitř sedí SoC Texas Instruments DM368 na 432 MHz, 256 MB paměti a má hardwarový H.264 enkodér.

V době vzniku uměl věci, které dávaly smysl: nahrávat na disk, streamovat rovnou na YouTube, ovládat se z mobilu. Jenže to YouTube API dávno neexistuje, mobilní aplikace zmizely z obchodů a já sám jsem k němu už dávno ztratil dálkové ovládání. Podpora skončila. Zůstal funkční hardware, ke kterému nevede žádná použitelná cesta.

Oprášil jsem ho z konkrétního důvodu. Pracuji na herním enginu picogame pro mikrokontroléry a potřeboval jsem nahrávat jejich video výstup – DVI 640×480. Doufal jsem, že aspoň na takhle jednoduchou věc box poslouží, protože záznam na disk jde spustit hardwarovým tlačítkem na krabičce.

Neposloužil 😥. Na vstupu podporoval jen velmi omezenou sadu rozlišení a VGA 640×480 mezi nimi nebylo. Krabička signál prostě nepřijala.

To byla ta chvíle, kdy mě napadlo, že by stálo za to podívat se dovnitř. A hned na začátku prozradím pointu, protože dobře ilustruje, o čem celý tenhle text je: to omezení nebylo v hardwaru. V ovladači jádra je tabulka podporovaných vstupních režimů a položka pro 640×480 progresivní tam celou dobu byla. Jen se k ní přes vendorskou aplikaci nedalo dostat.

Co je uvnitř

Zajímalo mě, proč je 640×480 hlášeno jako špatné rozlišení – jestli je to omezení hardwaru, nebo softwaru. Rozmontoval jsem tedy krabičku a podíval se, co ji vlastně pohání.

osazený díl
SoCTexas Instruments DM368ZCE, jádro ARM926EJ-S @ 432 MHz
integrovaný HDVICP – hardwarový koprocesor pro H.264
ISIF + IPIPE (previewer a resizer) pro zpracování obrazu
Řídicí MCUNuvoton NUC100 (Cortex-M0) – I²C master celé desky
HDMI vstupITE IT6604E – HDMI/DVI přijímač
HDMI výstupITE IT6613E – HDMI vysílač
Analogový vstupTI TVP7002 – komponentní/VGA video dekodér
RAM2× Nanya DDR2, dohromady 256 MB
NANDWinbond W29N01HVS1NA – 1 Gbit SLC, tedy 128 MB
Ethernet PHYRealtek RTL8201EL – 100Mbit
USB ↔ SATAGenesys Logic GL830
Sběrnicové budičeněkolik 74LVC244A mezi ITE čipy a SoC
RTCzálohovaný CR2032
EEPROM24C256 (32 kB) na I²C, drží nastavení a MAC adresu
Zvukdva kodeky TI TLV320AIC3x

Jedna věc byla patrná až po rozebrání: mezi ITE čipy a SoC sedí několik budičů 74LVC244A. To je fyzický důkaz toho, jak je vedená obrazová sběrnice, a později to dostalo smysl: přijímač a vysílač si data předávají po společné šestnáctibitové sběrnici a SoC z ní jen odečítá. Proto může na monitoru zároveň běžet obraz i bez aktivního zachytávání přes SoC.

V NAND paměti jsou dvě kompletní sady firmwaru:

mtd0  bootloader        0x00000000–0x003c0000   3,75 MB
mtd1  params            0x003c0000–0x00400000    256 kB   (prostředí U-Bootu)
mtd2  kernel_fw1        0x00400000–0x00800000      4 MB
mtd3  filesystem_fw1    0x00800000–0x04000000     56 MB
mtd4  kernel_fw2        0x04000000–0x04400000      4 MB
mtd5  filesystem_fw2    0x04400000–0x07c00000     56 MB
mtd6  programer_space   0x07c00000–0x08000000      4 MB   (zapisovatelný jffs2)

Dvě banky, mezi kterými se přepíná jednou proměnnou v zavaděči. To se později ukázalo jako naprosto zásadní – jedna banka zůstala celou dobu jako záchranná síť, do které se dá vrátit, zatímco jsem tu druhou opakovaně přepisoval a několikrát rozbil.

Hardware to umí, tak proč ne?

Podle datasheetů nic nenasvědčovalo tomu, že by ty čipy měly mít s 640×480 problém. IT6604 je běžný HDMI/DVI přijímač, který VGA režimy zvládá bez potíží. IPIPE v DM368 pracuje se šířkami až 2176 pixelů. Rozlišení 640×480 je oproti 1080p, které box umí, výrazně menší zátěž.

Usoudil jsem tedy, že omezení bude v softwaru – a že na téhle krabičce nejspíš poběží nějaký Linux. Průzkum internetu to potvrdil velmi rychle, a navíc mnohem líp, než jsem doufal.

Texas Instruments pro tuhle řadu dodával DVSDK – Digital Video Software Development Kit. Není to jen ovladač, je to kompletní stavebnice pro přesně tenhle typ zařízení:

  • codecs-dm365 – samotný H.264 enkodér běžící na HDVICP
  • linuxutils – jaderné moduly cmemk (souvislá paměť pro DMA), edmakirqkdm365mmap
  • a hlavně dvsdk-demos, mezi nimiž je demo jménem encode

To poslední je pointa. Vendorská aplikace v téhle krabičce se jmenuje encode a startuje ji init skript /etc/init.d/encode-demo. Jinými slovy: komerční produkt, který jsem si kdysi koupil, je potomek demo aplikace z SDK od Texas Instruments – a to jméno v něm zůstalo dodnes.

Na boxu je celý ten SDK pořád k dispozici, v /opt/dvsdk/dm368/, včetně skriptu loadmodules_hd.sh, který zavádí ty jaderné moduly. Verze odpovídají době vzniku: jádro Linux 2.6.32.17-davinci1 přeložené v prosinci 2017 kompilátorem gcc 4.3.3, zavaděč U-Boot 2009.03 z ledna 2014.

Tím se úloha proměnila. Nešlo o to, obejít hardwarové omezení – šlo o to dostat se k vrstvě, kterou vendorská aplikace zakrývala.

Mobilní aplikace, která už neexistuje

Než jsem se pustil dovnitř, zkusil jsem to nejjednodušší: co box vlastně nabízí po síti. Odpovídal na jediném portu, na kterém běželo API pro mobilní aplikaci. Ta ale zmizela z obchodů, takže mi to samo o sobě nebylo k ničemu.

Podařilo se mi dohledat starší APK a dekompilovat ho. Z toho vyplynul celý protokol. A byl jednoduchý – nešifrované HTTP na portu 24170. Žádná autentizace, žádné TLS, ani jiné složitosti. Komunikace má i druhý směr box aplikaci posílá události na port TCP 1516.

Celkem se mi podařilo zmapovat 117 koncových bodů – párování s PIN kódem, přepínání vstupu, spouštění a zastavování záznamu, emulaci tlačítek dálkového ovládání.

Tady poprvé nastoupila AI. Z těch nálezů jsem nechal napsat CLI nástroj a malou webovou aplikaci pro ovládání boxu. Povedlo se to prakticky napoprvé a plně to nahradilo ztracené dálkové ovládání i mrtvou mobilní aplikaci. Bez jediného zásahu do firmwaru jsem měl krabičku znovu ovladatelnou.

Sériová konzole: první vstup dovnitř

Ovládání jsem měl zpátky, ale původní problém zůstal. Doufal jsem, že někde v menu – které jsem teď konečně mohl procházet – najdu nastavení, které to rozlišení povolí. Nenašel. Nic takového tam prostě není.

Byl čas pokročit o kus dál. Na desce jsem našel pravděpodobný UART port. Opatrně jsem prozkoumal, co je co, připojil převodník – a za chvíli se na obrazovce objevil U-Boot (na 115200 8N1 což odpovídalo i datasheetu).

U-Boot 2009.03-dirty (Jan 14 2014 - 09:44:01)

I2C:   ready
DRAM:  256 MB
NAND:  128 MiB
In:    serial
Out:   serial
Err:   serial

Po něm nastartoval Linux a nakonec vendorská aplikace. A tady přišel první zádrhel: aplikace si převzala vstupy, takže sériová konzole byla po naskočení appky k ničemu.

Bootování se mi však podařilo přerušit pomocí CTRL+C a naskočil login:

|  _  |___ ___ ___ ___   |  _  |___ ___  |_|___ ___| |_
|     |  _| .'| . | . |  |   __|  _| . | | | -_|  _|  _|
|__|__|_| |__,|_  |___|  |__|  |_| |___|_| |___|___|_|
              |___|                    |___|

Arago Project http://arago-project.org dm368-evm

Arago 2011.02 dm368-evm

Arago je distribuce, kterou pro tuhle řadu dodával přímo TI – postavená na OpenEmbedded. A všimněte si toho hostname: dm368-evm, jméno vývojového kitu. Opět referenční návrh tak, jak přišel od výrobce čipu.

Jenže ani tenhle login mi nebyl k ničemu – vendorská aplikace naskočila souběžně a na vstupy zase nereagoval. Konzole byla obsazená.

Jedna věc mi ale to CTRL+C prozradila, a byla důležitější než samotný login: fungovalo. Box tedy moje znaky opravdu dostával – sériová linka byla obousměrně funkční. Tenhle poznatek si zapamatujte – za chvíli z něj bude záhada.

Zbývala totiž cesta o patro níž: dostat se do U-Bootu ještě předtím, než se Linux vůbec spustí. Zavaděč přitom sám nabízel přesně to, co jsem potřeboval:

Hit any key to stop autoboot:  1

Stiskni libovolnou klávesu. Odpočet jedna vteřina.

Na klávesy nereagoval.

A právě proto to byl skutečný hlavolam, a ne banální chyba v zapojení, protože serial prokazatelně fungoval. Znaky odcházely. Zavaděč je jen z nějakého důvodu zahazoval.

Firmware ke stažení je zašifrovaný

Než jsem se pustil do lámání konzole, zkusil jsem samozřejmě to pohodlnější: stáhnout starší firmware, které výrobce kdysi vydával, a rozebrat je v klidu na stole. Nepomohly.

Soubory měly čitelnou hlavičku:

AVT-CEDxc285WW001.002.0990.0.20.0.32 201710121914 723c8a4f5cacd1cc5a3fabb...
#k_s
2364296
#f_m
16
#f_s
3145752
3145752
...

Jenže všechno za tou hlavičkou je zašifrované (entropie 8 bitu na bajt = prakticky náhodná data).

Tím se cíl vyjasnil: bylo nutné se dostat k rozšifrovanému stavu v běžícím systému. Dumpovat flash paměť přímo z čipu jsem vyloučil – vybavení na to po ruce nemám (je to paralelní flash, která by se musela odpájet, ne jednoduchá sériová SPI).

Šum na sériové lince

Zbývala tedy ta konzole a U-Boot, který na klávesy nereagoval. Jedním z triků, které jsem zkusil, bylo poslat na sériový vstup šum – místo stisků konkrétních kláves prostě proud náhodných dat.

A ono to zabralo 🤯. Na obrazovce vyskočilo:

DM365 EVM >

Prompt zavaděče!

Co to odemklo:

Prodloužení odpočtu. Nastavil jsem bootdelay z jedné vteřiny na pět, abych měl příště víc času na stisk klávesy. Spoiler: nepomohlo to, a proč, to je jedna z nejlepších částí celého příběhu – vrátíme se k ní.

Prompt zavaděče sám o sobě ale ještě není výhra. Za zmínku stojí, co ten U-Boot umí a co ne: v tabulce příkazů je nandsetenvsaveenvbootmdhcptftpboot – ale žádné usbfatload ani mmc. Z U-Bootu samotného tedy nešlo nic uložit na flash disk; ten uměl leda sáhnout po síti. Skutečná cena promptu byla jinde – v tom, že mi dovolil přepsat, co se řekne jádru při startu. A přesně tam vedla cesta dál.

Ze zavaděče do shellu: přepsat bootargs

Původní boot parametry vypadaly takhle:

bootargs=mem=97M console=ttyS0,115200n8 quiet root=/dev/mtdblock5 rootfstype=cramfs ro
         video=davincifb:vid0=OFF:vid1=OFF:osd0=1280x720x16,5400K
         dm365_imp.oper_mode=0 davinci_capture.device_type=4
         davinci_enc_mngr.ch0_output=LCD davinci_enc_mngr.ch0_mode=720P-60
bootcmd=nboot 0x80700000 0 0x4000000;bootm

Ten řádek toho prozradil opravdu hodně:

  • systém běží z mtdblock5 – tedy z druhé banky, filesystem_fw2,
  • kořenový systém je cramfs, připojený read-only (takže nic nepůjde jen tak přepsat),
  • jádru zbývá 97 MB z 256 – zbytek si drží kodek,
  • video výstup je natvrdo 720p60,
  • a jsou tu jména ovladačů i s parametry: dm365_imp.oper_modedavinci_capture.device_typedavinci_enc_mngr.ch0_output. Každý z nich se mi později hodil.

Stačilo tedy na konec připsat init=/bin/sh. Vendorská aplikace se spouští až z init skriptů – když se init nikdy nespustí, aplikace nenaběhne, nesebere mi sériovou konzoli a poprvé mám skutečný root shell na běžícím, rozšifrovaném systému.

Odsud už to byla rutina: připojit USB flash disk a vysypat NAND oddíl po oddílu přes dd z /dev/mtd*. Zavaděč, obě jádra, oba souborové systémy.

Poklady v rozšifrovaném systému

Teď jsem měl na disku celý souborový systém a mohl jsem se v něm hrabat v klidu. A vyplatilo se to hned třikrát.

Klíč k firmwaru

Vzpomínáte na ty stažené .bin, které měly entropii přesně 8,0 a nedaly se rozbalit? Odpověď, jak je rozšifrovat, ležela v hlavní aplikaci encode, kde je tenhle příkaz:

openssl enc -d -des3 -in /tmp/file.en -out /tmp/file.de -pass pass:Av3rMed1a

To je 3DES s heslem Av3rMed1a – možná v tom hesle něco poznáte 🙂. Teď stačí jen jeden příkaz:

openssl enc -d -des3 -md md5 -pass pass:Av3rMed1a -in blob.en -out blob.de

Šifra je přitom symetrická a ta čitelná hlavička je kompletní recept, jak balík poskládat zpátky. Klíč by tak mohl posloužit i k zabalení vlastního „oficiálního fw“, který by přijal updater v aplikaci. Nakonec jsem to ale vůbec nepotřeboval: když mám root shell, zapíšu upravený systém rovnou do neaktivní banky NAND a celou aktualizační systém obejdu.

Root heslo: DES crypt a půl hodiny s hashcat

Z rozšifrovaného systému jsem vytáhl /etc/passwd. Řádek pro roota:

root:xvaWxZvodd.wU:0:0:root:/home/root:/bin/sh

Jedná se o prehistorický DES crypt(3) hash. Po zhruba půl hodině ho hashcat vydal. Samotné heslo by mi bez shellu bylo k ničemu – box žádnou síťovou přihlašovací službu standardně nespouštěl. A přesně o to šlo dál.

Telnet jednou proměnnou v prostředí zavaděče

telnetd je na boxu přítomný (busybox), ale ve výchozím stavu se nespouští. V init skriptu encode-demo je ale tohle:

var_logswitch=`fw_printenv log_switch | cut -c 12`
# enable telnet if debug log is turned on
if [ "$var_logswitch" == "1" ]; then
    telnetd
fi

Vzdálený přístup visí na jedné proměnné v U-Boot – log_switch. Původně sloužila k zapnutí ladicího logu, ale jako vedlejší efekt nastartuje i telnet. A protože prostředí zavaděče je perzistentní (žije v oddílu mtd1), stačí ho jednou nastavit z shellu příkazem fw_setenv a telnet naskočí při každém dalším startu, sám od sebe.

Hotovo. Root heslo z prolomeného hashe + telnet, který se pouští automaticky, = plný, perzistentní root přístup k boxu po síti, bez sériového kabelu, bez zásahů do bootargs při každém startu. Od téhle chvíle byla krabička normální malý Linux server, na který se dá kdykoliv připojit a pracovat na něm.

Vlastní firmware – a tady začíná pracovat AI

Do téhle chvíle šlo o klasický reverse engineering: kabel, konzole, dumpy, prolomený hash. Odsud dál se povaha práce změnila. Měl jsem rozšifrovaný systém a root přístup po síti – a nastal čas napsat vlastní software a dostat ho do krabičky. Tuhle část už prakticky celou odvedla AI. Vlastní záznamovou aplikaci, HTTP i RTSP server, webové rozhraní, build i flashovací postup (s trochou popostrčení správným směrem). Nebylo to bez úskalí, ale rozsah toho, co vzniklo prakticky za večer, by jinak znamenal týdny práce.

Proč se to nedá jen tak přepsat

Souborový systém je cramfs připojený read-only – to jsme věděli už z bootargs. Nejde do něj tedy nic připsat za běhu; jakákoliv změna znamená postavit celý obraz znovu. AI z toho udělala reprodukovatelný build: vyjmenuje zařízení v /dev z originálního cramfs, postaví strom pod fakeroot a slepí ho zpět pomocí mkfs.cramfs. Výsledek je obraz, který jádro připojí úplně stejně jako ten vendorský – jen je v něm místo aplikace encode ta moje.

Dvě banky jako záchranná síť

Tady se ta dvoubanková konstrukce z první kapitoly opravdu vyplatila. Vlastní firmware jsem vždycky nahrával do neaktivní banky, zatímco běžící systém jel z té druhé. Když nový obraz selhal – a několikrát selhal – stará banka pořád nastartovala. To je při experimentování k nezaplacení.

Jenže flashování trvalo čtvrt hodiny

Háček byl v tom, že banku, ze které systém běží, nejde přepsat za chodu – čte se z ní průběžně, takže smazat ji zpod běžícího systému znamená ho rozbít. Muselo se proto nabootovat do druhé, vendorské banky, teprve odtud tu naši přepsat, a nabootovat zpět. Dva rebooty, mazání, flashování a pobyt ve vendorském firmwaru – dohromady zhruba čtvrt hodiny.

Pro jednu velkou finální verzi je to v pořádku. Ale při ladění, kdy člověk mění jeden řádek a chce vidět výsledek, je patnáct minut na každou iteraci zabiják. Muselo to jít líp.

Firmware z flashdisku

Řešení bylo elegantní a využilo to, co v krabičce stejně bylo – USB disk. Spouštěč vlastního firmwaru při každém (re)startu aplikace nejdřív mrkne na připojený flashdisk. Když na něm najde binárku avmbox_h264, spustí přednostně ji místo té ve flash:

Tím se z patnácti minut stalo pár vteřin: wget binárky na disk, zavolat /api/restart – a běží nová verze. Flashování zůstalo jen pro to, aby se do trvalého obrazu zapekla finální ověřená verze.

for d in /tmp/media/*; do
    if [ -x "$d/avmbox_h264" ]; then OVR="$d/avmbox_h264"; break; fi
done

Proč box odmítal 640×480?

Teď, když vlastní aplikace běžela, jsem se konečně mohl vrátit k původní otázce: proč vlastně box to rozlišení odmítal? Opravdu to nebylo o hardwaru. Žádná složka řetězce s 640×480 problém nemá: přijímač IT6604 se na něj zamkne, ovladač davinci_capture ho zná, a kódování obstarává FFmpeg nad hardwarovým enkodérem, pro který je to úplná banalita.

Zádrhel byl o patro výš – v politice vendorské aplikace. encode porovnává detekovaný režim s ručně udržovaným seznamem povolených standardů, a když v něm režim není, nastavení selže přesně tou hláškou o „nepodporovaném rozlišení“. Nešlo tedy o žádnou technickou hranici, jen o whitelist, do kterého VGA nikdo nedopsal (a UI bylo stejně napevno postavené na 720p).

Dalo se to spravit záplatou té binárky, ale pořád by zůstala zavřená aplikace mluvící mrtvým protokolem. Čistší cesta byla naše vlastní aplikace: mluví přímo s V4L2 a vezme prostě tu geometrii, na kterou se driver zamkl – 640×480 tak „funguje samo“, a stejným krokem přibyl streaming, webové rozhraní i volba kodeku.

Bitva o barvy: když se hádá ve špatném modulu

Zachytávání se rozjelo, ale obraz byl zelený a posunutý dolů. A tady se ukázalo, jak vypadá spolupráce s AI ve své lepší i horší podobě zároveň 😁.

Nejdřív ta horší. AI vygenerovala jednu teorii za druhou – špatné pořadí bajtů, přehození barevných složek, konverze barev v čipu – a každou zkoušela naslepo. Několik kol dokola, bez posunu. Hrabala se přitom v tom modulu obrazové cesty, který vypadal jako viník. Nebyl.

Zlom přišel, když jsem trval na měření místo dohadů. AI si přečetla surové snímky přímo z paměti a ukázalo se, že barvy jsou na sběrnici celou dobu správně – chyba nebyla před čipem, ale kus dál v obrazové cestě, jinde, než se hledalo. Odtud to byla otázka dvou drobných vysvětlení: jedno řeklo čipu, ať příchozí data bere jako barvu (bez něj šlo všechno do zelena), druhé posunulo, kde v obraze začíná aktivní plocha (to srovnalo ten svislý posun). Dva bity a obraz seděl.

AI umí vygenerovat nekonečně věrohodně znějících hypotéz a poslušně je zkoušet – ale bez měření se točí v kruhu. Ta produktivní část nezačala lepší teorií, ale tím, že jsem ji donutil přestat hádat a začít měřit.

Výkon: od 3,6 k 60 snímkům za vteřinu

První verze zachytávání běžela na 3,6 snímku za vteřinu. To je slideshow, ne záznam hry. Cesta k použitelné rychlosti vedla přes tři úzká hrdla, a všechna byla o zbytečné práci s pamětí.

Nejdřív se u každého snímku softwarově kódoval JPEG – 270 ms a procesor na 99 %, i když se nikdo nedíval. Nechal jsem ho běžet jen tehdy, když je náhled opravdu potřeba. Pak vyšlo najevo, že snímky sedí v necachované paměti, kterou procesor čte zoufale pomalu (~21 MB/s); přesun na hardwarový DMA řadič zkrátil tentýž přenos na 3,2 ms a poslal FPS přes třicet. Poslední hrdlo byla konverze pixelů do formátu, který chce hardwarový enkodér – 10,7 ms na snímek, skoro tolik co celé kódování.

A tady přišel nejhezčí moment celého ladění: zachytávací hardware ten formát umí dodat rovnou. Jediné, co tomu bránilo, byl překlep v parsování parametrů – přepínač -E omylem vypínal -N. Tedy chyba v kódu, který AI sama napsala a pak kolem ní pracně optimalizovala konverzi, kterou vůbec nemusela dělat 🤦. Po opravě klesla konverze na nulu a snímková frekvence byla konečně tam, kde ji chci mít.

Webové rozhraní

Řetězec zachytávání teď jel rychle a se správným obrazem. Zbývalo to celé udělat ovladatelné. Vendorská aplikace se řídila přes dálkové ovládání a mobil, obojí pryč. Nechal jsem tedy napsat webové UI s použitím Bulma a Alpine.js – oba stahované z CDN (tuto kombinaci rád používám s mikrokontroléry).

Rozhraní má čtyři stránky: živý náhled, záznamy, nastavení a diagnostiku. Skoro každé rozhodnutí v tom UI plyne z jednoho faktu: na takhle pomalém SoC každý dotaz něco stojí – jeden poll stavu znamená několik I²C čtení přes MCU a jeden zápis konfigurace smazání bloku v jffs2. Proto se o stav stará jediný časovač (a na neaktivním tabu se zastaví) a změny nastavení se posílají po skupinách.

Záhada klávesy „U“

Teď splatím dluh z úvodu. Vzpomínáte na ten odpočet, který na klávesy nereagoval?

Hit any key to stop autoboot:  5

Jenže žádná „libovolná“ nefungovala i když serial rozhodně fungoval. Tady jsem měl od začátku podezření, že to nebude libovolná klávesa, ale nějaká konkrétní, a opakovaně jsem žádal, ať se prověří samotný U-Boot. AI stále tvrdila, že to podrobně prozkoumala a že opravdu stačí cokokoliv. Nestačilo.

Nechal jsem si tedy najít kód konkrétní kód v disassemly a na první pohled to bylo hned jasné a i AI svou chybu okamžitě pochopila:

333b40:  bl    0x330c50         ; getc()  - přečti stisknutý znak
333b44:  and   r3, r0, #255     ; r3 = znak & 0xFF
333b48:  cmp   r3, #85          ; ← porovnání s 0x55 = 'U'
333b54:  bne   0x333b68         ; není 'U'? → ignoruj a odpočítávej dál
333b58:  mov   r5, #1           ; je 'U'? → přeruš autoboot
333b5c:  mov   r4, #0           ;           a skoč do shellu

To cmp r3, #85 je celé jádro věci. Číslo 85 je 0x55, a 0x55 je v ASCII velké U. Nečeká se na libovolnou klávesu ale právě na tento znak. Jen tam někdo nechal původní hlášku z defaultního chování. AI i přes několik žádostí o hloubkové prověření skončila na tom, že našla tuto hlášku a tak to musí být pravda a dále to neřešila…

Na téhle epizodě je zajímavé, jak snadné to nakonec bylo – a jak dlouho to trvalo. Ta instrukce nebyla nikde schovaná. Je to jedno porovnání v přehledně pojmenované funkci abortboot, na kterou se dá v disassembly podívat během pár minut…

Kde měla AI problémy

Slíbil jsem v úvodu, že bude jasné i to, kde AI klopýtla — a spoustu času jsem strávil vyvracením nesmyslů. Opakovaly se ve vzorcích:

  • Věří vypsané hlášce víc než kódu. Ta proradná klávesa U…; jindy si naivním scannerem „napočítala“ klíčové snímky, které v souboru vůbec nebyly.
  • Z jedné chyby postaví princip. Opakovaně tvrdila, že současný passthrough a záznam „nejde“ – přitom to byl vedlejší efekt jejího vlastního příkazu, ne vlastnost zařízení. Stihla to zabudovat i do API a komentářů jako fakt.
  • Vymyslí si důkaz a uvěří mu. Domněnku, že vendorská aplikace přepisuje bootargs, „doložila“ výpisem, který si předtím sama vyrobila – a zapsala do trvalé paměti jako fakt.
  • Ublíží tomu, na čem pracuje. Několik pádů boxu si způsobila sama – slepým sondováním přes MCU, zaplavením systému stovkami shellů (dvakrát došla paměť), nebo kill -9, co shodil síť.

Na druhou stranu tytéž schopnosti odvedly obrovské množství správné, nudné práce a chybu skoro vždy dohledaly, jakmile jsem ji pojmenoval a nasměroval práci na správné místo.

Co box umí dnes

Z blackboxu, přivázaného ke službám, které dnes už neexistují, je otevřený síťový
capture box – a umí toho víc než v den, kdy jsem si ho koupil. Část práce bylo původní
funkce získat zpět na vlastním softwaru. Hlavně souběžný obraz na monitoru i záznam přes
hardwarovou cestu přijímač → vysílač (to uměl i originál, jen mi dalo zabrat rozchodit to na
vlastním firmwaru). Ale toho úplně nového je tam víc:

  • Živý RTSP stream po síti – pro mě ta zásadní funkce. Originál uměl jen push na YouTube. Teď mám univerzální H.264 stream po síti do OBS, VLC nebo ffmpeg (a MJPEG rovnou do prohlížeče).
  • Libovolné rozlišení – od 640×480, které vendor zakazoval a kvůli kterému to celé začalo,
    až po 1080p. To druhé si vyžádalo přeskládat v paměti oblast vyhrazenou kodeku a uvolnit v ní
    ~58 MB.
  • Záznam se vším všudy – Matroska kontejner se správným časováním, volitelným bitrate i snímkovou frekvencí.
  • Moderní webové rozhraní místo zmizelé mobilní aplikace.
  • 60 snímků/s ve 640×480 tam, kde to začínalo na nepoužitelných 3,6.

A protože je z toho obyčejný malý Linux server s vlastním softwarem, není to konečný stav, ale
základ, na kterém jde stavět dál.

Závěr

Začal jsem s krabičkou, kterou by většina lidí vyhodila: nepodporovaná, s mrtvým cloudem, bez ovladače, odmítající to jediné, co jsem po ní chtěl. Skončil jsem s otevřeným zařízením, které nezávisí na ničí cizí službě.

Nechci ale tvrdit, že „to udělala AI“. Dělba práce byla docela jasná. Klasický hardwarový reverse engineering – kabel, konzole, měření, náhodný vstup do zavaděče – byl na mně. Jakmile ale byla data venku, převzala AI drtivou většinu skutečné práce: rozbor firmwaru, dešifrovací klíč, celou vlastní aplikaci, server, webové rozhraní i build. Množství kódu a analýzy, které vzniklo za pár večerů, by dřív znamenalo týdny. Jen je dobré vědět, že ten člověk u toho pořád musí být a i sám technice trochu rozumět, aby hlad AI po pálení tokenů směroval správným směrem.

Ptáte se

Proč AverMedia Game Capture HD II odmítá rozlišení 640×480?

Není to hardwarové omezení. Vendorská aplikace encode porovnává detekovaný režim s ručně udržovaným whitelistem povolených standardů a VGA 640×480 do něj nikdo nedopsal. Přijímač IT6604, ovladač davinci_capture i hardwarový H.264 enkodér to přitom zvládají bez potíží.

Jaký hardware je uvnitř boxu C285?

SoC Texas Instruments DM368 (jádro ARM926EJ-S @ 432 MHz) s hardwarovým H.264 koprocesorem HDVICP, 256 MB DDR2 a 128 MB NAND. Dále HDMI přijímač ITE IT6604E, vysílač IT6613E, VGA/komponentní dekodér TI TVP7002 a řídicí MCU Nuvoton NUC100. Běží na něm Linux (distribuce Arago od TI, postavená na OpenEmbedded).

Jak se dostat do root shellu na boxu?

Přes sériovou konzoli (UART, 115200 8N1) se přeruší autoboot v U-Bootu a do bootargs se připíše init=/bin/sh. Tím se nespustí vendorská aplikace ani init skripty, takže konzoli nikdo neobsadí a získáte root shell na běžícím, rozšifrovaném systému.

Je firmware AverMedia zašifrovaný a jde rozšifrovat?

Ano. Soubory .bin mají čitelnou hlavičku, ale vše za ní je šifrované 3DES (entropie ~8 bitů/bajt). Klíč je natvrdo v aplikaci encode – heslo Av3rMed1a – a rozšifrování obstará jediný příkaz openssl enc -d -des3 -md md5 -pass pass:Av3rMed1a.

K čemu tu byla AI a co zvládla?

Klasický hardwarový reverse engineering (kabel, konzole, měření, náhodný vstup do zavaděče) zůstal na člověku. Jakmile byla data venku, AI odvedla drtivou většinu práce: rozbor firmwaru, dešifrovací klíč, vlastní záznamovou aplikaci, HTTP i RTSP server, webové rozhraní a build. Naopak opakovaně věřila výpisům víc než kódu a bez měření se točila v kruhu.

Proč U-Boot nereagoval na „libovolnou klávesu“?

Protože na libovolnou klávesu nečekal. Ve funkci abortboot je v disassembly cmp r3, #85, tedy porovnání se znakem U (0x55). Autoboot přeruší jedině velké U; původní hláška „Hit any key to stop autoboot“ tam zůstala z defaultního chování.
Sdílejte článek:
Ukaž světu,
že jsi Maker!
Koupit tričko
Kafe pro Chiptrona
Dodej energii dalšímu článku

Související články

Picogame je 2D herní engine pro CircuitPython od Vládi Smitky. Nativní jádro v C se stará o vykreslování, scény a kolize, herní logiku píšete v Pythonu – bez kompilace a flashování. Běží na PicoPadu, Raspberry Pi Picu, ESP32 i Adafruit…

Umělá inteligence už není sci-fi — ChatGPT, Gemini nebo Claude dnes umí napsat e-mail, shrnout dlouhý dokument, naplánovat dovolenou nebo připravit pracovní list do školy za pár vteřin. Háček je v tom, že většina lidí neví, jak na to. Placené online kurzy práce s…

Na serveru HN vyšel článek o USB-C a já na něj prostě musím reagovat. Kromě několika nepřesností se strhla i vlna nesmyslů a mýtů na sociálních sítích. Článek na HN je za paywallem, budu se tedy snažit reagovat na určité…

Telefon se přes USB-C nenabíjí, monitor nejde nebo je SSD pomalý? Vysvětlení problematiky USB-C srozumitelně – PD, CC vodiče, e-marker – plus interaktivní detektiv, který najde viníka a poradí, co s tím.

Letadla, rádio, vysílačky nebo třeba satelity – to vše zachytíte pomocí levného RTL-SDR dongle za pár stovek korun. V tomto praktickém tutoriálu ukážu, jak jej rozjedete na Ubuntu/Debian Linuxu krok za krokem. Žádné složité závislosti, jen terminál a pár příkazů.​ Přidám i návod na…

Jak během pár večerů proměnit mnoho let obsahu v moderní, živý web? Je WordPress vhodná volba? Co je potřeba si ohlídat? V tomto článku o redesignu Chiptron.cz najdete konkrétní postupy, jak se řešila migrace i jak nám pomohla AI.

Trendy