Daran habe ich angefangen zu arbeiten. Ich veröffentliche meine Ergebnisse hier aus zwei Gründen als "Community-Wiki" -Antwort: Erstens, wenn jemand anderes mitmachen möchte, gibt es einen Ort zum Reden. Zweitens, wenn ich von diesem Projekt zurückgezogen werde, gibt es Hinweise, damit jemand anderes anfängt zu arbeiten.
Die Sicherungslogik auf dem Host ist in der genannten Funktion vollständig in https://github.com/android/platform_system_core/blob/master/adb/commandline.cpp enthalten backup
. Die Funktion ist sehr einfach: Sie validiert die Befehlszeilenoptionen, sendet den Befehl zumeist unverändert an den ADB-Daemon auf dem Telefon und schreibt die Ausgabe des Telefons in die Datei. Es gibt nicht einmal eine Fehlerprüfung: Wenn Sie beispielsweise die Sicherung auf dem Telefon ablehnen, adb
schreiben Sie einfach eine leere Datei aus.
Am Telefon, startet die Backup - Logik in service_to_fd()
in https://github.com/android/platform_system_core/blob/master/adb/services.cpp . Die Funktion "backup"
erkennt /system/bin/bu
, dass der Befehl vom Host stammt , und übergibt den nicht analysierten Befehl an. Hierbei handelt es sich um ein einfaches Shell-Skript , das com.android.commands.bu.Backup
als Hauptklasse eines neuen Android-App-Prozesses gestartet werden soll. Das ruft ServiceManager.getService("backup")
auf, um den Sicherungsdienst als abzurufen IBackupManager
, und ruft auf IBackupManager.fullBackup()
und übergibt ihm den noch nicht verwendeten Dateideskriptor (sehr indirekt), der mit der backup.ab
Datei auf dem Host verbunden ist.
Die Steuerung geht zu fullBackup()
in com.android.server.backup.BackupManagerService , die die GUI dem Benutzer zu bestätigen / verwerfen die Sicherung zu fragen erscheint. Wenn der Benutzer dies tut, wird acknowledgeFullBackupOrRestore()
(dieselbe Datei) aufgerufen. Wenn der Benutzer die Anforderung genehmigt hat, stellt er fest acknowledgeFullBackupOrRestore()
, ob die Sicherung verschlüsselt ist, und übergibt eine Nachricht an BackupHandler
(dieselbe Datei). BackupHandler
Anschließend wird eine Instanz erstellt und gestartet PerformAdbBackupTask
( dieselbe Datei, Zeile 4004 zum Zeitpunkt des Schreibens).
Wir beginnen dortPerformAdbBackupTask.run()
zwischen Zeile 4151 und Zeile 4330 mit der Ausgabe .
Zuerst run()
schreibt einen Header, der von entweder 4 oder 9 ASCII Zeilen besteht:
"ANDROID BACKUP"
- die Backup-Format-Version: derzeit
"4"
- Entweder
"0"
wenn die Sicherung nicht komprimiert ist oder "1"
wenn dies der Fall ist
- die Verschlüsselungsmethode: derzeit entweder
"none"
oder"AES-256"
- (falls verschlüsselt), das "Benutzerpasswort Salt" in hexadezimaler Schreibweise, alle Großbuchstaben
- (falls verschlüsselt), das in hexadezimaler Schreibweise codierte "Hauptschlüssel-Prüfsummensalz", alle Großbuchstaben
- (falls verschlüsselt), die "Anzahl der verwendeten PBKDF2-Runden" als Dezimalzahl: aktuell
"10000"
- (falls verschlüsselt), die "IV des Benutzerschlüssels" in hexadezimaler Schreibweise mit Großbuchstaben
- (falls verschlüsselt), das "Master-IV + -Schlüssel-Blob, verschlüsselt durch den Benutzerschlüssel", hexadezimal codiert, alle Großbuchstaben
Die eigentlichen Sicherungsdaten folgen, entweder als (je nach Kompression und Verschlüsselung) tar
, deflate(tar)
, encrypt(tar)
, oder encrypt(deflate(tar))
.
TODO : Schreiben Sie den Codepfad auf, der die tar-Ausgabe generiert - Sie können einfach tar verwenden, solange die Einträge in der richtigen Reihenfolge sind (siehe unten).
Tar-Archivformat
App-Daten werden im Verzeichnis app / gespeichert, beginnend mit einer _manifest-Datei, der APK (falls angefordert) in einem /, App-Dateien in f /, Datenbanken in db / und gemeinsamen Einstellungen in sp /. Wenn Sie eine externe Speichersicherung angefordert haben (mit der Option -shared), befindet sich im Archiv auch ein freigegebenes Verzeichnis /, das externe Speicherdateien enthält.
$ tar tvf mybackup.tar
-rw------- 1000/1000 1019 2012-06-04 16:44 apps/org.myapp/_manifest
-rw-r--r-- 1000/1000 1412208 2012-06-02 23:53 apps/org.myapp/a/org.myapp-1.apk
-rw-rw---- 10091/10091 231 2012-06-02 23:41 apps/org.myapp/f/share_history.xml
-rw-rw---- 10091/10091 0 2012-06-02 23:41 apps/org.myapp/db/myapp.db-journal
-rw-rw---- 10091/10091 5120 2012-06-02 23:41 apps/org.myapp/db/myapp.db
-rw-rw---- 10091/10091 1110 2012-06-03 01:29 apps/org.myapp/sp/org.myapp_preferences.xml
Details zur Verschlüsselung
- Ein AES 256-Schlüssel wird aus dem Sicherungsverschlüsselungskennwort unter Verwendung von 10000 Runden PBKDF2 mit einem zufällig erzeugten 512-Bit-Salt abgeleitet.
- Ein AES 256-Hauptschlüssel wird zufällig generiert
- Eine Hauptschlüssel-Prüfsumme wird generiert, indem der Hauptschlüssel durch 10000 Runden von PBKDF2 mit einem neuen, zufällig generierten 512-Bit-Salt ausgeführt wird.
- Eine zufällige Sicherungsverschlüsselung IV wird generiert.
- Die IV, der Hauptschlüssel und die Prüfsumme werden mit dem in 1 abgeleiteten Schlüssel verknüpft und verschlüsselt. Der resultierende Blob wird im Header als Hex-Zeichenfolge gespeichert.
- Die eigentlichen Sicherungsdaten werden mit dem Hauptschlüssel verschlüsselt und an das Dateiende angehängt.
Beispiel für das Packen / Entpacken von Code-Implementierungen (produziert / verwendet) von Tar-Archiven: https://github.com/nelenkov/android-backup-extractor
Weitere Details hier: http://nelenkov.blogspot.com/2012/06/unpacking-android-backups.html
Perl-Skripte zum Packen / Entpacken und Reparieren defekter Archive:
http://forum.xda-developers.com/showthread.php?p=27840175#post27840175