picoCTF 2019 – reverse engineering aplikacji androida – one.apk i two.apk


Rozwiązania kolejnych zadań

Czas pokazać rozwiązania kolejnych zadań umieszczonych pod adresem: http://scvconsultants.com/apk/

Jeżeli chcesz ustawić środowisko, zajrzyj proszę o poprzedniego wpisu na moim blogu.

Zadanie 1 – hardkodowane stringi w aplikacji

Zaczynamy od dekompilacji aplikacji one.apk przy pomocy narzędzia apktool:

Dekompilacja aplikacji one.apk

Po czym otwieramy katalog one za pomocą IntelliJ:

Ustawiamy nasz katalog /one/smali przy pomocy komendy „Mark directory as -> Sources Root„.

MainActivity.smali z podkatalogu /one/smali/com.hellocmu.picoctf/ to klasa która odpalana jest jako punkt uruchomienia aplikacji Androida. Zajrzyjmy więc do niej:

MainActivity.smali

Po krótkiej analizie możemy zauważyć metodę buttonClick(), która wywołuję metodę getFlag z pliku FlagstaffHill.smali (ostatnia linijka kodu na screenshocie poniżej).

Przechodzimy więc do metody getFlag() w pliku FlagstaffHill.smali

Widzimy w nim stałą: const v0 – ta stała jest porównywana metodą if-eqz v1, :cond_0 z tym co zwraca metoda getString() z pola p1 (można się domyśleć, że jest to tekst który wpisze użytkownik w aplikacji).

(ctrl + shift + f w IntelliJ pokaże nam na co ta stała wskazuje). Po wyszukaniu widzimy obiecujące id stringa, o name=password:

Wyszukiwanie adresu 0x7f0b002f

Jeżeli hasła są równe (w linijce kodu if-eqz), to wywołana jest metoda fenugreek() z biblioteki libhellojni.so, która jak możemy podejrzewać ujawni nam flagę (wnioskuję to z poprzedniego zadania).

Zajrzyjmy jeszcze do pliku /res/values/strings.xml i zobaczmy jakie stałe zostały tam umieszczone:

strings.xml i zapisane stałe

To wygląda na hasło, które jest porównywane z tym co użytkownik wpisze. Zainstalujmy więc w naszym emulatorze aplikację one.apk i sprawdźmy co się stanie po wpisaniu hasła:

Et voila, flaga jest nasza.

Podsumowanie problemu

Trzymanie haseł jako czysty tekst w: bazach danych, aplikacjach androidowych, aplikacjach desktopowych to poważny błąd, który powinien zostać niezwłocznie zgłoszony i usunięty przez zespół developerów.

Każda stała w kodzie klienta jest domyślnie pakowana do binarki i musimy o tym pamiętać. Wyciągnięcie jej nie jest żadnych problemem.

Takie rzeczy można wyłapać na etapie Code Review i niezwłocznie zgłaszać sekrety w kodzie jako błędy P1 (o ile zależy nam na bezpieczeństwie).

Zadanie 2 – dobry breakpoint podstawą sukcesu

Zaczynamy od dekompilacji: apktool d two.apk i otwieramy folder przy pomocy IntelliJ ustawiając katalog smali Mark Directory as -> Sources Root. Jest to niezbędne do działania breakpointów.

Tym razem zobaczymy w metodzie getFlag() pliku FlagstaffHill.smali kilka czarownic z uniwersum Świata Dysku (sir Terrego Pratchetta). I dość skomplikowany na pierwszy rzut oka kod, który przerzuca metodami aput-object imiona czarownic 🙂 Przypominam Dalvik Opcodes gdyby ktoś chciał przeanalizować kod maszynowy na własną rękę.

Zdekompilowana klasa FlagstaffHill.smali z aplikacji two.apk

Tutaj mamy dwa rozwiąznia. Jedno, to prześledzić kod i go zrozumieć (lvl hard). Drugie – to ustawić dobrze breakpoint podczas wykonywania kodu aplikacji. Ja jestem leniwy, więc ustawiam breakpoint na linii 169:

if-eqz to porównanie, które w przypadku poprawnego sprawdzenia wywoła nam metodę sesame(string userEntry) z biblioteki libhellojni.so

Uruchomienie aplikacji i debugowanie

Po zainstalowaniu i uruchomieniu two.apk na emulatorze, IntelliJ + smali debugger (w poprzednim artykule opisałem jak to zrobić) pozwoli nam się podłączyć do procesu i ustawiać breakpointy.

IntelliJ Menu Run -> Attach Debugger to Android Process:

I widzimy uruchomiony proces w emulatorze Androida. Wybieramy com.hellocmu.picocft i klikamy ok:

Podłączanie debuggera do procesu odpalonego w emulatorze Androida

Przełączamy się do aplikacji (na emulatorze) i wpisujemy cokolwiek po czym klikamy myszką na guzik „HELLO I AM A BUTTON”. Breakpoint powinien nam zadziałać i zatrzymać się w linii 169:

Po przejściu do IntelliJ widzimy zmienną password, z którą porównywane jest to co wpisał użytkownik:

Breakpoint złapany! 🙂

Sprawdźmy czy to hasło faktycznie jest poprawne:

Flaga zadania two.apk

Podsumowanie problemu

Jakkolwiek skomplikowana byłaby metoda wyliczania zmiennej password, na niewiele się to zda, jeżeli w kodzie w pewnym momencie mamy warunek logiczny: if (userEntry==password). Wystarczy w odpowiednim momencie zatrzymać aplikację, odczytać z pamięci zmienną z którą porównujemy co wpisał użytkownik i nasze zabezpieczenie zostało złamane.


Kategoria: reverse engineering | security

Możliwość komentowania została wyłączona.