Recover LUKS Password from Android Phone
I had an old backup of an encrypted SD-Card from my old android phone. I just dd‘ed the whole SD-Card for backup reason. I was able to mount the img file as a loop device and confirm that it was encrypted:
$ sudo losetup -P loop1 sd.img
Now for the LUKS query:
$ cryptsetup luksDump /dev/loop0
LUKS header information for /dev/loop0
Version: 1
Cipher name: aes
Cipher mode: cbc-plain
Hash spec: sha1
Payload offset: 4096
MK bits: 256
MK digest: 46 97 79 28 ed 60 6a fe ad 7e cb d7 67 37 6a ab 89 2d bc fc
MK salt: 54 1f 7e a0 ea da e4 d0 f8 af 53 e2 c1 e6 c7 be
1b 18 e8 e0 1c 68 cc 01 3e c8 cd 07 9a ee 5f 8a
MK iterations: 38625
UUID: 62acffbc-6102-485c-8f37-9d9a9727ad1c
Key Slot 0: ENABLED
Iterations: 154775
Salt: 67 49 33 d9 ca 5b 3d f4 05 46 6d a9 a0 9e a4 1f
97 0a 5c 68 72 f1 ad b5 ac dd e0 97 f0 f5 b2 70
Key material offset: 8
AF stripes: 4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
We can also confirm by using file:
$ file /data/phone/sd.img
/data/phone/sd.img: LUKS encrypted file, ver 1 [aes, cbc-plain, sha1] UUID: 62acffbc-6102-485c-8f37-9d9a9727ad1c
Reading over the “Revisiting Android disk encryption” site we can see that AES in CBC mode is indeed used by android phone for disk encryption:
Full disk encryption (FDE) for Android was introduced in version 3.0 (Honeycomb) and didn’t change much until version 4.4 (discussed in the next section). Android’s FDE uses the dm-crypt target of Linux’s device mapper framework to implement transparent disk encryption for the userdata (mounted as /data) partition. Once encryption is enabled, all writes to disk automatically encrypt data before committing it to disk and all reads automatically decrypt data before returning it to the calling process. The disk encryption key (128-bit, called the ‘master key’) is randomly generated and protected by the lockscreen password. Individual disk sectors are encrypted by the master key using AES in CBC mode, with ESSIV:SHA256 to derive sector IVs.
My phone was running cyanogenmod 9.1 which is andoid 4.0.4:
$ adb shell
shell@android:/ $ getprop ro.build.version.release
4.0.4
shell@android:/ $ getprop ro.modversion
9.1.0-pyramid
The phone was of course rooted. So I wanted to mount the disk image on my laptop.
Getting the Master Key File
I ran into this site which talked about cracking the master key. It talked about installing a module called LiME which allows you to dump the contents of your phone’s RAM into a file.
Installing LiME
Compiling LiME has a couple of steps, I found good sites that go over the process:
So let’s get started on that.
Install Android NDK
You can download it from here. At the time of writing I was able to get this one:
$ wget http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin
To install it, I first made the installer executable and then ran the installer:
$ chmod +x android-ndk-r10d-linux-x86_64.bin
$ ./android-ndk-r10d-linux-x86_64.bin
Extracting android-ndk-r10d/build/gmsl
Extracting android-ndk-r10d/build/core
Extracting android-ndk-r10d/build/awk
Extracting android-ndk-r10d/build
Extracting android-ndk-r10d
Everything is Ok
After that I put it under /usr/local:
$ sudo mv android-ndk-r10d /usr/local/.
$ sudo ln -s /usr/local/android-ndk-r10d /usr/local/and-ndk
Install Android sdk
You can download the SDK from here. At the time of writing I got the following version:
$ wget http://dl.google.com/android/android-sdk_r24.0.2-linux.tgz
Then I extracted it:
$ tar xvzf android-sdk_r24.0.2-linux.tgz
And lastly I installed in under /usr/local:
$ sudo mv android-sdk-linux/ /usr/local/.
$ sudo ln -s /usr/local/android-sdk-linux/ /usr/local/and-sdk
Get the Kernel Source
My phone was running 3.0 version of the kernel:
$ adb shell
shell@android:/ $ uname -a
Linux localhost 3.0.36-g7290c7f #2 SMP PREEMPT Sun Jul 1 00:25:26 PDT 2012 armv7l GNU/Linux
After some research I found the source in the following locations:
My phone was an HTC Sensation:
shell@android:/ $ getprop ro.product.model
HTC Sensation
So I decided to just clone the git repo (and it worked out):
$ git clone https://github.com/htc-msm8660/android_kernel_htc_msm8660.git -b android-msm-pyramid-3.0
Get the Source Code for LiME
This one is pretty easy just run the following to clone the git repo:
$ git clone https://github.com/504ensicsLabs/LiME.git
I just left it in my home directory.
Prepare the Environment for Compiling
First we need to set up all the environment variables:
export SDK_PATH=/usr/local/and-sdk/
export NDK_PATH=/usr/local/and-ndk/
export KSRC_PATH=/data/work/android_kernel_htc_msm8660/
export CC_PATH=/usr/local/and-ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/
export LIME_SRC=~/LiME/src/
Now let’s pull the kernel config from phone:
$ adb pull /proc/config.gz
Now let’s extract it
$ gunzip config.gz
And let’s copy it into the kernel source
$ cp config /data/work/android_kernel_htc_msm8660/.config
Before preparing the source I had to modify the wrapper script to use python 2.7 (by default my gentoo box uses python 3), the issue was discussed here. So I modified the following file: /data/work/android_kernel_htc_msm8660/scripts/gcc-wrapper.py and made the following change:
- #! /usr/bin/env python
+ #! /usr/bin/env python2.7
I was then able to prepare the source without any warnings:
$ cd /data/work/android_kernel_htc_msm8660
$ make ARCH=arm CROSS_COMPILE=$CC_PATH/arm-linux-androideabi- modules_prepare
Compile LiME
Now let’s modify the Makefile for LiME, I edited the ~/LiME/src/Makefile file and made the following changes:
PWD := $(shell pwd)
+ KDIR := /data/work/android_kernel_htc_msm8660/
+ CCPATH := /usr/local/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/
default:
- $(MAKE) -C /lib/modules/$(KVER)/build M=$(PWD) modules
- strip --strip-unneeded lime.ko
- mv lime.ko lime-$(KVER).ko
+ # $(MAKE) -C /lib/modules/$(KVER)/build M=$(PWD) modules
+ # strip --strip-unneeded lime.ko
+ # mv lime.ko lime-$(KVER).ko
+ $(MAKE) ARCH=arm CROSS_COMPILE=$(CCPATH)/arm-linux-androideabi- -C $(KDIR) EXTRA_CFLAGS=-fno-pic M=$(PWD) modules
+ mv lime.ko lime-pyramid.ko
Then running make worked without issues:
$ cd ~LiME/src
$ make
Try loading the LiME module on the Android Phone
Let’s push the module to the phone:
$adb push lime-pyramid.ko /sdcard/lime.ko
1520 KB/s (347364 bytes in 0.223s)
Upon loading the module I saw the following:
$ adb shell
shell@android:/ $ su -
root@android:/ # cd sdcard
root@android:/sdcard # insmod lime.ko
insmod: init_module 'lime.ko' failed (Exec format error)
255|
I ran dmesg and I saw the following:
<3>[656653.599731] lime: version magic '3.0.36-g7290c7f-dirty SMP preempt mod_unload ARMv7 ' should be '3.0.36-g7290c7f SMP preempt mod_unload ARMv7 '
Fixing Kernel Version for LiME Module
It looks like another person ran into the same and his discoveries are here. We need to make sure the kernel version of the module matches the kernel version running on the phone. So the one I built had the following information:
~/LiME/src$ modinfo ./lime-pyramid.ko
filename: ~/LiME/src/./lime-pyramid.ko
license: GPL
depends:
vermagic: 3.0.36-g7290c7f-dirty SMP preempt mod_unload ARMv7
parm: path:charp
parm: dio:int
parm: format:charp
So I specified the version in the kerner source make file here /data/work/android_kernel_htc_msm8660/Makefile:
VERSION = 3
PATCHLEVEL = 0
SUBLEVEL = 36
EXTRAVERSION = -g7290c7f
NAME = Sneaky Weasel
Then re-prepared the kernel source:
$ cd /data/work/android_kernel_htc_msm8660
$ make ARCH=arm CROSS_COMPILE=$CC_PATH/arm-linux-androideabi- clean
$ make ARCH=arm CROSS_COMPILE=$CC_PATH/arm-linux-androideabi- modules_prepare
And then rebuilding the LiME module:
$ cd ~LiME/src
$ make clean
$ rm lime-pyramid.ko
$ make
Double checking the module it had the following information:
~/LiME/src$ modinfo ./lime-pyramid.ko
filename: ~/LiME/src/./lime-pyramid.ko
license: GPL
depends:
vermagic: 3.0.36-g7290c7f SMP preempt mod_unload ARMv7
parm: path:charp
parm: dio:int
parm: format:charp
Getting the RAM contents from the phone
Then after pushing the new module it loaded fine:
root@android:/ # insmod /sdcard/lime.ko "path=/sdcard/lime.dump format=lime"
root@android:/sdcard # ls -la /sdcard/lime.dump
----rwxr-x system sdcard_rw 627048480 2015-03-15 10:05 lime.dump
Then I just grabbed the whole file
$ adb pull /sdcard/lime.dump
3119 KB/s (627048480 bytes in 196.314s)
It took about 3 mins (it wasn’t that much)
Compile aeskeyfind
I just grabbed the source:
$ wget http://ftp.ubuntu.com/ubuntu/pool/universe/a/aeskeyfind/aeskeyfind_1.0.0.orig.tar.gz
Then extracted it:
$ tar xzf aeskeyfind_1.0.0.orig.tar.gz
And the compile was pretty easy:
$ cd aeskeyfind/
aeskeyfind$ make
cc -Wall -O4 -std=c99 -c -o aeskeyfind.o aeskeyfind.c
cc -Wall -O4 -std=c99 -c -o aes.o aes.c
cc -Wall -O4 -std=c99 -c -o util.o util.c
cc -o aeskeyfind aeskeyfind.o aes.o util.o
Getting the master key from the LiME Dump
Now that I have the aeskeyfind and the LiME dump on the same machine I can just run the following to get the key:
aeskeyfind$./aeskeyfind -v ~/lime.dump
FOUND POSSIBLE 256-BIT KEY AT BYTE d666c60
KEY: 487c537e76e0eb1aac6becfe9a93dbb1995e3ba1ce239c78e4fea6ec9becedb7 <---
EXTENDED KEY:
487c537e76e0eb1aac6becfe9a93dbb1
995e3ba1ce239c78e4fea6ec9becedb7
8729fa6af1c911705da2fd8ec731263f
5f99ccd491ba50ac7544f640eea81bf7
47869242b64f8332ebed7ebc2cdc5883
2e1fa638bfa5f694cae100d424491b23
7829b474ce663746258b49fa09571179
2f44248e90e1d21a5a00d2ce7e49c9ed
4bf4e1878592d6c1a0199f3ba94e8e42
fc6b3da26c8aefb8368a3d7648c3f49b
754bf5d5f0d9231450c0bc2ff98e326d
65721e9e09f8f1263f72cc5077b138cb
9d4cea206d95c9343d55751bc4db4776
79cbbea670334f804f4183d038f0bb1b
51a645273c338c130166f908c5bdbe7e
CONSTRAINTS ON ROWS:
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000
110b84a00c81083346f8f40d8470daa3154dba3b11f24e23ecd4fe53a08240f2
2bc9081b4577838cba0332218ab1b60172424fc6f1ff0c07207361290db2a319
1449acbf57f2c8f2ff74b1ad30b2842045236cd72ace95b6d18c6d2e2dc1c230
df0da3daee94ad1ea886795fcfc6358dea825eba4950bfeefb42f898fc4daf1e
dfb3863bbc58e3694612d44167404cd25132c4668c188e9ab2124776070f5786
2d9318383c22c5aafa4a3728215298938329a390c45c32853e0ac9ecb51d10f0
1bd15b85f7aedb01c668f282db18afbb29ecb4a3b58b617854a72ae779095c75
Keyfind progress: 100%
Mount the encrypted LUKS disk
First let’s create the master key file:
$ echo "487c537e76e0eb1aac6becfe9a93dbb1995e3ba1ce239c78e4fea6ec9becedb7" | xxd -r -p > mf.key
Now let’s decrypt the disk:
$ sudo cryptsetup luksOpen --master-key-file mf.key /dev/loop0 phone
Lastly let’s mount the decrypted disk:
$ sudo mount /dev/mapper/phone /mnt/phone