Friday, February 1, 2013

Access Android app data without root

Recently I recommended a certain data collecting Android app to my coworker. The application was great, but it was designed to upload collected data to the cloud and didn't offer any means to export or backup information locally.

This isn't an issue on my rooted Galaxy Nexus. Usually, I connect my phone to my computer with USB cable, open CLI and do the following, where app.package.name should be replaced with the actual package name of the application:

adb shell
su
cp /data/data/app.package.name/databases/application.sqlite /sdcard/
exit
exit
adb pull /sdcard/application.sqlite ~/

Update: after I've discovered this neat trick, the above can be reduced to one line:

adb shell su -c cat /data/data/app.package.name/databases/application.sqlite | sed 's/\r$//' > application.sqlite

On my coworker's phone, however, this wouldn't work since he was using a stock, non-rooted Android OS.

I Googled around for a solution and seemingly found one. If the application, whose data you wish to access, is debuggable, its read-protected folder can be accessed with the help of the run-as command. In essence, we pretend to be the application in question and copy file(s) stored inside the application's data folder into user readable folder like so:

adb shell
run-as app.package.name \
cp /data/data/package.name/databases/application.sqlite /sdcard/
exit
adb pull /sdcard/application.sqlite ~/

Unfortunately, in this case the application was not debuggable, so the method above did not work either. It appeared that reading Android application data folder with root access was impossible...

At this point I remembered that starting with Android v4.0 (Ice Cream Sandwich) Google has provided a way to backup data and applications from Android devices without root via adb. So all I had to do in order to pull that application's data from the device is to run:

adb backup -f ~/data.ab -noapk app.package.name

This will prompt you to "unlock your device and confirm the backup operation". To keep things simple do not provide a password, otherwise you will have to jump through the hoops to decrypt it later. Just click on "Back up my data" button. The screen will display the name of the package you're backing up, then close by itself upon successful completion.


The resulting ".ab" file contains application data in android backup format, which, thanks to +Nikolay Elenkov, is very well explained and documented in his excellent blog post. Basically, it's a tar archive that has been run through deflate and optionally encrypted (in a somewhat peculiar way) by AES-256-CRC cypher. Nikolay even went as far as to write a convenient Java program that can pack and unpack such Android backups with and without encryption.

To quickly extract a simple non-encrypted backup (you did omit the backup password as I suggested, didn't you?) run:

dd if=data.ab bs=1 skip=24 | openssl zlib -d | tar -xvf -

Update: It was brought to my attention that not all openssl installations are compiled with zlib support. Here's an alternative one-liner that makes use of python to achieve the same result:

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

The result is the apps/app.package.name/ folder containing application data, such as SQLite database I was particularly interested in and the application preferences.

Enjoy!

Update: A few people mentioned in comments below and on StackOverflow that this method doesn't work if application developer has explicitly disabled ability to backup his app by setting android:allowBackup="false" in the application manifest.