
In einem
früheren Artikel habe ich eine Überprüfung von OWASP Mobile TOP 10 durchgeführt, und dann hatte ich keinen geeigneten Fall, um die Notwendigkeit des Schutzes des Quellcodes zu demonstrieren. Ein interessanter Demonstrationsfall ist erst kürzlich aufgetaucht. Wer sich für unsere Erfahrungen mit der Umgehung von Umweltkontrollen interessiert, sollte unter die Katze gehen.
Bei der Beurteilung der Leistung eines der Projekte stellte unser Team sofort fest, dass der Fall nicht einfach sein würde. Die Entwickler gingen das Problem der Informationssicherheit im Programm gut an und überprüften den Status der Ausführungsumgebung. Die Anwendung wurde unter keiner der folgenden Bedingungen gestartet:
- das Gerät wurde gerissen;
- ein Emulator wurde verwendet;
- Verfügbarkeit der Verbindung über USB;
- im Entwicklermodus.
Die Entwickler haben den Quellcode nicht verschleiert und es gab keine integrierte Überprüfung für Codeänderungen, die es mir ermöglichte, die Methoden zu analysieren, mit denen die Überprüfungen durchgeführt wurden, und die erforderlichen Manipulationen mit ihnen durchzuführen.
Also fangen wir an. Laut OWASP Mobile TOP 10, das wir als Basistestmethode bei Hacken, Reverse Engineering, verwenden, umfasst diese Sicherheitsanfälligkeit die Analyse von Binärdateien, um den Quellcode, Bibliotheken, Algorithmen usw. zu bestimmen. Software wie IDA Pro, Hopper, otool und andere Reverse Engineering-Tools können einen Eindruck vom internen Betrieb der Anwendung vermitteln. Dies kann verwendet werden, um nach Anwendungsschwachstellen zu suchen, wichtige Informationen wie einen Back-End-Server, Verschlüsselungsschlüssel oder geistiges Eigentum zu extrahieren.
Um eine grundlegende statische Analyse durchzuführen, verwendete ich ein so interessantes Tool wie MobSF, das eine Dekompilierung und eine grundlegende statische Analyse durchführte. Nach der Dekompilierung interessierte ich mich für die Java- und Smali-Codes des Programms. Für die Analyse wird Java-Code benötigt, und wir werden Änderungen am Smali-Code vornehmen. Weitere Details zur Beziehung zwischen Smali und Java finden Sie
hier .
Nachdem ich mir die Liste der Klassen angesehen hatte, fand ich eine Datei, die für die Überprüfung der Telefonroutine verantwortlich ist (siehe Abbildung 1) - rootingcheck / RootBeerNative.java.
Abb. 1. Liste der AnwendungsklassenNach der Analyse der Klasse wurde klar, dass wir weiter nach den Aufrufen der Funktionen checkForRoot () und setLogDebugMessage () suchen müssen (siehe Abbildung 2).
Abb. 2. Der Quellcode der Klasse zur Überprüfung auf RutovanostMit dem Befehl grep erhalten wir die folgenden Ergebnisse, die uns zeigen, welche Dateien den Aufruf der Methoden checkForRoot () und setLogDebugMessage () enthalten.
Suchergebnisse:root @ kali: ~ / Desktop # grep -nr 'RootBeerNative' ******** _ v_0.9.2 /
********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:1:.class public Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:17: sput-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:28: sput-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:57: sget-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/o/CM.smali:591: new-instance v1, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:593: invoke-direct {v1}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:685: new-instance v0, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:687: invoke-direct {v0}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:689: invoke-static {}, Lrootingcheck/RootBeerNative;->?()Z ********_v_0.9.2/smali/o/CM.smali:753: new-instance v4, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:755: invoke-direct {v4}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:764: invoke-virtual {v4, v3}, Lrootingcheck/RootBeerNative;->checkForRoot([Ljava/lang/Object;)I ********_v_0.9.2/smali/o/xZ$5.smali:257: new-instance v1, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/xZ$5.smali:259: invoke-direct {v1}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/xZ$5.smali:261: invoke-static {}, Lrootingcheck/RootBeerNative;->?()Z
root @ kali: ~ / Desktop # grep -nr 'setLogDebugMessages' ******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:599: invoke-virtual {v1, v0}, Lrootingcheck/RootBeerNative;->setLogDebugMessages(Z)I ********_v_0.9.2/smali/o/CM.smali:761: invoke-virtual {v4, v0}, Lrootingcheck/RootBeerNative;->setLogDebugMessages(Z)I
Dies waren jedoch nicht alle Schecks. Nach der Analyse der MainActivity.java-Klasse haben wir Funktionsaufrufe gefunden, bei denen die Zeichenfolgen "su", "test-keys" und "which" übergeben werden, mit deren Hilfe die Prüfung durchgeführt wird (siehe Abb. 3).
Abb. 3. RoutineprüfungenUnd wieder suchen wir mit dem Befehl grep in den smali-Dateien nach der Routine:
Suchergebnisse:root @ kali: ~ / Desktop # grep -nr 'su' ******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:443: const-string v2, "su" ********_v_0.9.2/smali/o/CM.smali:706: const-string v2, "su" ********_v_0.9.2/smali/o/xZ$5.smali:172: const-string v1, "su" ********_v_0.9.2/smali/o/xZ$5.smali:347: const-string v0, "su"
root @ kali: ~ / Desktop # grep -nr 'Testschlüssel' ******** _ v_0.9.2 / ********_v_0.9.2/smali/o/xZ$5.smali:141: const-string v1, "test-keys" ********_v_0.9.2/smali/o/xZ$5.smali:374: const-string v0, "test-keys"
root @ kali: ~ / Desktop # grep -nr 'which' ******** _ v_0.9.2 / ********_v_0.9.2/smali/o/CM.smali:437: const-string v2, "which"
In dem Artikel werde ich nur eine der gefundenen Modifikationen der Routineprüfungen zeigen. Nach einer kleinen Manipulation, nämlich dem Ändern von 1 auf 0, wurden die Routineprüfungen entfernt.
Abb. 4. Der Wert der Variablen ist gleich eins, wenn das Telefon gerootet ist
Abb. 5. Jetzt ist der Wert der Variablen Null, wenn das Telefon gerootet istDanach kann das Programm zusammengestellt, mit Ihrem Release-Schlüssel signiert und auf einem Mobiltelefon ausgeführt werden. Aber wenn nicht für zwei ABER! Nämlich:
- USB-Verbindungsprüfung;
- Überprüfung auf Einbeziehung des Entwicklermodus - Die USB-Verbindung und der enthaltene Entwicklermodus ermöglichen eine dynamische Analyse.
Die Überprüfung des Entwicklermodus wird auf die gleiche Weise wie die Routineprüfung deaktiviert - indem die Einheit in den Prüfungen auf Null gesetzt wird
In der MainActivity.java-Klasse finden wir die Zeile, die für die Überprüfung des Entwicklermodus verantwortlich ist (siehe Abbildung 6). Danach suchen wir mit grep nach Dateien, in denen die Zeichenfolge "development_settings_enabled" vorhanden ist, und ändern die Prüfung - ändern Sie 1 in 0 (siehe Abb. 7 und 8).
Abb. 6. Überprüfen Sie, ob der Entwicklermodus auf dem Telefon aktiviert istSuchergebnisse:grep -nr "development_settings_enabled" ******** _ v_0.9.2 \ Binary file ********_v_0.9.2\/build/apk/classes.dex matches ********_v_0.9.2\/smali/o/xZ$1.smali:49: const-string v1, "development_settings_enabled"
Abb. 7. Der Ort, an dem Sie die Änderung durchführen müssen
Abb. 8. ÄnderungNach allen Manipulationen können Sie das Programm im Entwicklermodus ausführen.
Schalten Sie als Nächstes die USB-Verbindungsprüfung aus. Diese Prüfung befindet sich in der Klasse MainActivity.java (siehe Abbildung 9). Ohne grep finden wir die Zeile in MainActivity.smali, wir finden die Zeile, die die Zeile mit dem USB-Check enthält - android.hardware.usb.action.USB_STATE. Danach ändern wir im smali-Code die Zeile in andere Berechtigungen, die "false" zurückgeben (siehe Abb. 10).
Abb. 9. Überprüfen Sie den MainActivity.java-Code auf USB-Verbindung
Abb. 10. Die Codezeile, die in MainActivity.smali gelöscht werden sollJetzt müssen Sie Ihren Release-Schlüssel generieren und die Anwendung damit signieren. Dies geschieht wie folgt:
- Sie müssen zwei Anwendungen installieren: Keytool und Jarsinger.
- Führen Sie den Befehl aus, um die Anwendung zusammenzustellen:
- apktool b C: \ Benutzer \ Benutzer \ Desktop \ ********
- Weiter: cd ******** \ dist \
- Weiter: Keytool.exe -genkey -alias key.keystore -keyalg RSA -validity 20000 -keystore key.keystore
- Weiter: Jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore key.keystore ********. Apk key.keystore
- Weiter: jarsigner -verify -verbose -certs ********. Apk
Hier sind prinzipiell alle Manipulationen abgeschlossen. Jetzt installieren wir die Anwendung mit adb install oder aus dem Smartphone-Verzeichnis auf dem Telefon und Sie können dynamische Schwachstellentests durchführen.
Führen Sie die Anwendung nach der Installation aus (siehe Abb. 11 und Abb. 12).
SchlussfolgerungenIn einem praktischen Beispiel habe ich gezeigt, wie Sie einige Überprüfungen des Laufzeitstatus deaktivieren können. Darüber hinaus haben wir mithilfe anderer Tools eine Analyse der Sicherheitsanfälligkeit durchgeführt, aber dies ist eine andere Geschichte ...
Was für eine nachlässige Haltung gegenüber dem Codeschutz kann führen zu:
- Dies sind Umgehungen bestimmter Prüfungen, die in das Programm eingebettet sind
- Implementierung von Code von Drittanbietern, wonach das Programm veröffentlicht und als bösartig verwendet werden kann
Wie kann ich mich schützen? Bei
ByteCode haben wir beschlossen, das Rad nicht neu zu erfinden, und vorgeschlagen, dass der Client den Quellcode verschleiert und Funktionen verwendet, die die Änderung des Quellcodes überprüfen.
PS
Sie können eine erweiterte Analysemethode verwenden - dies ist das kleine Debuggen. Weitere Informationen hierzu finden Sie im
Handbuch .
Ein wenig als Referenz formulierte ich eine Liste von Zeilen, die zur Überprüfung auf Routine verwendet werden:
- "Testschlüssel";
- "/system/app/Superuser.apk";
- "/ sbin / su";
- "/ system / bin / su";
- "/ system / xbin / su";
- "/ data / local / xbin / su";
- "/ data / local / bin / su";
- "/ system / sd / xbin / su";
- "/ system / bin / fehlersicher / su";
- "/ data / local / su";
- "/ su / bin / su";
- "/ system / xbin / which";
- "Su";
- "Welche".