Ho iniziato a lavorarci su. Sto pubblicando i miei risultati finora qui come una risposta "wiki della comunità" per due motivi: primo, se qualcun altro vuole partecipare, c'è un posto dove parlare; secondo, se mi stacco da questo progetto, ci saranno suggerimenti per qualcun altro che inizi a lavorare.
La logica di backup sull'host è interamente contenuta in https://github.com/android/platform_system_core/blob/master/adb/commandline.cpp , nella funzione denominata backup
. La funzione è molto semplice: convalida le opzioni della riga di comando, invia il comando principalmente com'è al demone adb sul telefono e scrive l'output del telefono nel file. Non c'è nemmeno il controllo degli errori: se, ad esempio, si rifiuta il backup sul telefono, adb
scrive solo un file vuoto.
Al telefono, la logica di backup inizia service_to_fd()
in https://github.com/android/platform_system_core/blob/master/adb/services.cpp . La funzione identifica il comando dall'host "backup"
e passa il comando non analizzato a /system/bin/bu
, che è un banale script di shell da avviare com.android.commands.bu.Backup
come classe principale di un nuovo processo di app Android. Che chiama ServiceManager.getService("backup")
per ottenere il servizio di backup come IBackupManager
, e chiama IBackupManager.fullBackup()
, passandogli il descrittore di file ancora inutilizzato (molto indirettamente) collegato al backup.ab
file sull'host.
Il controllo passa al fullBackup()
di com.android.server.backup.BackupManagerService , che si apre la GUI che chiede all'utente di confermare / rifiutare il backup. Quando l'utente lo fa, acknowledgeFullBackupOrRestore()
viene chiamato (stesso file). Se l'utente approva la richiesta, acknowledgeFullBackupOrRestore()
scopre se il backup è crittografato e passa un messaggio a BackupHandler
(stesso file.) BackupHandler
Quindi crea un'istanza e dà il via a uno PerformAdbBackupTask
( stesso file, riga 4004 al momento della scrittura)
Iniziamo finalmente a generare output lì, inPerformAdbBackupTask.run()
, tra la linea 4151 e la linea 4330 .
Innanzitutto, run()
scrive un'intestazione, che consiste in 4 o 9 righe ASCII:
"ANDROID BACKUP"
- la versione del formato di backup: attualmente
"4"
- o
"0"
se il backup non è compresso o "1"
se si tratta di
- il metodo di crittografia: attualmente
"none"
o"AES-256"
- (se crittografato), la "password utente salt" codificata in esadecimale, tutto maiuscolo
- (se crittografato), il "sale di checksum della chiave master" codificato in esadecimale, tutto maiuscolo
- (se crittografato), il "numero di round PBKDF2 utilizzati" come numero decimale: attualmente
"10000"
- (se crittografato), il "IV della chiave utente" codificato in esadecimale, tutto maiuscolo
- (se crittografato), il "BLOB chiave IV + master, crittografato dalla chiave utente" codificato in esadecimale, maiuscolo
I dati di backup effettivo segue, sia in (a seconda della compressione e cifratura) tar
, deflate(tar)
, encrypt(tar)
, o encrypt(deflate(tar))
.
TODO : scrivi il percorso del codice che genera l'output tar - puoi semplicemente usare tar fintanto che le voci sono nell'ordine corretto (vedi sotto).
Formato archivio tar
I dati dell'app vengono archiviati nella directory app /, iniziando con un file _manifest, l'APK (se richiesto) in a /, i file app in f /, i database in db / e le preferenze condivise in sp /. Se hai richiesto il backup della memoria esterna (usando l'opzione -shared), ci sarà anche una directory condivisa / nell'archivio che contiene i file della memoria esterna.
$ 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
Dettagli di crittografia
- Una chiave AES 256 viene derivata dalla password di crittografia di backup utilizzando 10000 round di PBKDF2 con un salt a 512 bit generato casualmente.
- Una chiave master AES 256 viene generata casualmente
- Una "somma di controllo" della chiave principale viene generata eseguendo la chiave principale attraverso 10000 round di PBKDF2 con un nuovo sale a 512 bit generato casualmente.
- Viene generata una crittografia di backup casuale IV.
- IV, chiave master e checksum vengono concatenati e crittografati con la chiave derivata in 1. Il BLOB risultante viene salvato nell'intestazione come stringa esadecimale.
- I dati di backup effettivi vengono crittografati con la chiave principale e aggiunti alla fine del file.
Esempio di implementazione del pacchetto / decompressione del codice (produce / utilizza) archivi tar: https://github.com/nelenkov/android-backup-extractor
Alcuni maggiori dettagli qui: http://nelenkov.blogspot.com/2012/06/unpacking-android-backups.html
Script Perl per l'imballaggio / disimballaggio e il fissaggio di archivi rotti:
http://forum.xda-developers.com/showthread.php?p=27840175#post27840175