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.