Zostałem niedawno poproszony o odzyskanie danych z zepsutego telefonu. Haczyk: dane były w pamięci telefonu, opcja podłączania się przez USB jako dysk zewnętrzny była wyłączona, a ekran dotykowy nie działał. I co z takim fantem zrobić? Otóż okazało się, że da się zrobić całkiem sporo, i choć ostatecznie danych nie udało mi się odzyskać, to przebieg samej walki z telefonem był dość ciekawy i wydaje mi się, że warty opisania.
Próby odzyskania danych
Przede wszystkim potrzebny mi był pomysł jak wejść w jakąkolwiek interakcję z telefonem w takim stanie. Jako że był to smartfon z Androidem, dość szybko przyszedł mi do głowy jeden pomysł - ADB, czyli "Android Debug Bridge". Jest to opcja wykorzystywana głównie przez programistów aplikacji na smartfony, pozwalająca na wysyłanie telefonowi przez USB różnych poleceń, a nawet podłączenie się do terminala. Tylko jeden drobny problem: opcja musi być włączona także po stronie telefonu, a tu nie była. No i jesteśmy w punkcie wyjścia.
Trochę zabawy z Google w krótkim czasie powiedziało mi, że istnieją jednak sposoby włączenia ADB przez USB. Wymagały jednak kolejnej rzeczy, której ten konkretny telefon nie miał - odpowiedniego oprogramowania tzw. "recovery". Recovery jest specjalnym programem, który można uruchomić przy włączaniu telefonu, aby naprawić uszkodzony system - podmieniać pliki w pamięci telefonu itp. Jak się okazuje, ADB można włączyć edytując kilka plików, ale w tym celu trzeba najpierw mieć do nich dostęp. Smartfon, którym się zajmowałem, dostępu mi oczywiście nie dawał.
No nic, atakujemy dalej. Nie ma odpowiedniego recovery, to trzeba takie wgrać. Dość znanym i lubianym przez osoby modyfikujące oprogramowanie w swoich telefonach programem jest ClockworkMod Recovery (w skrócie CWM). Znalazłem odpowiedni obraz i spróbowałem wrzucić go na telefon... ale jakżeby inaczej, nie ma tak łatwo. Oprogramowanie było za każdym razem odrzucane ze względu na brak poprawnego podpisu cyfrowego. Częścią zabezpieczeń smartfonów jest blokada bootloadera, która powoduje tyle, że na telefon da się wgrać jedynie oprogramowanie podpisane cyfrowo przez producenta. Producent (w tym wypadku HTC) oczywiście CWM Recovery nie podpisał, więc wgrać się go nie da.
Tu okazało się, że miałem trochę szczęścia - otóż HTC umożliwiało bezpłatne zdjęcie blokady bootloadera. Wystarczyło włączyć telefon w trybie fastboot, wykonać polecenie opisane na stronie, przekleić fragment danych, które telefon odsyłał przez USB, po czym wykonać jeszcze jedno polecenie. No to próbujemy: wybrałem na stronie odpowiedni model, na którym to etapie poinformowała mnie, że w celu odblokowania będę musiał najpierw wykonać aktualizację oprogramowania. Postanowiłem najpierw spróbować bez niej, gdyż obawiałem się usunięcia danych, które miałem odzyskać. Telefon wszedł w tryb fastboot, wyświetlił mi token, który miałem wkleić na stronę, co też zrobiłem. Strona w odpowiedzi wygenerowała klucz do zdjęcia blokady... który nie zadziałał. Ech.
Dobrze więc - ściągnąłem, co było potrzebne do aktualizacji, uruchomiłem, ale wykonać się jej nie dało. Oprogramowanie najpierw nie chciało wykryć telefonu, a gdy już je do tego zmusiłem, aktualizacja kończyła się błędem. W tym momencie byłem przekonany, że wiele już nie zdziałam.
Szczęśliwie jednak szukając w desperacji jakiegoś rozwiązania, trafiłem gdzieś na opis przebiegu zdejmowania blokady, w którym autor polecał na etapie wyboru modelu telefonu wskazać "Inny model" zamiast jakiegoś konkretnego. Spróbowałem tego - znów wygenerowałem token, wkleiłem na stronę, użyłem otrzymanego klucza... i bootloader się odblokował! Wszystkie przejścia z próbami aktualizacji były kompletnie niepotrzebne.
Mając odblokowany bootloader, wgrałem recovery, po czym udało mi się połączyć z powłoką na telefonie. Strona, która opisywała, jak włączyć ADB, kazała edytować dwa pliki: /default.props
oraz /system/build.props
. Edytowałem je, uruchomiłem telefon ponownie, ale ADB nie działało. Sprawdziłem pliki jeszcze raz, a tu po mojej edycji nie ma śladu. Ki czort?
Skracając już nieco historię - okazało się, że pliki, które edytowałem, były obecne jedynie w pamięci RAM. Same partycje z danymi w telefonie nie były domyślnie zamontowane. Po zamontowaniu ich udało mi się poprawnie włączyć ADB, jednak przy okazji zobaczyłem niepokojącą rzecz, a mianowicie że partycja, która powinna zawierać dane do odzyskania, wygląda na pustą. Najwyraźniej w którymś momencie (podejrzewam próby niepotrzebnej aktualizacji oprogramowania...) zrobiłem coś, co przywróciło partycjom stan fabryczny. Porażka.
Odzyskiwanie kontroli nad telefonem - hackowanie ekranu dotykowego
Dane straciłem, ale postanowiłem przynajmniej znaleźć sposób na umożliwienie korzystania z telefonu w ograniczonym zakresie. Wiedziałem, że istnieje możliwość kontrolowania telefonu w jakimś stopniu przez ADB, więc zacząłem szukać programów, które by to umożliwiały. Jeden z nich, ADB Control wyglądał dokładnie na coś, o co mi chodziło - wyświetlał zrzut ekranu z telefonu w okienku oraz wysyłał wszystkie kliknięcia i przeciągnięcia myszką na telefon jako zdarzenia ekranu dotykowego.
Pobrałem program, spróbowałem uruchomić, ale znowu - nie ma łatwo, nie działał. To znaczy, uruchamiał się, owszem, ale nie pobierał żadnego obrazu, wyświetlał jedynie czarne okno. Rzut oka na konsolę pokazał, że problem był w pobieraniu zrzutu ekranu.
Zbadanie problemu głębiej ujawniło, że wersja Androida na smartfonie nie posiada wielu przydatnych aplikacji, z których korzystał ADB Control. Między innymi, nie posiadał programu do pobierania zrzutów ekranu ani do wysyłania zdarzeń dotykowych. Fantastycznie. Ale po kolei, zacznijmy od screenów.
Chwila googlowania pozwoliła na znalezienie skompilowanego już programu, który miał robić screeny. Wrzuciłem go na telefon i uruchomiłem przez ADB - zadziałał. Cudnie. Przerobiłem nieco ADB Control (na szczęście autor udostępnił kod źródłowy - chwała mu) i zawartość ekranu zaczęła poprawnie wyświetlać się w okienku. Nadal jednak nie miałem działających zdarzeń dotykowych.
Nowsze wersje Androida zawierają programik o nazwie input
, który udostępnia dwa ciekawe polecenia: input tap
oraz input swipe
. Pierwsze symuluje dotknięcie ekranu, drugie - przeciągnięcie po nim palcem. Z niego też korzystał autor ADB Control. Niestety, wersja na smartfonie pod moją opieką tych opcji nie miała. Udało mi się znaleźć jedynie polecenie sendevent
, które również pozwala symulować dotknięcia ekranu, ale w dużo mniej przyjemny sposób. No nic, przynajmniej coś miałem.
Niestety - przykłady z sendevent
, które znalazłem, nie chciały za nic zadziałać. Wysyłałem zdarzenia o odpowiednich (wg internetu) kodach na wszystkie możliwe urządzenia wejściowe, ale nie widać było żadnej reakcji. Znowu wyglądało, że to koniec zabawy.
Znalazłem jednak sposób na monitorowanie urządzeń wejściowych i okazało się, że jeden róg ekranu przejawia szczątkową aktywność. Przy dotknięciu wysyłał do systemu dane... które były kompletnie różne od opisywanych w internecie. Nic dziwnego, że nie udawało mi się pobudzić telefonu do działania. Problem tylko w tym, że co prawda wiedziałem, że wysyłam błędne dane, ale ciągle nie wiedziałem, jakie powinny być poprawne. Badanie tego, co wysyła prawdziwy ekran dotykowy niewiele dawało, gdyż on wysyłał tylko w kółko dwie te same rzeczy. Wiele wywnioskować się z tego nie dało.
Została mi ostatnia opcja. Było już tylko jedno miejsce, z którego mogłem się dowiedzieć, czego oczekuje od ekranu dotykowego jądro systemu - kod tegoż jądra. Android jest na szczęście oparty na Linuksie, co oznacza, że jego kod jest na licencji GNU GPL i musiał zostać udostępniony przez producenta telefonu. I faktycznie, na stronie HTC można pobrać pełen kod źródłowy oprogramowania różnych modeli. Znalazłem ten właściwy i pobrałem paczkę.
Znalezienie kodu sterownika ekranu dotykowego okazało się zaskakująco proste. Wcześniej udało mi się z konsoli odczytać nazwę modułu sterownika, którą następnie wyszukałem i znalazłem w jednym pliku: drivers/input/touchscreen/cy8c_tma_ts.c
. Otworzyłem plik i zacząłem przeglądać.
Zaskakująco łatwo odkryłem też interesujący fragment: funkcję cy8c_ts_probe
, zawierającą odwołania do kodów zdarzeń, które wcześniej znajdowałem w internecie. Udało mi się z niej wywnioskować, jaki jest poprawny format zdarzeń przesyłanych do jądra. Okazało się, że jest on oczywiście kompletnie inny, niż w większości telefonów i dlatego przykłady, które znajdowałem, nic mi nie pomogły. Dowiedziałem się też dzięki niemu, co oznaczały kody wysyłane przez działającą resztkę ekranu - były to sygnały dotknięcia w jednym konkretnym punkcie i informacja o sile nacisku.
Znając już kody odpowiednich zdarzeń, przerobiłem nieco ADB Control, aby wysyłał te kody i symulował nimi kliknięcia oraz przeciągnięcia. Po drobnych poprawkach (okazało się, że ekran dotykowy używa innych współrzędnych, niż wyświetlacz, więc trzeba było je skalować) - sukces! Udało mi się wirtualnym przeciągnięciem odblokować ekran i zacząć przeglądać zawartość telefonu.
Niestety, potwierdziło się, że nie było już żadnych danych do odzyskania. Główny cel przepadł, ale przynajmniej czegoś się nauczyłem.
Morały
Po pierwsze, hackowanie rzeczy jest fajne! :p Walka ze sprzętem elektronicznym i powolne naginanie go do swojej woli była całkiem ekscytującym doświadczeniem.
Po drugie - Open Source jest super. Gdyby kod systemu telefonu nie był publicznie dostępny, nijak bym się nie dogrzebał do informacji o tym, jak właściwie symulować ekran dotykowy.
I po trzecie - nie ma co bać się kodu systemu. Wiadomo, system operacyjny robi zaawansowane rzeczy, ale ostatecznie jest to po program jak każdy inny. Jego kod z początku wygląda jak kompletny chaos, ale tak jest z każdym kodem, którego struktury się nie zna. Po chwili skupienia zaczyna się dostrzegać o co w tym wszystkim chodzi i można całkiem sporo zrozumieć. Oczywiście, spodziewam się, że sporą zasługę mają tu twórcy jądra Linuksa, którzy dbają o to, żeby kod był możliwie przejrzysty :)
Podsumowując - takie niskopoziomowe hackowanie sprzętu to fajna rozrywka, przy której można się wiele nauczyć. Polecam! ;)