¿Cómo se pueden extraer los datos (privados) de la propia aplicación de Android?

97

Intentando extraer un solo archivo usando

adb pull /data/data/com.corp.appName/files/myFile.txt myFile.txt

falla con

failed to copy '/data/data/com.corp.appName/files/myFile.txt myFile.txt' to 'myFile.txt': Permission denied

a pesar de que la depuración USB está habilitada en el dispositivo.

Podemos dar la vuelta al problema por la ruta arcaica

adb shell
run-as com.corp.appName
cat files/myFile.txt > myFile.txt

pero esto es difícil de manejar para más de un archivo.

¿Cómo puedo extraer el directorio /data/data/com.corp.appName/files a mi MacBook?

Hacer esto ya sea directamente o mediante un tránsito en `/ storage / sdcard0 / myDir (desde donde puedo continuar con Android File Transfer) está bien.

Comentario adicional

Puede ser que solo corra

adb backup  -f myFiles com.corp.appName

generará los archivos que estoy buscando. En ese caso, estoy buscando una manera de descomprimir / descomprimir la copia de seguridad resultante.

Calaf
fuente
5
A menos que el dispositivo esté rooteado, simplemente no puede hacer eso.
323go
Espero que esté equivocado, pero por si acaso, mueva su comentario para que sea una respuesta. ¿Podría agregar algún tipo de referencia para respaldar por qué cree eso? Me gustaría guardar todos los archivos basura que las versiones con errores de mi programa han guardado para asegurarme en el futuro de que mi programa más cercano al lanzamiento manejará con gracia todo tipo de archivos de entrada.
Calaf
1
¿Significa eso que se podría modificar el directorio de world: - x to world: rx el tiempo suficiente para poder recuperar los archivos?
Calaf
1
@Knossos A pesar de que es mi aplicación, ¿no es legítimo que los usuarios puedan guardar una copia de los datos privados que una aplicación ha almacenado en sus dispositivos? Después de todo, presumiblemente los datos pertenecen al propietario del dispositivo, no al autor de la aplicación.
Calaf
1
El problema es cómo diferenciar entre el propietario y una aplicación / programa malicioso que intenta interactuar con los datos privados de su aplicación. (que podría tener datos personales de los usuarios)
Knossos

Respuestas:

101

adb backup escribirá un archivo específico de Android:

adb backup  -f myAndroidBackup.ab  com.corp.appName

Este archivo se puede convertir a formato tar usando:

dd if=myAndroidBackup.ab bs=4K iflag=skip_bytes skip=24 | openssl zlib -d > myAndroidBackup.tar

Referencia:

http://nelenkov.blogspot.ca/2012/06/unpacking-android-backups.html

Busque "Actualizar" en ese enlace.


Alternativamente, use el extractor de respaldo de Android para extraer archivos del archivo de respaldo de Android ( .ab).

Calaf
fuente
5
bs=24 skip=1es mucho más rápido que bs=1 skip=24(en mi sistema, 38,6 MB / s frente a 1,7 MB / s) :)
netvope
18
Alternativa de Python para donde openssl no se ha compilado con zlib: dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -(de la fuente anterior)
OJFord
6
Nunca he tenido éxito con el ddcomando en mi MacBook en el trabajo. En cambio, utilizo java -jar ./abe.jar unpack data.ab data.tar. Puede descargar la utilidad abe desde sourceforge.net/projects/adbextractor/files/?source=navbar
Someone Somewhere
3
Además, noté que tuve que forzar el cierre de la aplicación cuyos datos quiero respaldar, de lo contrario, ¡la copia de seguridad está vacía! (Android 4.4.2) Que es el mismo efecto que cuando se muestra el manifiestoandroid:allowBackup="false"
Alguien en algún lugar
2
Aún mejor, extraiga directamente los archivos en el directorio local:dd if=myAndroidBackup.ab bs=24 skip=1 | openssl zlib -d | tar -x
mreichelt
50

Tuve el mismo problema pero lo resolví ejecutando lo siguiente:

$ adb shell
$ run-as {app-package-name}
$ cd /data/data/{app-package-name}
$ chmod 777 {file}
$ cp {file} /mnt/sdcard/

Después de esto puedes correr

$ adb pull /mnt/sdcard/{file}
Trunst
fuente
1
¡gracias hombre! también necesita usar "cp -r" para convertirlo en una copia recursiva. stackoverflow.com/questions/39961621/…
朱 西西
31

Esto es lo que funcionó para mí:

adb -d shell "run-as com.example.test cat /data/data/com.example.test/databases/data.db" > data.db

Estoy imprimiendo la base de datos directamente en un archivo local.

Vinicius Avellar
fuente
3
Exactamente este comando hizo que mi archivo db se corrompiera. Pero lo hice funcionar con los siguientes pasos: ------ adb shell ------ dentro del shell ejecutar run-as com.example.test ------ dentro del shell ejecutar cat ...db > /mnt/sdcard/file.db------ adb pull /mnt/sdcard/file.db .------ end (lo siento, los saltos de línea no funcionan)
Kirill Oficerov
@KirillOficerov sería bueno si esos comandos se pueden escribir en una línea
emen
Genial cuando necesitas 1 archivo. He estado usando esto para la base de datos. Frente al caso ahora donde necesito varios archivos.
Dave Thomas
Por alguna razón, el uso adb shellno funcionó para mí, ¡pero seguir esta respuesta y usarlo adb exec-outfuncionó!
EpicPandaForce
21

En MacOSX, al combinar las respuestas de Calaf y Ollie Ford, lo siguiente funcionó para mí.

En la línea de comando (asegúrese de que adb esté en su camino, el mío estaba en ~ / Library / Android / sdk / platform-tools / adb) y con su dispositivo Android conectado y en modo de depuración USB, ejecute:

 adb backup -f backup com.mypackage.myapp

Su dispositivo Android le pedirá permiso para hacer una copia de seguridad de sus datos. Seleccione "COPIA DE SEGURIDAD DE MIS DATOS"

Espere unos momentos.

La copia de seguridad del archivo aparecerá en el directorio donde ejecutó adb.

Ahora ejecuta:

dd if=backup bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" > backup.tar

Ahora tendrá un archivo backup.tar que puede descomprimir así:

 tar xvf backup.tar

Y vea todos los archivos almacenados por su aplicación.

Eric Van Bezooijen
fuente
¡Tu versión para Mac funciona! NOTA: adb backuplos ddpasos de conversión de alquitrán y ambos no proporcionan ningún estado mientras funcionan y pueden tardar unos minutos si tiene muchos datos. ¡Se paciente!
MechEthan
2
Recibo: "zlib.error: Error -3 al descomprimir datos: comprobación de encabezado incorrecta" Sin embargo, mi copia de seguridad solicita una contraseña para cifrar. Este método de Python no solicita una contraseña para descifrar la copia de seguridad. El abe.jar en los comentarios del ejemplo anterior solicita una contraseña, pero no obtuve todos los archivos después de desarmar usando ese método.
Dave Thomas
Mi segundo intento con abe.jar en una copia de seguridad cifrada funcionó.
Dave Thomas
7

Las versiones más recientes de Android Studio incluyen el Explorador de archivos del dispositivo que me parece un método de GUI útil para descargar archivos de mi Nexus 7 de desarrollo.

Debe asegurarse de haber habilitado la depuración USB en el dispositivo

  1. Haga clic en Ver> Ventanas de herramientas> Explorador de archivos del dispositivo o haga clic en el botón Explorador de archivos del dispositivo en la barra de la ventana de herramientas para abrir el Explorador de archivos del dispositivo.
  2. Seleccione un dispositivo de la lista desplegable.
  3. Interactúe con el contenido del dispositivo en la ventana del explorador de archivos. Haga clic con el botón derecho en un archivo o directorio para crear un nuevo archivo o directorio, guarde el archivo o directorio seleccionado en su máquina, cargue, elimine o sincronice. Haz doble clic en un archivo para abrirlo en Android Studio.

    Android Studio guarda los archivos que abres de esta manera en un directorio temporal fuera de tu proyecto. Si realiza modificaciones en un archivo que abrió con el Explorador de archivos del dispositivo y desea guardar los cambios en el dispositivo, debe cargar manualmente la versión modificada del archivo en el dispositivo.

explorador de archivos

Documentación completa

Jon
fuente
6

Puede utilizar este script de shell a continuación. También puede extraer archivos del caché de la aplicación, no como la adb backupherramienta:

#!/bin/sh

if [ -z "$1" ]; then 
    echo "Sorry script requires an argument for the file you want to pull."
    exit 1
fi

adb shell "run-as com.corp.appName cat '/data/data/com.corp.appNamepp/$1' > '/sdcard/$1'"
adb pull "/sdcard/$1"
adb shell "rm '/sdcard/$1'"

Entonces puedes usarlo así:

./pull.sh files/myFile.txt
./pull.sh cache/someCachedData.txt
Tamas
fuente
10
La mejor parte es cuando no das argumentos y luego rm /sdcard/sustituyes, afortunadamente no es así -rf.
TWiStErRob
3
Puede simplemente conectar directamente a un archivo en el host: "adb shell run-as com.whatever.Fnord cat /data/data/com.whatever.Fnord/databases/logging.db> / tmp / foo" (donde / tmp / foo es un archivo en la máquina host, no en el dispositivo Android)
James Moore
Recién me di cuenta de que @ dave-thomas solucionó el problema hace un tiempo. Eliminando mi voto negativo.
Don Hatch
O no :-( "Su voto ahora está bloqueado a menos que se edite esta respuesta".
Don Hatch
TBH, no entiendo el alboroto por esto. El script (original) nunca habría eliminado el directorio (falta el interruptor -rf), a menos que estuviera vacío. No lo he verificado, pero incluso si el directorio está vacío, dudo que el script elimine el directorio ya que es un punto de montaje. El guión parecía peligroso, pero nunca lo fue ...
Tamas
5

Si está utilizando una máquina Mac y un teléfono Samsung, esto es lo que debe hacer (ya run-as que no funciona en Samsung y zlib no funciona en Mac)

  1. Realice una copia de seguridad del directorio de datos de su aplicación adb backup -f /Users/username/Desktop/data.ab com.example

  2. Se le pedirá una contraseña para cifrar en su teléfono, no ingrese ninguna. Simplemente toque "Hacer una copia de seguridad de mis datos". Consulte ¿Cómo realizar una copia de seguridad?

  3. Una vez que se haya realizado una copia de seguridad con éxito, verá el data.abarchivo en su escritorio. Ahora necesitamos convertir esto a tarformato.

  4. Utilice Android Backup Extractor para esto. Descarga | Código fuente

  5. Descárguelo y verá el abe.jararchivo. Agregue esto a su variable PATH.

  6. Ejecute esto para generar el archivo tar :java -jar abe.jar unpack /Users/username/Desktop/data.ab /Users/username/Desktop/data.tar

  7. Extraiga el archivo data.tar para acceder a todos los archivos

Enrique
fuente
2
Seguí esto exactamente y lo data.tarjusto se extrae a data.tar.cpgz@henry
usuario-44651
2

Esta respuesta se basa en mi experiencia con otras respuestas y comentarios en las respuestas. Mi esperanza es poder ayudar a alguien en una situación similar.

Estoy haciendo esto en OSX a través de la terminal.

Anteriormente, la respuesta de Vinicius Avellar funcionó muy bien para mí. La mayor parte del tiempo solo necesitaba la base de datos del dispositivo desde una aplicación de depuración.

Hoy tuve un caso de uso en el que necesitaba varios archivos privados . Terminé con dos soluciones que funcionaron bien para este caso.

  1. Utilice la respuesta aceptada junto con los comentarios específicos de OSX de Someone Somewhere. Cree una copia de seguridad y use la solución de terceros, sourceforge.net/projects/adbextractor/files/?source=navbar para descomprimir en un tar. Escribiré más sobre mi experiencia con esta solución al final de esta respuesta. Desplácese hacia abajo si esto es lo que está buscando.

  2. Una solución más rápida con la que me conformé. Creé un script para extraer varios archivos similar a la respuesta de Tamas. Puedo hacerlo de esta manera porque mi aplicación es una aplicación de depuración y tengo acceso a ejecutar como en mi dispositivo. Si no tiene acceso a ejecutar, este método no le funcionará en OSX.

Aquí está mi script para extraer varios archivos privados que compartiré con usted, el lector, que también está investigando esta increíble pregunta;):

#!/bin/bash
#
# Strict mode: http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'

# 
# Usage: script -f fileToPull -p packageName
# 

# This script is for pulling private files from an Android device
# using run-as. Note: not all devices have run-as access, and
# application must be a debug version for run-as to work.
# 
# If run-as is deactivated on your device use one of the
# alternative methods here:
# http://stackoverflow.com/questions/15558353/how-can-one-pull-the-private-data-of-ones-own-android-app
# 
# If you have encrypted backup files use:
# sourceforge.net/projects/adbextractor/files/?source=navbar 
# From comments in the accepted answer in the above SO question
# 
# If your files aren't encrypted use the accepted answer 
# ( see comments and other answers for OSX compatibility )
# 
# This script is open to expansions to allow selecting 
# device used. Currently first selected device from
# adb shell will be used.

#Check we have one connected device
adb devices -l | grep -e 'device\b' > /dev/null

if [ $? -gt 0 ]; then
    echo "No device connected to adb."
    exit 1
fi

# Set filename or directory to pull from device
# Set package name we will run as
while getopts f:p: opt; do
    case $opt in
        f)
            fileToPull=$OPTARG
            ;;
        p)
            packageName=$OPTARG
            ;;
    esac
done;

# Block file arg from being blank
if [ -z "$fileToPull" ]; then
    echo "Please specify file or folder to pull with -f argument"
    exit 1
fi

# Block package name arg from being blank
if [ -z "$packageName" ]; then
    echo "Please specify package name to run as when pulling file"
    exit 1
fi

# Check package exists
adb shell pm list packages | grep "$packageName" > /dev/null
if [ $? -gt 0 ]; then
    echo "Package name $packageName does not exist on device"
    exit 1
fi

# Check file exists and has permission with run-as
fileCheck=`adb shell "run-as $packageName ls $fileToPull"`
if [[ $fileCheck =~ "Permission denied" ]] || [[ $fileCheck =~ "No such file or directory" ]]; then
    echo "Error: $fileCheck"
    echo "With file -> $fileToPull"
    exit 1
fi

# Function to pull private file
#
# param 1 = package name
# param 2 = file to pull
# param 3 = output file
function pull_private_file () {

    mkdir -p `dirname $3`

    echo -e "\033[0;35m***" >&2
    echo -e "\033[0;36m Coping file $2 -> $3" >&2
    echo -e "\033[0;35m***\033[0m" >&2

    adb shell "run-as $1 cat $2" > $3
}

# Check if a file is a directory
# 
# param 1 = directory to check
function is_file_dir() {

    adb shell "if [ -d \"$1\" ]; then echo TRUE; fi"
}

# Check if a file is a symbolic link
# 
# param 1 = directory to check
function is_file_symlink() {

    adb shell "if [ -L \"$1\" ]; then echo TRUE; fi"
}

# recursively pull files from device connected to adb
# 
# param 1 = package name
# param 2 = file to pull
# param 3 = output file
function recurse_pull_private_files() {

    is_dir=`is_file_dir "$2"`
    is_symlink=`is_file_symlink "$2"`

    if [ -n "$is_dir" ]; then

        files=`adb shell "run-as $1 ls \"$2\""`

        # Handle the case where directory is a symbolic link
        if [ -n "$is_symlink" ]; then
            correctPath=`adb shell "run-as $1 ls -l \"$2\"" | sed 's/.*-> //' | tr -d '\r'`
            files=`adb shell "run-as $1 ls \"$correctPath\""`
        fi

        for i in $files; do

            # Android adds nasty carriage return that screws with bash vars
            # This removes it. Otherwise weird behavior happens
            fileName=`echo "$i" | tr -d '\r'` 

            nextFile="$2/$fileName"
            nextOutput="$3/$fileName"
            recurse_pull_private_files "$1" "$nextFile" "$nextOutput"
        done
    else

        pull_private_file "$1" "$2" "$3"
    fi
}

recurse_pull_private_files "$packageName" "$fileToPull" "`basename "$fileToPull"`"

Gist: https://gist.github.com/davethomas11/6c88f92c6221ffe6bc26de7335107dd4


Volver al método 1 , descifrar una copia de seguridad con Android Backup Extractor

Estos son los pasos que tomé en mi Mac y los problemas que encontré:

Primero puse en cola una copia de seguridad (y establecí una contraseña para cifrar mi copia de seguridad, mi dispositivo la requería):

adb backup -f myAndroidBackup.ab  com.corp.appName

En segundo lugar, descargué solo abe.jar desde aquí: https://sourceforge.net/projects/adbextractor/files/abe.jar/download

Luego corrí:

java -jar ./abe.jar unpack myAndroidBackup.ab myAndroidBackup.tar

En este punto recibí un mensaje de error. Debido a que mi archivo está encriptado, Java me dio un error que necesitaba para instalar algunas bibliotecas de políticas de seguridad.

  • Así que fui a http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html y descargué los archivos de política de seguridad que necesitaba. Ahora, en mi caso, las instrucciones de instalación me indicaron la ubicación incorrecta para colocar los archivos jar. Dice que la ubicación adecuada es <java-home> / lib / security . Los puse allí primero y todavía recibí el mensaje de error. Así que investigué y en mi Mac con Java 1.8 el lugar correcto para colocarlos era: <java-home> / jre / lib / security . Me aseguré de hacer una copia de seguridad de los archivos de políticas originales y los puse allí. Vola, pude ingresar una contraseña con abe.jar y descifrarla en un archivo tar.

Por último, acabo de ejecutar ( después de ejecutar el comando anterior nuevamente )

tar xvf myAndroidBackup.tar

Ahora es importante tener en cuenta que si puedes correr como y gato, es mucho más rápido. Uno, solo obtiene los archivos que desea y no la aplicación completa. Dos, cuantos más archivos (+ cifrado para mí), la transferencia es más lenta. Entonces, saber hacerlo de esta manera es importante si no tiene run-as en OSX, pero el script debe ir primero a una aplicación de depuración.

Eso sí, lo escribí hoy y lo probé varias veces, ¡así que notifícame de cualquier error!

Dave Thomas
fuente
1
Gracias a su respuesta con el método n. ° 1, pude obtener y explorar una copia de seguridad de un paquete de una aplicación de depuración de destino instalada en un dispositivo de producción no rooteado, pero la copia de seguridad solo contiene el archivo de manifiesto. Con el método n. ° 2, descargué todos los datos de la aplicación, pero los binarios (es decir, los archivos SQLite) no se pueden leer. Agrego una solución basada en su script que funcionó para mí.
Paolone
1

Después de configurar los permisos correctos agregando el siguiente código:

File myFile = ...;
myFile.setReadable(true, false); // readable, not only for the owner

adb pull funciona como se desee.

ver File.setReadable ()

18446744073709551615
fuente
Está bien cambiar los permisos durante la depuración, pero en algún momento cerca del lanzamiento, hacerlo anularía la protección ofrecida por defecto (para evitar que otras aplicaciones accedan / estropeen los archivos). Por lo tanto, es más deseable una forma para que el desarrollador acceda a los archivos aunque solo sean legibles por el usuario / escribibles.
Calaf
1

A partir del script de Dave Thomas, he podido escribir mi propia solución para superar 2 problemas:

  1. mi copia de seguridad solo contenía el archivo de manifiesto
  2. archivos binarios con Dave Thomas donde no se pueden leer

Este es mi script, que copia los datos de la aplicación a la tarjeta SD y luego lo extrae

#Check we have one connected device
adb devices -l | grep -e 'device\b' > /dev/null

if [ $? -gt 0 ]; then
    echo "No device connected to adb."
    exit 1
fi

# Set filename or directory to pull from device
# Set package name we will run as
while getopts f:p: opt; do
    case $opt in
        f)
            fileToPull=$OPTARG
            ;;
        p)
            packageName=$OPTARG
            ;;
    esac
done;

# Block package name arg from being blank
if [ -z "$packageName" ]; then
    echo "Please specify package name to run as when pulling file"
    exit 1
fi

# Check package exists
adb shell pm list packages | grep "$packageName" > /dev/null
if [ $? -gt 0 ]; then
    echo "Package name $packageName does not exist on device"
    exit 1
fi

    adb shell "run-as $packageName cp -r /data/data/$packageName/ /sdcard/$packageName"
    adb pull /sdcard/$packageName
    adb shell rm -rf /sdcard/$packageName
Paolone
fuente
1

Similar a la respuesta de Tamas , aquí hay una sola línea para Mac OS X para recuperar todos los archivos de la aplicación your.app.iddesde su dispositivo y guardarlos en (en este caso) ~/Desktop/your.app.id:

(
    id=your.app.id &&
    dest=~/Desktop &&
    adb shell "run-as $id cp -r /data/data/$id /sdcard" &&
    adb -d pull "/sdcard/$id" "$dest" &&
    if [ -n "$id" ]; then adb shell "rm -rf /sdcard/$id"; fi
)
  • Excluir el -dpara extraer del emulador
  • No pisotea las variables de tu sesión
  • Puede pegar todo el bloque en Terminal.app (o eliminar nuevas líneas si lo desea)
Zack Morris
fuente
0

Copia de seguridad de los datos del juego con apk . Turrón Oneplus 2.

**adb backup "-apk com.nekki.shadowfight" -f "c:\myapk\samsung2.ab"**
Samin
fuente
adb backup -f myapp.ab -apk com.myapp # backup on one device adb restore myapp.ab # restore to the same or any other device
Steven Linn
0

¿Significa eso que se podría modificar el directorio de world: - x to world: rx el tiempo suficiente para poder recuperar los archivos?

Sí exactamente. Curiosamente, también necesita el archivo para tener el xbit configurado. (al menos en Android 2.3)

chmod 755 Todo el camino hacia abajo funcionó para copiar un archivo (pero debe revertir los permisos después, si planea continuar usando el dispositivo).

serv-inc
fuente
0

tu puedes hacer:

adb pull / storage / emulated / 0 / Android / data //

Roi Bareket
fuente
2
No me malinterpretes, pero ¿has leído la pregunta correctamente? OP solicita extraer los datos 'privados', NO 'públicos'
baburao