Tym razem zaglądamy do wnętrza routera Cyfrowego Polsatu LT-6408n. W rzeczywistości jest to model produkowany przez firmę Edimax i sprzedawany operatorowi jako Edimax LT‑6408n z jego brandingiem. Router powstał głównie po to, aby współdzielić internet z modemów LTE lub HSPA+ podłączanych przez USB.
Całość pracuje z zasilaczem 5 V, co jest charakterystyczne dla nieco już nowszych sprzętów. Na spodniej naklejce znajduje się domyślne IP, nazwa i hasło administracyjne. FCC ID urządzenia to NDD9564081112.
Z tyłu mamy przycisk On/Off, WPS/Reset, cztery porty LAN, jeden WAN, wejście zasilacza (DC Jack) oraz port USB, służy on często do podłączenia wspomnianego modemu LTE/4G (przykładowo Huawei E3372s-153).
Wnętrze routera
Wystarczy odkręcić śrubki na spodzie. Mogą być one schowane pod nóżkami.
Pierwsze co rzuca się w oczy to przewód USB poprowadzony przez środek płytki. Ktoś chyba zmienił zdanie co do lokalizacji portu. Miał być on z przodu, a został przeniesiony na tył.
Router oparty jest o RTL8196C wraz z pamięcią W9825G6JH (4194304 słów * 4 banków * 16 bitów, czyli 32 MB).
Pamięć łączy się z głównym kontrolerem przez 16 bitowy interfejs. Całość posiada dodatkowo GPIO, USB 2.0, EJTAG, UART oraz kontrolery Switcha i PCIE.
Właściwy program jest na osobnej pamięci Flash, 25L6406E. Te 64 w nazwie sugeruje duży rozmiar - 64 megabity, czyli 8 megabajtów.
Obok pamięci są cztery pady, które wyglądają na miejsce z wyprowadzonym UART.
W sekcji zasilania widzę przetwornicę obniżającą napięcie IT76520M. Jest też miejsce na drugą przetwornicę, ale nie jest ona wlutowana. Można by pomyśleć, że całość pracuje na jednym napięciu.
Pomiar potwierdza, że całość pracuje na 3.3 V:
Nie ma dodatkowych komponentów na spodzie płytki, choć widać, że ktoś planował umieszczać tam cewki.
Zostaje jeszcze RTL8192CE - kontroler WLAN z PCI-Express miniCard, czyli Wi-Fi. Ciekawe, że mimo obramówki sugerującej ekran, tego ekranu tam nie ma.
Odczyt pamięci Flash przez CH341
Pierwszą rzeczą którą zawsze robię, jest pełna rzetelna kopia pamięci Flash przez programator CH341. Nie korzystam z klipsa, nie jest on rzetelny, chyba częściej zdarza mi się, że on nie działa niż działa, więc zamiast tego wolę wylutować układ za pomocą topnika i gorącego powietrza. Potem jeszcze usuwam spoiwo bezołowiowe z padów i lutuję go ponownie na ołowiowe, wtedy kolejne operacje wylutu będą prostsze. Przy kolejnych operacjach już nawet nie czyszczę padów, tylko używam tego spoiwa co jest.
Kiedyś usuwałem takie układy zwykłą lutownicą grotową, ale teraz mam pod ręką ciągle hot air.
NeoProgrammer rozpoznaje pamieć:
Odczyt odbywa się bezproblemowo. Dla pewności wykonałem jeszcze operację verify. Kopię zapisałem na swoim repozytorium:
https://github.com/openshwprojects/FlashDumps/commit/823f9895317a5984cb99fcc468382662b3e52137
Połączenie UART - log bootowania
Teraz można podłączyć się do UART i podejrzeć log startowy routera. Najpierw trzeba odnaleźć piny – zwykle są to cztery pady obok głównego CPU. Najczęściej są to: GND, TX, RX oraz VCC (3.3 V). Do komunikacji użyłem konwertera USB-UART (CH340) ustawionego na 3.3 V. Nie trzeba podłączać VCC, wystarczą trzy przewody: GND, TX, RX (TX z routera do RX konwertera i odwrotnie).
Baud dobrałem eksperymentalnie. W routerach najczęściej spotyka się te same wartości, takie jak 57600, 38400, rzadziej 115200 - w przypadku układów Realtek bardzo często trafia się właśnie 38400 8N1.
W ten sposób udało się odebrać pierwsze znaki. Zapisałem je do pliku przez "Capture to file" w Realterm.
Booting...
========== SPI =============
---RealTek(RTL8196C)at 2013.05.22-07:15+0800 version v1.1f [16bit](390MHz)
DRAM Spreading Spectrum: [ON] TRX Timing: [T:4 R:6]
<=== GPIOA4 off/on 9/1 2197619 times ===>
Jump to image start=0x80500000...
decompressing kernel:
Uncompressing Linux... done, booting the kernel.
done decompressing kernel.
start address: 0x80003770
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 26632k/32768k available (2696k kernel code, 6136k reserved, 697k data, 108k init, 0k highmem)
Calibrating delay loop... 388.30 BogoMIPS (lpj=1941504)
Mount-cache hash table entries: 512
net_namespace: 528 bytes
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
W logu widać informacje o procesie startowym urządzenia, w tym o dekompresji jądra Linuxa. Potem jednak router utyka na:
WEBS Restarting !
Initialize AP MIB failed!
Wygląda na to, że nie udaje się poprawnie zainicjalizować konfiguracji zapisanej w pamięci flash (tzw. MIB – Management Information Base w implementacji Realteka).
Połączenie UART - linia komend
Po komunikacie o MIB proces utyka i router nie startuje. Nie reaguje też na polecenia. Czyżby linia komend była zablokowana? Nic bardziej mylnego. Szybko odkryłem, że wciśnięcie klawisza Escape w momencie bootowania blokuje proces i uwalnia linię komend:
Co więcej, działa komenda help - udostępnia nam listę poleceń:
Komendy zdają się być już znane, widzę, że panowie z OpenWRT je udokumentowali:
https://openwrt.org/docs/techref/bootloader/realtek
W dużym skrócie, mamy tu:
- D <Address> <Len> - dump pamięci (podgląd obszaru RAM/flash)
- DB <Address> <Len> - dump bajtów (byte)
- DW <Address> <Len> - dump słów (word)
- EB <Address> <Value1> ... - zapis bajtów do pamięci
- EW <Address> <Value1> ... - zapis słów (word write)
- CMP <dst><src><length> - porównanie dwóch obszarów pamięci
- IPCONFIG <TargetAddress> - konfiguracja IP (np. do TFTP / recovery)
- AUTOBURN 0/1 - włącza/wyłącza automatyczne programowanie flasha (tzw. "autoflash")
- LOADADDR <Load Address> - ustawia adres, pod który ładowane są dane (np. z sieci lub UART)
- J <TargetAddress> - skok do adresu (uruchomienie kodu w RAM)
- FLW ... - zapis do flash przez SPI (z RAM do SPI flash)
Zadowolony z rezultatów, zacząłem na własną rękę testować komendy. Na pierwszy ogień poszło IPCONFIG:
Z tego co rozumiem, ustawia on docelowy IP routera, gdzie można wrzucić firmware przez żądanie PUT. Co ciekawe, ten IP nie odpowiada nawet na pingi, ale arp zdaje się go widzieć:
Potem zacząłem testować komendy D - dump, czyli podgląd pamięci. Szybko zorientowałem się, że można by tu pójść o krok dalej, i zautomatyzować odczyt flash właśnie przez taką prymitywną komendę. Nie będzie to wydajne, ale pozwoli nam zweryfikować, czy dobrze rozumiemy jej działanie.
Połączenie UART - własny dumper flash
Na odpowiedź komendy dump składa się adres danych oraz zawartości kolejnych słów 32-bitowych w formacie szesnastkowym:
80008000: 00001021 0800200D 00000000 8FA40014
Można to łatwo parsować i zapisywać do pliku. Zagadką pozostaje jedynie offset - gdzie jest zmapowana pamięć Flash? Sprawdziłem to doświadczalnie, skryptem. Wsad odczytany z CH341 zaczyna się na 0xBD000000. W ten sposób mogłem opracować proste narzędzie do odczytu danych przez UART:
Na zrzucie ekranu widać offset $F2A80 wraz z dostępnymi tam danymi. Co takiego jest w zgranym pliku pod tym offsetem?
Dane się zgadzają a zgrana pamięć jest 1:1 zgodna z zawartością Flash.
Dalsze poszukiwania - analiza firmware przez binwalk
Mając zrzut 8 MB pamięci Flash, można go przeanalizować narzędziem binwalk, które automatycznie szuka znanych sygnatur w pliku binarnym. Oto co binwalk znalazł:
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
5344 0x14E0 LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 52128 bytes
76824 0x12C18 LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 3586380 bytes
1179648 0x120000 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 4942768 bytes, 744 inodes, blocksize: 131072 bytes, created: 2038-04-12 00:51:12
Widzimy trzy kluczowe fragmenty:
- pod offsetem 0x14E0 znajduje się niewielki skompresowany fragment LZMA (prawdopodobnie część bootloadera lub recovery)
- pod offsetem 0x12C18 znajduje się skompresowane jądro Linux (LZMA) - to właśnie bootloader je dekompresuje i uruchamia pod adresem 0x80003770
- pod offsetem 0x120000 zaczyna się system plików SquashFS w wersji 4.0
W teorii powinien wypakować to przełącznik -e, ale u mnie wysypuje się z błędem kompresji sasquatch:
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
5344 0x14E0 LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 52128 bytes
76824 0x12C18 LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 3586380 bytes
WARNING: Extractor.execute failed to run external extractor 'sasquatch -p 1 -le -d 'squashfs-root-0' '%e'': [Errno 2] No such file or directory: 'sasquatch', 'sasquatch -p 1 -le -d 'squashfs-root-0' '%e'' might not be installed correctly
WARNING: Extractor.execute failed to run external extractor 'sasquatch -p 1 -be -d 'squashfs-root-0' '%e'': [Errno 2] No such file or directory: 'sasquatch', 'sasquatch -p 1 -be -d 'squashfs-root-0' '%e'' might not be installed correctly
1179648 0x120000 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 4942768 bytes, 744 inodes, blocksize: 131072 bytes, created: 2038-04-12 00:51:12
Dodatkowo, co jeszcze ciekawsze, jednocześnie odzywał się antywirus:
Poradziłem sobie skryptem Python:
Kod: Python
Wypakowany system okazał się być... dość bogaty:
W samym /bin mamy ciekawe pliki, takie jak:
- skrypty do zarządzania routerem (np. firewall.sh, init.sh)
- pliki i sterowniki do obsługi modemów 3G/LTE (cdc-acm.ko, cdc-wdm.ko, usb_modeswitch, qmicli, comgt, bpalogin)
- a nawet skrypty i demony przeznaczone do tetheringu z urządzeń iOS (iPhonów)! Znajdziemy tu m.in. iphone_connect.sh, ipheth-pair, usbmuxd czy ideviceinfo
- serwer webs, czyli główny proces odpowiedzialny za stronę konfiguracyjną i komunikację
Drugi ciekawy katalog to /web, tam są same źródła serwera. Od razu rzuca się w oczy:
- nadmiar plików .asp - na początku myślałem, że to technologia Active Server Pages (ASP) od Microsoftu, ale na to nie wygląda - to inne rozwiązanie, też zawierające HTML, Javascript, ale również specjalne tagi, pobierające zmienne z systemu. Przykładowo:
- wśród .asp widzę interfejs komend:
- pliki obrazów - gif, jpg, a nawet jakimś cudem też PSD:
- w katalogu file widzę też zmienne - pliki var, w tym tłumaczenia:
var alertFunctionRule=new Array
(
"Rule Name ",
"Regelname ",
"Nombre de la regla ",
"Nom de la règle ",
"Nome regola ",
"Regelnaam ",
"Nome da regra ",
"Název pravidla ",
"Nazwa reguły",
"Nume Regula",
"Имя правила",
"Názov pravidla",
"規則名稱",
"规则名称",
"ชื่อกฎ",
"Regelnavn ",
"Regelnamn ",
"Kural Adı"
);
Z kolei zaglądając do katalogu /etc można natknąć się na domyślny plik kont passwd. Oprócz roota i usług sieciowych figurują tam dziwne nazwy kont, "john", "dliu", "odysseus", "ygtai" czy "hcjong", czyżby należały do programistów?
Data kompilacji całego oprogramowania widniejąca w pliku compiler_date - Thu Jan 2 09:13:20 CST 2014 - wskazuje na 2 styczeń 2014 roku.
Głównym skryptem startowym operującym na wszystkich tych systemach jest /bin/init.sh. To bardzo obszerny plik zajmujący się inicjalizacją interfejsów sieciowych, wczytywaniem ustawień (w tym konfiguracji MIB z użyciem wywołań wbudowanego narzędzia systemowego flash, np. flash test-hwconf) i uruchamianiem całej gamy usług - od dhcpd, przez klienta pppoe, aż po obsługę WPS i watchdoga ("wps_daemon", "watchdog.sh").
Zrzut ekranu przedstawia watchdog - gdy dany host nie odpowiada, router jest rebootowany. Poniżej skrypt rebootujący:
Podsumowanie
Przygoda okazała się ciekawsza niż myślałem. Router, choć już dość stary, może przydać się jeszcze również w celach hobbystyczno-edukacyjnych. Jest duży potencjał na zmianę wsadu i uruchomienie programu przesłanego do pamięci RAM. Spróbuję to pokazać w osobnym temacie, choć jeszcze nie wiem, na ile się uda. Część źródeł od Realteka widziałem na GitHubie, ale czy aby na pewno będą pasować do tej płytki? Przekonamy się! Całość nie wygląda na oficjalnie wspieraną przez OpenWRT, ale to nie znaczy, że trzeba ją od razu przekreślać.
Czy widzicie jakieś zastosowanie dla starego routera? Zapraszam do dyskusji.
Fajne? Ranking DIY Pomogłem? Kup mi kawę.