Mounting encrypted Android emulator image

fastboot icon

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:

  1. Password. If there is no screen lock set, it should default to ‘default_password’ and this is what worked in my case
  2. 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. Either way, 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.

Leave a Reply

Your email address will not be published. Required fields are marked *