Skip to content

reverse engineering

PicoCTF 2019 – reverse engineering aplikacji Androida – część 3, ostatnia.

Zadanie 3 – zmiana, podpisanie i ponowna instalacjia aplikacji

Po dekompilacji pliku three.apk widzimy kod, który niezależnie od wyniku wywołuje metodę nope(), kawałek niżej widzimy też metodę yep()

return-object v0 zwróci nam napis „don’t wanna” i wydrukuje w aplikacji jako flagę, a my chcemy poznać wynik funkcji cilantro() z metody yep(). Zmieńmy zatem w linijce 25 wywołanie funkcji na inną.

Po zapisaniu zmian w aplikacji budujemy ją na nowo:

I instalujemy plik new_three.apk, żeby otrzymać błąd…

Problemem jest niepodpisana aplikacja .apk i to że mamy już taką aplikację zainstalowaną na emulatorze. Możemy poczytać o podpisywaniu aplikacji więcej w tym artykule, a ja w skrócie podam komendy które wygenerują nam klucz i podpiszą aplikację do użytku lokalnego.

Generowanie klucza (ważne jest to, żeby ścieżka do jdk/bin Javy była w zmiennej systemowej PATH, u mnie to C:\Program Files\Java\jdk1.8.0_211\bin).

1
keytool -genkey -v -keystore mycustomname.keystore -alias mycustom_alias -keyalg RSA -keysize 2048 -validity 10000

Musimy po tym przejść przez krótki generator i podać trochę danych (nie muszą być prawdziwe. Ci idioci tego nie sprawdzają 😉 )

Następnie podpisujemy aplikację gdy mamy już wygenerowany klucz:

1
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore mycustomname.keystore new_three.apk mycustom_alias

Powinniśmy otrzymać na koniec komunikat, że się udało:

Teraz możemy uruchomić naszą zmienioną aplikację na emulatorze i zobaczyć czy zadziałało.

Uwaga: zanim zainstalujemy aplikację na nowo musimy odinstalować starą ręcznie z emulatora androida (drag and drop do kosza z nią wystarczy). Chwilę po tym możemy cieszyć się flagą wpisując dowolne hasło:

Flaga zadania three.apk

Zadanie 4 – ostatnie

Zaczynamy od dekompilacji aplikacji four.apk

Metoda getFlag() jest dość skomplikowana i można by pokusić się o odwrócenie funkcji wyliczającej hasło, ale oczywiście breakpoint załatwi nam sprawę szybciej. Ustawiamy go na linię 228 pliku FlagstaffHill.smali i odpalamy aplikację

Widzimy hasło: alphabetsoup, którego nawet nie musieliśmy wyliczać odwracając skomplikowany kod. Ale… co stanie się po wpisaniu go do aplikacji? Kod zwróci obiekt v5, czyli napis „call it” w miejsce flagi. Hmmm, wygląda na to że programiści zapomnieli wywołać odpowiednią funkcję w tym miejscu…

Po analizie pliku widzimy w linii 16 tego pliku ciekawą metodę statyczną (to jest import z biblioteki zewnętrznej) cardamom().

1
.method public static native cardamom(Ljava/lang/String;)Ljava/lang/String;

Wywołajmy zatem poprawną metodę zmieniając liniję 234 . Nasz kod po zmianie powinien wyglądać tak:

Kompilujemy, podpisujemy i uruchamiamy aplikację (tak jak powyżej w zadaniu 3) wpisując tym razem poprawne hasło „alphabetsoup” i… flaga jest nasza.

W ten sposób rozwiązaliśmy wszystkie zadania picoCTF2019 dotyczące reverse engineeringu aplikacji na Androida.

Podsumowanie zadań

  1. Każdą aplikację androida możemy zdekompilować, przerobić i uruchomić zdalnie. Trzymanie jakichkolwiek sekretów (nawet zaszyfrowanych) w aplikacji udostępnionej klientowi jest nieskuteczne.
  2. Prawie każdy kod da się odwrócić (wyjątkiem są algorytmy hashujące)
  3. A nawet jak się nie da, to wystarczy ustawić w dobrym miejscu breakpoint.
  4. A jeżeli nie da się ustawić breakpointa, to zawsze można zmienić kod (np. if (userEntry == passwordHash) na if (userEntry != passwordHash)
  5. Nie ma idealnych zabezpieczeń dla aplikacji Androida, są tylko takie których złamanie zajmie więcej czasu (będzie bardziej kosztowne) niż zakup licencji…

Tym optymistycznym akcentem, zachęcam do udziału w kolejnych edycjach picoCTF wszystkich testerów i programistów. Spojrzenie z tej drugiej strony na aplikacje jest niezwykle rozwojowe 🙂

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

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.

picoCTF 2019 – podstawy reverse engineeringu dla Androida

Jakiś czas temu wystartowaliśmy w picoCTF 2019 i jako drużyna AvaHack zajęliśmy 381 miejsce na 23 tysiące zgłoszonych drużyn. Zawody CTF (capture the flag) polegają na grzebaniu w aplikacjach i wyszukiwaniu ich słabych punktów. W skrócie chodzi o to, żeby zdobyć flagę (którą jest ciąg znaków), które organizatorzy sprytnie pochowali w różnych miejscach aplikacji (używając do tego różnych sposobów ukrywania lub szyfrowania tychże flag).

Chcę się podzielić rozwiązaniami zadań z działu reverse engineering aplikacji Androida. Jest to o tyle ważne dla testerów, że właśnie te zawody uświadomiły mi na jakie problemy (bezpieczeństwa i jakości) możemy natrafić podczas testowania aplikacji mobilnych.

Wszystkie 5 zadań (aplikacji androida) można pobrać stąd: http://scvconsultants.com/apk/.

Read More →