Passcode bypass of the HTC Desire Z using an unexpected feature of the bootloader

Sun 22 May 2011 by cedric

Android devices are becoming increasingly present everywhere. iPhone security has been analyzed by researchers -- however this is more difficult for Android devices due to the diversity of vendors and devices: each model has its own characteristics and has a unique combination of hardware and software. What will be discussed here is an unexpected feature of the stock HTC Desire Z bootloader that allows an attacker to access any file on the device before the Linux operating system starts, bypassing the passcode protection entirely.

There is a great variety of Android devices from various manufacturers (HTC, Samsung, Motorola, etc.) and customised by numerous telecommunication operators (Orange, T-Mobile, etc.). Before loading the operating system (i.e. Android), these devices generally pre-load a bootloader. This bootloader is not open-source, contrary to the Android source code, and differs from one device to another. Some manufacturers implement a way for the end-user to interact with it using serial over USB. An example below of the available commands of an HTC Desire Z:

hboot>h

command list
keytest
heap
boot
reset
powerdown
rebootRUU
heap_test
rtask
task
enableqxdm
gencheckpt
list_partition_emmc
load_emmc
check_emmc
check_emmc_mid
read_emmc
get_wp_info_emmc
send_wp_info_emmc
get_ext_csd_emmc
get_sector_info_emmc

One command that got my attention is the read_emmc command.

hboot>read_emmc
command format: read_emmc [start] [#blocks] [#blocks/read] [show]

You can specify the starting offset with the number of blocks to read and it will basically display to you in hexadecimal format the bytes that are on your phone's flash. Below is the first sector that is actually a partition table.

hboot>read_emmc 0 1 1 1
reading sector 0 ~ 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 0
0 0 4D 0 0 0 1 0 0 0 E8 3 0 0 0 0
0 0 45 0 0 0 E9 3 0 0 80 0 0 0 0 0
0 0 46 0 0 0 69 4 0 0 28 23 0 0 0 0
0 0 5 0 0 0 91 27 0 0 6E 58 45 0 55 AA
read sector done average = 583

The first idea that came to my mind is to dump the whole flash using this method but it is really slow. It took 6 hours to dump 10 MB so it will take approximatively 33 days to get 1,3 GB... So I decided to use FUSE (Filesystem in Userspace) to mount the user data partition remotely and get only the files I want. You basically have to implement those four functions: getattr, readdir, open and read.

The phone's filesystem becomes accessible through one device file, let's name it dev. Reads on this file will be proxied by FUSE over USB to the read_emmc implementation on the device.

hboot_fuse.png

Writes will not be implemented because we do not need them (and we do not have commands such as write_emmc :-(. Consequently, this dev file will have *read only* attributes.

# ls -l mnt
total 0
-r--r--r-- 1 root root 1232076288 1970-01-01 01:00 dev

We now have a virtual disk image that we are able to mount and get the files we are interested in:

# dd if=mnt/dev of=first_sector bs=512 count=1
# mount -o loop,ro -t ext2 mnt/dev mnt2
# cp mnt2/data/com.android.providers.telephony/databases/mmssms.db dump/
# cp mnt2/data/com.android.providers.contacts/databases/contacts2.db dump/

Finally, we are able to get the files storing the passcode information (as a numerical PIN code for example below) if the end-user defined one.

# cp mnt2/data/com.android.providers.settings/databases/settings.db dump/
# cp mnt2/system/password.key dump/

The salt is stored in the settings.db SQLite database. The passcode is simply stored in a hash form in password.key:

SHA-1(password|salt)|MD5(password|salt)

So it is easy to bruteforce from the computer once we get the file.

This basically shows how some devices may implement things or leave some doors open in a way that allows an attacker to bypass security protections...

Edit: source code is available in github.