Cycript vs. Frida

Przy testowaniu aplikacji na iOS bardzo przydatny jest cycript. Ma on jednak jedną wadę – nie można “wstrzyknąć się” do procesu, który jest dopiero tworzony. Kiedy to jest potrzebne? Na przykład wtedy, gdy aplikacja przeprowadza jailbreak detetection i chcielibyśmy ten test oszukać.

Rozwiązaniem tego problemu może być użycie narzędzia Frida, które pozwala uruchomić proces i jednocześnie wstrzyknąć nasz skrypt, który pożądane modyfikacje wprowadzi.

Frida ma swoje wady, dość kiepską dokumentację, nie do końca działa na iOS7 (w moim przypadku cały binding do ObjC nie działa w iOS7), ale jeśli do czynienia mamy z iOS8 to zwykle działa zgodnie z oczekiwaniami.

Dwie uwagi. Po pierwsze jeśli nie chcesz zaśmiecać swojego komputera iTunes możesz skorzystać skorzystać z połączenia TCP zamiast połączenia urządzenia przez USB. Co prawda na stronie porada ta jest w kontekście Linuksa, ale nie ma to znaczenia:

There's not yet any usbmuxd integration, so in the meantime you can use WiFi and set up an SSH tunnel between localhost:27042 in both ends, and then use -R instead of -U (just like on Android).

Po drugie zamiast podmieniać implementację metody tak naprawdę zwykle wystarczy zmienić wartości do niej przekazywane lub przez nie zwracane. W przypadku Fridy oznacza to, że zamiast bawić się w zmiany implementacji przez ObjC.implement dużo łatwiej skorzystać jest z Interceptor.attach i wprowadzać potrzebne modyfikacje przez onEnter lub onLeave.

Większość potrzebnych informacji można znaleźć w dokumentacji na stronie, przy czym warto przejrzeć ją całą, a nie tylko fragment odnośnie ObjC.

Na koniec – dwa przykłady oparte na Damn Vulnerable iOS Application (DVIA).

Pierwszy przykład – podmiana wartości zwracanej przez metodę instancji:

var JailbreakDetectionVC = ObjC.classes.JailbreakDetectionVC; var isJailbroken = JailbreakDetectionVC['– isJailbroken'];

Interceptor.attach(sJailbroken.implementation, { onLeave: function(retval) { retval.replace(ptr(“0x0”)); } });

Przykład drugi – podmiana wartości przekazywanej do metody (w tym wypadku – klasy):

var DamnVulnerableAppUtilities = ObjC.classes.DamnVulnerableAppUtilities; var showAlertForJailbreakTestIsJailbroken_ = DamnVulnerableAppUtilities.showAlertForJailbreakTestIsJailbroken_;

Interceptor.attach(showAlertForJailbreakTestIsJailbroken_.implementation, { onEnter: function(args) { args[2] = ptr(“0x0”); } });

I tak, wiem – można to zrobić na wiele innych sposobów, ale ten ma jedną bardzo istotną zaletę. Można z niego skorzystać z Windows / Linuks, nie trzeba mieć OS X (i XCode).

P.S. Mała aktualizacja co do iOS7 – działa, pod warunkiem, że korzysta się z frida-server do wersji 5.0.1 od wersji 5.0.2 (lub 5.0.3, nie pamiętam teraz, nie chce mi się sprawdzać) binding do ObjC przestał działać. W praktyce okazuje się również, że są pewne różnice między tym, co wspierane jest w 5.0.10, a tym, co jest dostępne w 5.0.1. Przykład? findExportByName nie ma jeszcze opcji, by pierwszy argument był null. Być może różnic jest więcej, ale skoro dokumentacja jest jaka jest – ciężko powiedzieć co się jeszcze zmieniło między wersjami.

Oryginał tego wpisu dostępny jest pod adresem Cycript vs. Frida

Autor: Paweł Goleń