Android emulator is really nice way to play with Android’s internals. Unfortunately at least those emulators, which have Play Store preinstalled, also don’t have root access via adb root
command. What is more, latest emulators started encrypting userdata partition, even if no lock mechanism is configured and there is no way to undo the encryption from inside the Android.
In this article, I will show how to gain access to emulator’s partitions from outside the emulator.
Note: I didn’t need to write anything, so I didn’t try to reencrypt the partition.
AVD structure
Before getting into encryption itself, let’s see quick summary of how to find emulator data and what to expect inside. On Linux all AVDs are stored at:
.android/avd/$NAME.avd
where $NAME
is name of the target AVD. Inside there are a few .img
files. In a good old days, inside there were all the data of the emulated devices. Now, they seem to be only base for the real partition image. These real device files are called almost the same, but with .qcow2
extension. In my case the interesting part looks like below:
cache.img cache.img.qcow2 encryptionkey.img encryptionkey.img.qcow2 sdcard.img sdcard.img.qcow2 userdata.img userdata-qemu.img userdata-qemu.img.qcow2
Interesting part is userdata-qemu
and encryptionkey
.
Mounting qcow2
qcow2 is format provided by qemu. Fortunately, along the support for emulated devices, there is a tool called qemu-nbd
, which allows to use qcow2 images in a similar way as losetup handles normal images. At first, we have to make sure nbd device is loaded into kernel:
sudo modprobe nbd max_part=8
Inserting it should cause nbd devices to appear under /dev filesystem:
$ ls -1 /dev/nbd* /dev/nbd0 /dev/nbd1 /dev/nbd10 /dev/nbd11 /dev/nbd12 /dev/nbd13 /dev/nbd14 /dev/nbd15 /dev/nbd2 /dev/nbd3 /dev/nbd4 /dev/nbd5 /dev/nbd6 /dev/nbd7 /dev/nbd8 /dev/nbd9
Now, we can connect our image to it with command like:
sudo qemu-nbd --connect=/dev/nbd0 userdata-qemu.img.qcow2
By the way following partition have to be connected. It will be needed in the next step:
sudo qemu-nbd --connect=/dev/nbd1 encryptionkey.img.qcow2
cryptfs footer
The mentioned partition contains is so called crypt footer. It stores parameters of encryption. Sometimes it may happen that it is appended to the partition itself (I don’t know on what it depends).
It would be easier to handle it from regular file, so let’s dump it:
dd if=/dev/nbd1 of=footer
Some tools I was using shows some information about the contents of this footer. It looks more or less like that:
Magic : 0xD0B5B1C4 Major Version : 1 Minor Version : 3 Footer Size : 104 bytes Flags : 0x00000000 Key Size : 128 bits Failed Decrypts: 0 Crypto Type : aes-cbc-essiv:sha256 Encrypted Key : 0xE94C81922869235354DEF01FA4D04C97 Salt : 0x921600CF57725700CB286378C333A019 ----------------
Meanwhile, I also created quick HDCB script to see it in hexdump:
00000000 c4 b1 b5 d0 01 00 03 00 30 09 00 00 00 00 00 00 |........0.......| 00000010 10 00 00 00 01 00 00 00 00 00 c0 00 00 00 00 00 |................| 00000020 00 00 00 00 61 65 73 2d 63 62 63 2d 65 73 73 69 |....aes-cbc-essi| 00000030 76 3a 73 68 61 32 35 36 00 00 00 00 00 00 00 00 |v:sha256........| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000060 00 00 00 00 00 00 00 00 e9 4c 81 92 28 69 23 53 |.........L..(i#S| 00000070 54 de f0 1f a4 d0 4c 97 00 00 00 00 00 00 00 00 |T.....L.........| 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000090 00 00 00 00 00 00 00 00 92 16 00 cf 57 72 57 00 |............WrW.| 000000a0 cb 28 63 78 c3 33 a0 19 00 10 00 00 00 00 00 00 |.(cx.3..........| 000000b0 00 20 00 00 00 00 00 00 00 10 00 00 02 0f 03 01 |. ..............| 000000c0 00 00 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000008e0 00 00 00 00 00 00 00 00 00 00 00 00 5d d2 5c e6 |............].\.| 000008f0 af 3b 29 0b e9 0a 2b 0e db 19 e8 da d9 f8 50 10 |.;)...+.......P.| 00000900 a7 ed 14 ef 1a 82 67 26 22 b8 fc bf 2a f4 ac 5b |......g&"...*..[| 00000910 a4 13 70 82 29 bf 50 b0 76 d5 a6 01 56 15 4e 69 |..p.).P.v...V.Ni| 00000920 70 29 84 2a 00 72 3e 72 a6 6a c9 74 00 00 00 00 |p).*.r>r.j.t....| 00000930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00001000 44 cd 50 e9 00 00 00 00 00 00 00 00 00 00 00 00 |D.P.............| 00001010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00100000 [algo] [failures] [flags] [fs_size] [kdf] [keysize] [magic] [major] [master_key] [minor] [N] [offset] [p] [r] [reserved] [salt] [size]
Decryption
Finally, it is possible to decrypt partition contents. What we need to know is:
- Password. If there is no screen lock set, it should default to ‘default_password’ and this is what worked in my case
- Partition size in bytes. If unknown, it could be calculated from footer (I marked it on hexdump as fs_size and is given in sectors, where size of sector is 512 bytes)
For this step android-fde repository is required. I made small improvement to it to make block devices working. Otherwise, it would be required to dump nbd image to file. It can be cloned from Github using:
git clone git@github.com:v3l0c1r4pt0r/android-fde.git -b blockdev
Then we can do:
android-fde/pydroidfde/decrypt.py \ -p default_password \ -S 6442450944 \ /dev/nbd0 footer userdata-qemu.img
where -S
is for giving partition size, nbd0
is my userdata partiton and userdata-qemu.img
is output file.
After few minutes of decryption, it can be mounted easily using losetup and mount commands:
sudo losetup /dev/loop0 userdata-qemu.img sudo mount /dev/loop0 /mnt
Contents of userdata partition should appear in /mnt
.
When done, it is good idea to unmount everything.
What about encrypting it back? Is it possible to create on-the-fly block device for encryption?
In principle it is possible to encrypt it back. I’m only worried that no tool might exist for the job. The same problem might be with both – encryption from file and mounting on the fly. Looking at the length of decrypt.py script, it shouldn’t be very complicated to do the other way round, though.
Hello,
I tried your setup on Ubuntu 20 LTS, it failed on the python script. Could you check that? I want to decrypt an Android 10 system.
What error exactly did you get? Maybe with Android 10 there is some change to encryption scheme? I don’t have any device with Android 10 to check if I can reproduce the issue. The script was not mine, I just did some tweaks for my use case. Maybe the original script was fixed already?
I don’t remember the exact error message, but it said something like “invalid key size” when I tried to decrypt the system.
I don’t have an android 10 device either, I tried to break into a emulated device (I use Android Studio)
As long as your computer supports hardware virtualisation, you could simply download Android studio and try to decrypt the emulated system. Since the original script wasn’t updated for a long time, i guess it just doesn’t work anymore on modern systems.
Script complaining about key size indeed sounds like a lack of support. You still can try comparing major and minor number of the footer. But if really it is greater than what I have, there is not much we can do. In such case, somebody has to make a research about new format and rewrite the script.
Hi. Is it possible to read and write to the system.img.qcow2 disk of Android 11 AVDs? The android-fde project does not appear to support file-based encryption.
Most likely, they changed format of encrypted container. For virtual systems I don’t see any way of preventing you from accessing the container, other than software support. And software must already be open source, like whole AOSP. So, it’s only a matter of adding the support to a tool of your choice.