Nico Feulner
Nico Feulner

Reputation: 185

Mount qcow2 image created by Android emulator

I'm trying to mount the userdata-qemu.img.qcow2 file created by the Android emulator. The following procedure does not work:

sudo qemu-nbd -c /dev/nbd0 ~/.android/avd/Pixel_C_API_27.avd/userdata-qemu.img.qcow2

First command runs well, but running

sudo qemu-nbd -c /dev/nbd0 ~/.android/avd/Pixel_C_API_27.avd/userdata-qemu.img.qcow2

results in this output:

Fehler: /dev/nbd0: unbekannte Partitionstabelle
Modell: Unbekannt (unknown)                                               
Festplatte  /dev/nbd0:  3146MB
Sektorgröße (logisch/physisch): 512B/512B
Partitionstabelle: unknown
Disk-Flags: 

Basically it cannot recognize a partition table in the image file. You may wonder what's the output of

fdisk /dev/nbd0 -l

so here it is:

Medium /dev/nbd0: 3 GiB, 3145728000 Bytes, 6144000 Sektoren
Einheiten: sectors von 1 * 512 = 512 Bytes
Sektorengröße (logisch/physisch): 512 Bytes / 512 Bytes
I/O Größe (minimal/optimal): 512 Bytes / 512 Bytes

As you could expect already, mounting fails of course, since no partitions can be recognized if the partition table itself cannot be recognized either. Thanks for any help!

Edit: I've just found out that the problem must have to do with Android's userdata encryption. As I've never changed any password the encryption password of the emulator's userdata partition would have to be the default one "default_password". How can I decrypt the image to be able to mount it?

Upvotes: 2

Views: 5466

Answers (2)

SlugFiller
SlugFiller

Reputation: 1864

The question explicitly mentions API 27 (Android 8.1), so the drive in question would be encrypted using Full Disk Encryption (FDE). This also applies to API 28. The way it works is that a key is stored in a separate partition, and each 512-byte block of the main partition is encrypted using AES-128/256-CBC with ESSIV used to produce per-sector IV values. The stored key is encrypted in CBC, with the key-encrypting-key using the user's PIN/password (or default_password if no PIN was set), hashed using either scrypt or pbkdf2.

You can find a utility for decrypting FDE-encrypted emulator images here.

If, however, you're reading this from the future, and your image uses API 30+ (Android 11+), then chances are the drive is encrypted using File Based Encryption (FBE) with metadata encryption. The metadata encryption is similar to FDE, except the blocks are 4096 bytes long, and encrypted using AES-256-XTS or Adiatnum. Additionally the encryption key is no longer encrypted using the user PIN. Instead, the encryption key partition is now a regular Ext4 partition, with several files in the folder /vold/metadata_encryption/key. The file encrypted_key contains the key encrypted using AES-256-GCM, and the file keymaster_key_blob contains the encryption key for encrypted_key (Specifically, in the 6th through 37th bytes).

One tiny caveat of metadata encryption is that it only encrypts blocks not previously encrypted by the filesystem contained in the drive. FBE uses a second layer of encryption for individual files and folders. This means that metadata encryption can't be "blindly" decrypted, as that would corrupt the file contents of any encrypted files. A two-step process would be needed where first the group descriptor and inode tables are decrypted, and only after checking which blocks belong to files (This can be done without decrypting any files or folders), the remaining blocks are decrypted.

If you're using API 29, the disk itself should not be encrypted, and can be mounted using the procedure in the OP. However, both the unencrypted disk in API 29, and the decrypted disk in API 30+, contain encrypted files and folders instead. These are encrypted using "Linux native file encryption", also known as "fscrypt". This wouldn't interfere with running fdisk or mounting the drive, since the format is natively supported by the filesystem driver, but encrypted files and folders would remain inaccessible until the matching keys are added the keyring. The locations of the keys are:

  • /unencrypted/key/encrypted_key - Used to encrypt the folder containing the other two keys
  • misc/vold/user_keys/de/0/encrypted_key - Used to encrypt files and folders that do not require PIN unlock to be accessible. For instance, it's used for application code, to allow applications to send notifications even when the device is locked.
  • misc/vold/user_keys/ce/0/current/encrypted_key - Used to encrypt files and folders that do require PIN unlock, such as private user data. The encryption key for this key is generated using a combination of the user PIN or hardware-generated token (e.g. for fingerprint unlock), and files in the system_de/0/spblob and /misc/keystore folders.

A utility for decrypting all of the above, from metadata encryption to individual files, under the assumption that no PIN was set, can be found here.

Upvotes: 0

Ryan Goodfellow
Ryan Goodfellow

Reputation: 51

You can mount userdata-qemu.img.qcow2 using the following procedure

  1. convert the image to a raw image

    qemu-img convert -O raw userdata-qemu.img.qcow2 udata-raw.img

  2. use losetup to setup a loopback device for mounting

    sudo losetup -f -P userdata.img

  3. use losetup -l to see what device was setup

    losetup -l
    NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                                DIO
    /dev/loop0         0      0         0  0 /path/to/userdata.img   0
    
  4. mount the drive

    mkdir /tmp/mnt
    sudo mount /dev/loop0 /tmp/mnt
    

Then ls /tmp/mnt/ gives

app  benchmarktest  benchmarktest64  lost+found  misc  nativetest nativetest64

Upvotes: 2

Related Questions