Skip to content

Instantly share code, notes, and snippets.

@jevakallio
Last active November 1, 2024 00:01
Show Gist options
  • Save jevakallio/452c54ef613792f25e45663ab2db117b to your computer and use it in GitHub Desktop.
Save jevakallio/452c54ef613792f25e45663ab2db117b to your computer and use it in GitHub Desktop.
`adb pull` from app data directory without root access

TL;DR;

com.package.name is your app identifier, and the file path is relative to the app user's home directory, e.g. '/data/user/0/com.package.name.

adb shell run-as com.package.name cp relative/path/file.ext /sdcard
adb pull /sdcard/file.ext

See long explanation below.

Problem

Trying to adb pull files from our app's directory fails with Permission denied, because the adb user doesn't have access to the home directory.

adb pull /data/user/0/com.package.name/file.ext

Error:

adb: error: failed to stat remote object '/data/user/0/com.package.name/file.ext': Permission denied

You can try to run adb as root first:

adb root

But on a non-rooted device, this fails with:

adbd cannot run as root in production builds`

Here's a workaround on how to download a file from the app data directory using run-as.

Long version

This explains the solution step by step.

Start a shell session on the device. All following commands will be executed in the shell session on your device.

adb shell

Assuming our app identifier is com.package.name, the app data directory is at /data/user/0/com.package.name.

You can try to list files in that directory:

ls /data/user/0/com.package.name

This should result in error:

ls: /data/user/0/com.package.name/: Permission denied

However, you can run a command using the com.package.name application identity with the run-as command

run-as com.package.name ls /data/user/0/com.package.name/

You should now see a directory listing, and you can find the file you want, and copy it to a directory on your device that doesn't require root access, e.g. /sdcard:

run-as com.package.name cp /data/user/0/com.package.name/file.ext /sdcard

We can then exit the adb shell:

exit

Back at our own computer, we can adb pull the file:

adb pull /sdcard/file.ext
@impvd
Copy link

impvd commented Aug 7, 2020

Awesome thanks, it works.

My additional note is we could make adb push in that way:

$ adb push VID_000.mp4 /sdcard/

$ adb shell run-as com.android.example.camera2.video cp /sdcard/VID_000.mp4 /data/user/0/com.android.example.camera2.video/files/

$ adb shell run-as com.android.example.camera2.video ls /data/user/0/com.android.example.camera2.video/files
VID_000.mp4

@lovelyplanet2019
Copy link

i hit the run-as: package not debuggable when run
run-as com.package.name ls /data/user/0/com.package.name/

@hmoffatt
Copy link

I also have "package not debuggable" for everything I want to do.

@UlyssesAlves
Copy link

Perfect solution. Thank you!

@TomHejret
Copy link

This only works for Debug builds and, for a production app you will get "package not debuggable". :(

Another way is to use adb backup -f myapp.ab -apk com.myapp but that requires the app didn't "opt out of Backup" by declaring ALLOW_BACKUP:FALSE. https://android.stackexchange.com/questions/182381/is-it-possible-to-backup-and-restore-an-app-with-data-via-adb

@HawkElena
Copy link

HawkElena commented Jul 21, 2022

i have some trouble when trying to copy file into my package

1 step work well
adb -s mobil push C:\Users\droid\source\HawkStore.Android/InventoryDB1.db3 /sdcard/

2 step doen't work display an error Permission denied
adb -s mobil -d shell "run-as com.companyname.hawkstore cp /sdcard/InventoryDB1.db3
/data/user/0/com.companyname.hawkstore/files/.local/share/"

help me please if some body get the solution!

@UlyssesAlves
Copy link

UlyssesAlves commented Jul 21, 2022

@HawkElena using adb to access my app database was not a long term solution for me, so I ended up implementing a troubleshooting screen on my app. This screen is only available when the app is in debug mode, so the end users don't have access to it once I publish release versions on the app stores.

This tourbleshooting screen allows me to make simple queries, like listing all objects in the database, quering some specific tables, etc. It has been particularly very useful for debuging migrations of the database.

If ADB is not being very productive for you, creating a troubleshooting screen could be an alternative for you too.

@listvin
Copy link

listvin commented Sep 28, 2023

For those who facing package not debuggable for release build.
IF: debug have same package name and signed with same key as release (which is not recommended in some cases)
You can install debug build and access the files in same way after that.
Unless your file is not recreated/rewritten/modified_in_interfering_way on app start, do not run.

Bonus track: one-liner for linux/macos
adb shell "run-as $package base64 '$1'" | base64 -d > "$save_as"
Base64 ensures that binary file is not affected with any adb/\n shenanigans

@tuanchauict
Copy link

tuanchauict commented Oct 8, 2023

I have searched for a way to pull and push data from the app's folder for 3 years (since I wrote this note). From Android 10, using cp to copy files from the app's folder to the common space (eg. /sdcard) won't work anymore.

Recently, when I had to update my scripts to make them able to sync files from the device into the PC, the script by @listvin gave me a hint and helped me find out dd command, which I guess is the command Android Studio uses for the "Save" and "Upload" functions on "Device Explorer".

# Pull
adb shell "run-as $package dd if=$1" | dd of=$2

# Push
dd of=$1 | adb shell "run-as $package dd of="$2"

(Using base64 -d > file won't work with Push flow)

If you are interested, I summarize what I learned in this note: https://iamtuna.org/2023-10-08/use-adb-backup-restore-local-data-2

@crok
Copy link

crok commented Oct 9, 2023

# Pull
adb shell "run-as $package dd if=$1" | dd of=$2

# Push
dd of=$1 | adb shell "run-as $package dd of="$2"

The one and only thing that prevents users to make proper backups with this method is that run-as only works with apps that has debuggable set enabled in their Android manifest :\ It does work for you because your RC and dev. builds are definitely has debuggable enabled. Or in case the ROM has an implementation that does not respect the debuggable flag..
Anyway, thank you for the info and effort you put into the this and your article.

@kdrkdrkdr
Copy link

kdrkdrkdr commented Oct 14, 2023

This script can make app debuggable!

apk_name=com.example
apk_location=$(adb shell pm list packages -f -3 | grep $apk_name | sed 's/.*:\(.*\).apk.*/\1/').apk
adb pull $apk_location original.apk
keytool -genkey -v -keystore resign.keystore -storepass androiddbg -alias androiddbg -dname "CN=Android Debug,O=Android,C=US"
python make_debuggable.py apk original.apk patched.apk resign.keystore androiddbg
adb uninstall $apk_name
adb install patched.apk

Push file example!

tmp="/data/local/tmp"
adb push /home/Desktop/a.txt $tmp
adb shell run-as com.example cp $tmp $dst

Pull file example!

app="com.example"
adb -d shell "run-as $app cat /data/user/0/$app/file.txt" > file.txt

@gokaybiz
Copy link

This script can make app debuggable!

apk_name=com.example
apk_location=$(adb shell pm list packages -f -3 | grep $apk_name | sed 's/.*:\(.*\).apk.*/\1/').apk
adb pull $apk_location original.apk
keytool -genkey -v -keystore resign.keystore -storepass androiddbg -alias androiddbg -dname "CN=Android Debug,O=Android,C=US"
python make_debuggable.py apk original.apk patched.apk resign.keystore androiddbg
adb uninstall $apk_name
adb install patched.apk

Push file example!

tmp="/data/local/tmp"
adb push /home/Desktop/a.txt $tmp
adb shell run-as com.example cp $tmp $dst

Pull file example!

app="com.example"
adb -d shell "run-as $app cat /data/user/0/$app/file.txt" > file.txt

https://github.com/julKali/makeDebuggable/raw/master/makeDebuggable.py

@mickael28
Copy link

mickael28 commented Mar 17, 2024

@kdrkdrkdr @gokaybiz @jevakallio , with this script getting this error, any idea what it could be pls?

https://github.com/julKali/makeDebuggable/raw/master/makeDebuggable.py

python make_debuggable.py apk original.apk patched.apk resign.keystore androiddbg

File "D:\Temp\APKs-for-NvidiaShield\apks\adb\make_debuggable.py", line 611, in
patchApk(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6])
~~~~~~~~^^^
IndexError: list index out of range

Bypassed the error adding 'androiddbg' at the end, but then it fails with:

$ python make_debuggable.py apk original.apk patched.apk resign.keystore androiddbg androiddbg

17324808 res/raw/wallpaper.apk (OK)
19083357 res/xml/components.xml (OK - compressed)
19084178 res/xml/network_security_config.xml (OK - compressed)
19084553 res/xml/nimble_log.xml (OK - compressed)
19084744 resources.arsc (OK)
Verification succesful
Exception in thread "main" java.security.InvalidKeyException: Failed to sign using signer "ANDROIDD"
at com.android.apksig.internal.apk.v1.V1SchemeSigner.signManifest(V1SchemeSigner.java:293)
at com.android.apksig.internal.apk.v1.V1SchemeSigner.sign(V1SchemeSigner.java:254)
at com.android.apksig.DefaultApkSignerEngine.outputJarEntries(DefaultApkSignerEngine.java:933)
at com.android.apksig.ApkSigner.sign(ApkSigner.java:551)
at com.android.apksig.ApkSigner.sign(ApkSigner.java:223)
at com.android.apksigner.ApkSignerTool.sign(ApkSignerTool.java:395)
at com.android.apksigner.ApkSignerTool.main(ApkSignerTool.java:92)
Caused by: java.security.InvalidKeyException: Failed to sign using SHA1withDSA
at com.android.apksig.internal.apk.v1.V1SchemeSigner.generateSignatureBlock(V1SchemeSigner.java:516)
at com.android.apksig.internal.apk.v1.V1SchemeSigner.signManifest(V1SchemeSigner.java:291)
... 6 more
Caused by: java.security.InvalidKeyException: The security strength of SHA-1 digest algorithm is not sufficient for this key size
at sun.security.provider.DSA.checkKey(DSA.java:111)
at sun.security.provider.DSA.engineInitSign(DSA.java:143)
at java.security.Signature$Delegate.init(Signature.java:1155)
at java.security.Signature$Delegate.chooseProvider(Signature.java:1115)
at java.security.Signature$Delegate.engineInitSign(Signature.java:1179)
at java.security.Signature.initSign(Signature.java:530)
at com.android.apksig.internal.apk.v1.V1SchemeSigner.generateSignatureBlock(V1SchemeSigner.java:512)
... 7 more
Value of sys.argv[2]: original.apk
Patching AndroidManifest.xml ...
Found application tag at 7868 !
Found debuggable attribute!
Copying file ...
Copying rest of files
Using zipalign at .\zipalign.EXE
Aligning...
Verifying alignment...
Using apksigner at .\apksigner.BAT
Signing...
apksigner failed, aborting.

@netgoatfr
Copy link

Here is my fixed version:

apk_name=<app namp>
apk_location="$(adb shell pm list packages -f -3 | grep $apk_name | sed 's/.*:\(.*\).apk.*/\1/').apk"
adb pull $apk_location original.apk
keytool -genkey -v -keystore resign.keystore -storepass androiddbg -alias androiddbg -dname "CN=Android Debug,O=Android,C=US"
python make_debuggable.py apk original.apk patched.apk resign.keystore androiddbg androiddbg
adb uninstall $apk_name
adb shell settings put global verifier_verify_adb_installs 0
adb install patched.apk

This is bash code btw

@briandyy
Copy link

briandyy commented Nov 1, 2024

this will remove the file data before backed up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment