Saya mulai mengerjakan ini. Saya memposting hasil saya sejauh ini di sini sebagai jawaban "komunitas wiki" karena dua alasan: pertama, jika orang lain ingin bergabung, ada tempat untuk berbicara; kedua, jika saya ditarik dari proyek ini, akan ada petunjuk bagi orang lain untuk mulai bekerja.
Logika cadangan pada host sepenuhnya terkandung dalam https://github.com/android/platform_system_core/blob/master/adb/commandline.cpp , dalam fungsi yang bernama backup
. Fungsi ini sangat sederhana: memvalidasi opsi baris perintah, mengirim perintah sebagian besar apa adanya ke adb daemon di telepon, dan menulis output telepon ke file. Bahkan tidak ada pengecekan kesalahan: jika, misalnya, Anda menolak cadangan di telepon, adb
cukup tuliskan file kosong.
Di telepon, logika cadangan dimulai service_to_fd()
di https://github.com/android/platform_system_core/blob/master/adb/services.cpp . Fungsi ini mengidentifikasi bahwa perintah dari tuan rumah adalah "backup"
, dan meneruskan perintah yang tidak diuraikan ke /system/bin/bu
, yang merupakan skrip shell sepele untuk diluncurkan com.android.commands.bu.Backup
sebagai kelas utama dari proses aplikasi Android baru. Itu panggilan ServiceManager.getService("backup")
untuk mendapatkan layanan cadangan sebagai IBackupManager
, dan panggilan IBackupManager.fullBackup()
, melewati itu deskriptor file yang masih tidak digunakan (sangat tidak langsung) terhubung ke backup.ab
file di host.
Kontrol berpindah ke fullBackup()
dalam com.android.server.backup.BackupManagerService , yang muncul pada GUI yang meminta pengguna untuk mengonfirmasi / menolak cadangan. Ketika pengguna melakukannya, acknowledgeFullBackupOrRestore()
(file yang sama) dipanggil. Jika pengguna menyetujui permintaan tersebut, mencari acknowledgeFullBackupOrRestore()
tahu apakah cadangan dienkripsi, dan meneruskan pesan ke BackupHandler
(file yang sama.) BackupHandler
Kemudian instantiate dan memulai PerformAdbBackupTask
( file yang sama, baris 4004 pada saat penulisan)
Kami akhirnya mulai menghasilkan output di sana, diPerformAdbBackupTask.run()
, antara baris 4151 dan baris 4330 .
Pertama, run()
tulis header, yang terdiri dari 4 atau 9 baris ASCII:
"ANDROID BACKUP"
- versi format cadangan: saat ini
"4"
- baik
"0"
jika cadangan tidak terkompresi atau "1"
jika itu
- metode enkripsi: saat ini
"none"
atau"AES-256"
- (jika dienkripsi), "garam kata sandi pengguna" disandikan dalam hex, semuanya huruf besar
- (jika dienkripsi), "master checksum salt" dikodekan dalam hex, semuanya caps
- (jika dienkripsi), "jumlah putaran PBKDF2 digunakan" sebagai angka desimal: saat ini
"10000"
- (jika dienkripsi), "IV kunci pengguna" dikodekan dalam hex, semua huruf besar
- (jika dienkripsi), "master IV + gumpalan kunci, dienkripsi oleh kunci pengguna" dikodekan dalam hex, semua huruf besar
Backup data aktual berikut, baik sebagai (tergantung pada kompresi dan enkripsi) tar
, deflate(tar)
, encrypt(tar)
, atau encrypt(deflate(tar))
.
TODO : tulis jalur kode yang menghasilkan keluaran tar - Anda bisa menggunakan tar selama entri berada dalam urutan yang benar (lihat di bawah).
Format arsip tar
Data aplikasi disimpan di bawah direktori app /, dimulai dengan file _manifest, APK (jika diminta) di file a, file aplikasi di f /, database di db / dan preferensi bersama di sp /. Jika Anda meminta cadangan penyimpanan eksternal (menggunakan opsi-shared), juga akan ada direktori / shared dalam arsip yang berisi file penyimpanan eksternal.
$ 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
Detail enkripsi
- Kunci AES 256 berasal dari kata sandi enkripsi cadangan menggunakan 10000 putaran PBKDF2 dengan garam 512 bit yang dihasilkan secara acak.
- Kunci master AES 256 dibuat secara acak
- Kunci master 'checksum' dihasilkan dengan menjalankan kunci utama melalui 10.000 putaran PBKDF2 dengan garam 512 bit baru yang dihasilkan secara acak.
- Enkripsi cadangan acak IV dibuat.
- IV, kunci utama, dan checksum disatukan dan dienkripsi dengan kunci yang diturunkan dalam 1. Gumpalan yang dihasilkan disimpan di header sebagai string hex.
- Data cadangan aktual dienkripsi dengan kunci master dan ditambahkan ke akhir file.
Contoh paket / unpack implementasi kode (menghasilkan / menggunakan) arsip tar: https://github.com/nelenkov/android-backup-extractor
Beberapa detail lebih lanjut di sini: http://nelenkov.blogspot.com/2012/06/unpacking-android-backups.html
Skrip Perl untuk mengemas / membongkar dan memperbaiki arsip yang rusak:
http://forum.xda-developers.com/showthread.php?p=27840175#post27840175