Comecei a trabalhar nisso. Estou postando meus resultados até agora aqui como uma resposta "wiki da comunidade" por dois motivos: primeiro, se alguém quiser participar, há um lugar para conversar; segundo, se eu me afastar desse projeto, haverá dicas para alguém começar a trabalhar.
A lógica de backup no host está totalmente contida em https://github.com/android/platform_system_core/blob/master/adb/commandline.cpp , na função nomeada backup
. A função é muito simples: valida as opções da linha de comando, envia o comando principalmente como está para o daemon adb no telefone e grava a saída do telefone no arquivo. Não há nem verificação de erros: se, por exemplo, você recusar o backup no telefone, adb
basta gravar um arquivo vazio.
No telefone, a lógica de backup inicia service_to_fd()
em https://github.com/android/platform_system_core/blob/master/adb/services.cpp . A função identifica que o comando do host é "backup"
e transmite o comando não analisado para /system/bin/bu
, que é um script de shell trivial para iniciar com.android.commands.bu.Backup
como a classe principal de um novo processo de aplicativo Android. Isso chama ServiceManager.getService("backup")
para obter o serviço de backup como IBackupManager
e chama IBackupManager.fullBackup()
, passando a ele o descritor de arquivo ainda não utilizado (muito indiretamente) conectado ao backup.ab
arquivo no host.
O controle passa para fullBackup()
em com.android.server.backup.BackupManagerService , que exibe a GUI solicitando ao usuário que confirme / rejeite o backup. Quando o usuário faz isso, acknowledgeFullBackupOrRestore()
(mesmo arquivo) é chamado. Se o usuário aprovou a solicitação, acknowledgeFullBackupOrRestore()
descobre se o backup está criptografado e passa uma mensagem para BackupHandler
(mesmo arquivo.), Em BackupHandler
seguida, instancia e inicia um PerformAdbBackupTask
( mesmo arquivo, linha 4004 no momento da gravação).
Finalmente começamos a gerar saída láPerformAdbBackupTask.run()
, entre as linhas 4151 e 4330 .
Primeiro, run()
escreve um cabeçalho, que consiste em 4 ou 9 linhas ASCII:
"ANDROID BACKUP"
- a versão do formato de backup: atualmente
"4"
- tanto
"0"
se o backup é descompactado ou "1"
se é
- o método de criptografia: atualmente um
"none"
ou"AES-256"
- (se criptografado), o "sal da senha do usuário" codificado em hexadecimal, todas as maiúsculas
- (se criptografado), o "sal da soma de verificação da chave mestra" codificado em hexadecimal, todas as maiúsculas
- (se criptografado), o "número de rodadas de PBKDF2 usadas" como um número decimal: atualmente
"10000"
- (se criptografado), o "IV da chave do usuário" codificado em hexadecimal, todas as maiúsculas
- (se criptografado), o "blob principal da chave IV +, criptografado pela chave do usuário" codificado em hexadecimal, todas as maiúsculas
Os dados de backup real segue, quer como (dependendo de compressão e de criptografia) tar
, deflate(tar)
, encrypt(tar)
, ou encrypt(deflate(tar))
.
TODO : escreva o caminho do código que gera a saída do tar - você pode simplesmente usar o tar desde que as entradas estejam na ordem correta (veja abaixo).
Formato de arquivo Tar
Os dados do aplicativo são armazenados no diretório app /, começando com um arquivo _manifest, o APK (se solicitado) em /, arquivos de aplicativo em f /, bancos de dados em db / e preferências compartilhadas em sp /. Se você solicitou um backup de armazenamento externo (usando a opção -shared), também haverá um diretório / compartilhado no arquivo que contém arquivos de armazenamento externo.
$ 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
Detalhes de criptografia
- Uma chave AES 256 é derivada da senha de criptografia de backup usando 10000 rodadas de PBKDF2 com um sal de 512 bits gerado aleatoriamente.
- Uma chave mestra AES 256 é gerada aleatoriamente
- Uma chave mestra 'checksum' é gerada executando a chave mestra por 10000 rodadas de PBKDF2 com um novo sal de 512 bits gerado aleatoriamente.
- Uma criptografia de backup aleatória IV é gerada.
- A IV, chave mestra e soma de verificação são concatenadas e criptografadas com a chave derivada em 1. O blob resultante é salvo no cabeçalho como uma sequência hexadecimal.
- Os dados de backup reais são criptografados com a chave mestra e anexados ao final do arquivo.
Exemplo de implementação de código de pacote / descompactação (produz / usa) arquivos tar: https://github.com/nelenkov/android-backup-extractor
Mais alguns detalhes aqui: http://nelenkov.blogspot.com/2012/06/unpacking-android-backups.html
Scripts Perl para empacotar / descompactar e corrigir arquivos quebrados:
http://forum.xda-developers.com/showthread.php?p=27840175#post27840175