Elelzedel's Projects

Security and hardware enthusiast

Reball to Unlock


Introduction

Not too long ago I used Android phones that were completely unencrypted. At the time, I felt confident that anyone trying to steal my phone would just wipe it so they could resell it, rather than trying to steal my actual data. Eventually, I wised up and switched over to only using phones that had some form of user data encryption with the key stored in a TPM. The question is, how difficult would it have been to steal my data back in the day? Wanting to answer this question and improve my microcomponent handling/soldering skills, I decided to pull one of my old phones apart, dump the internal flash, and analyze it.

The Target

Here is my dented, dusty LG “Sunset” L33L “the device that gives you superior viewing power and security.” Oh wait, “security”? I guess it must be encrypted after all ;).

Sunset

Disassembly

To give credit where credit is due, I do miss these old phones where you could just pop the back off. Not only can you easily replace the main point of failure, but the SIM and SD cards can be swapped without special tools too.

Battery

After removing the battery and unscrewing the back we finally see the PCB, but all the interesting components are hidden under shields:

Exposed PCB

After using a heatgun to get two of those shields off, I finally found what I was looking for:

Flash Chip on PCB

Under that sticker was this chip:

Flash Chip on PCB Zoomed

The Chip

That chip label was a real challenge to read. After shining a flashlight around I finally came up with SAMSUNG KMQN1000SM-B316. I could not find an official datasheet for this online, but I was able to find out that this is an 8GB BGA221 eMMC chip. 8GB? They were being really stingy with memory on this. Remembering back, I did have to use an SD card for photos and screenshots. That was definitely unencrypted.

Regardless, eMMC chips actually have standardized pinouts defined by JEDEC. This means any generic adapter that accepts a BGA221 chip should work for this one as well.

The Adapter

There are test sockets specifically designed for BGA221, but they can be quite pricey. What I opted for was to buy a $10 PCB off of AliExpress that had a BGA221 footprint on it and MMC card pads on the other side. My plan was to remove the flash chip from the PCB, put it on the adapter, and slide the PCB itself into an SD/MMC slot in one of my laptops.

Adapter

Extraction

First I needed to physically remove the flash chip from the L33L’s PCB.

Extraction

I used my rework hot air gun at 700F with a bit of flux to help conduct heat. After about 2 minutes the chip started to float and I was able to get it off the board:

Extracted

Reballing

The chip was free, but I couldn’t just place it on the adapter. The amount of solder remaining on the pads was inconsistent with some of it being left behind on the L33L’s PCB. It needed to be reballed which meant putting fresh solder evenly across the pads.

First, I used a copper wick and my microsoldering iron to soak up the old solder until the pads were nice and clean:

Flash Underside

There are a lot of ways to do reballing, the generally preferred way is to use a stencil to apply solder to the pads. Unfortunately, I did not have a BGA221 stencil. An adaptable, but tedious option is to directly place balls of solder on each of the 221 pads individually and then melt them to the pads.

Opting for the insane option, I smeared a thin layer of flux across the bottom of the chip, dumped 0.35mm 63/37 tin/lead solder balls on the pads, and pushed them into place with the sharp point of a precision test probe:

Solder Balls

After a few hours with lots of breaks, I got all of the balls pushed into place. Next, I heated them with the rework gun while adding a bit of flux until they fused with the pads:

Reballed

Soldering to the Adapter

With the hard part done, I put some flux on the adapter’s footprint, aligned the flash chip, and heated it with the rework gun again. After heating it for a bit, it snapped into place from the ball’s surface tension and I let it cool:

Flash Installed

Dumping the Flash

I have several devices that are advertised as supporting MMC cards, but the only one I could get working was the one in my Lenovo X260:

Adapter in X260

I was absolutely thrilled when I ran lsblk on the X260 and saw it recognized as a drive.

$ lsblk 

NAME                    MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
# SNIP
mmcblk0                 179:0    0   7.3G  0 disk  
├─mmcblk0p1             179:1    0   512K  0 part  
├─mmcblk0p2             179:2    0   512K  0 part  
├─mmcblk0p3             179:3    0   512K  0 part  
├─mmcblk0p4             179:4    0   512K  0 part  
├─mmcblk0p5             179:5    0     2M  0 part  
├─mmcblk0p6             179:6    0   1.5M  0 part  
├─mmcblk0p7             179:7    0   512K  0 part  
├─mmcblk0p8             179:8    0   512K  0 part  
├─mmcblk0p9             179:9    0   512K  0 part  
├─mmcblk0p10            179:10   0   512K  0 part  
├─mmcblk0p11            179:11   0     2M  0 part  
├─mmcblk0p12            179:12   0    16M  0 part  
├─mmcblk0p13            179:13   0    16M  0 part  
├─mmcblk0p14            179:14   0   512K  0 part  
├─mmcblk0p15            179:15   0   1.5M  0 part  
├─mmcblk0p16            179:16   0   1.5M  0 part  
├─mmcblk0p17            179:17   0    24M  0 part  
├─mmcblk0p18            179:18   0    24M  0 part  
├─mmcblk0p19            179:19   0    24M  0 part  
├─mmcblk0p20            179:20   0   1.5M  0 part  
├─mmcblk0p21            179:21   0   512K  0 part  
├─mmcblk0p22            179:22   0   512K  0 part  
├─mmcblk0p23            179:23   0   512K  0 part  
├─mmcblk0p24            179:24   0   512K  0 part  
├─mmcblk0p25            179:25   0   512K  0 part  
├─mmcblk0p26            179:26   0   512K  0 part  
├─mmcblk0p27            179:27   0   512K  0 part  
├─mmcblk0p28            179:28   0     8M  0 part  
├─mmcblk0p29            179:29   0    32M  0 part  
├─mmcblk0p30            179:30   0    32M  0 part  
├─mmcblk0p31            179:31   0     8M  0 part  
├─mmcblk0p32            179:32   0    32M  0 part  
├─mmcblk0p33            179:33   0    64M  0 part  
├─mmcblk0p34            179:34   0     2M  0 part  
├─mmcblk0p35            179:35   0   2.4G  0 part  
├─mmcblk0p36            179:36   0   850M  0 part  
├─mmcblk0p37            179:37   0   3.7G  0 part  
└─mmcblk0p38            179:38   0    16M  0 part  
mmcblk0boot0            179:256  0     4M  1 disk  
mmcblk0boot1            179:512  0     4M  1 disk

Rather than messing around with the actual flash device, I wanted to make a proper forensics copy:

$ sudo dd if=/dev/mmcblk0 of=dump.img bs=4M status=progress

I dumped the entire memory twice into two different images and used sha256sum to confirm they were the exact same.

Mounting Userdata Partition

I first tried to use Autopsy to analyze the image, but it turns out most of the Android plugins only work on Windows. Opting to use some standard Linux utilities, I ran losetup to set up a new read-only loop device with the image:

$ sudo /usr/sbin/losetup -P --read-only /dev/loop6 dump.img

Now I had access to the partitions again:

$ lsblk
NAME                                MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
# Snip...
loop7                                 7:7    0   7.3G  1 loop  
├─loop7p1                           259:38   0   512K  1 part  
├─loop7p2                           259:39   0   512K  1 part  
├─loop7p3                           259:40   0   512K  1 part  
├─loop7p4                           259:41   0   512K  1 part  
├─loop7p5                           259:42   0     2M  1 part  
├─loop7p6                           259:43   0   1.5M  1 part  
├─loop7p7                           259:44   0   512K  1 part  
├─loop7p8                           259:45   0   512K  1 part  
├─loop7p9                           259:46   0   512K  1 part  
├─loop7p10                          259:47   0   512K  1 part  
├─loop7p11                          259:48   0     2M  1 part  
├─loop7p12                          259:49   0    16M  1 part  
├─loop7p13                          259:50   0    16M  1 part  
├─loop7p14                          259:51   0   512K  1 part  
├─loop7p15                          259:52   0   1.5M  1 part  
├─loop7p16                          259:53   0   1.5M  1 part  
├─loop7p17                          259:54   0    24M  1 part  
├─loop7p18                          259:55   0    24M  1 part  
├─loop7p19                          259:56   0    24M  1 part  
├─loop7p20                          259:57   0   1.5M  1 part  
├─loop7p21                          259:58   0   512K  1 part  
├─loop7p22                          259:59   0   512K  1 part  
├─loop7p23                          259:60   0   512K  1 part  
├─loop7p24                          259:61   0   512K  1 part  
├─loop7p25                          259:62   0   512K  1 part  
├─loop7p26                          259:63   0   512K  1 part  
├─loop7p27                          259:64   0   512K  1 part  
├─loop7p28                          259:65   0     8M  1 part  
├─loop7p29                          259:66   0    32M  1 part  
├─loop7p30                          259:67   0    32M  1 part  
├─loop7p31                          259:68   0     8M  1 part  
├─loop7p32                          259:69   0    32M  1 part  
├─loop7p33                          259:70   0    64M  1 part  
├─loop7p34                          259:71   0     2M  1 part  
├─loop7p35                          259:72   0   2.4G  1 part  
├─loop7p36                          259:73   0   850M  1 part  
├─loop7p37                          259:74   0   3.7G  1 part
└─loop7p38                          259:75   0    16M  1 part

I decided to start looking at the largest partition, 37:

$ sudo mount /dev/loop7p37 ~/mnt
mount: /home/elelzedel/mnt: WARNING: source write-protected, mounted read-only.

So far so good, let’s see what’s in there:

$ tree --charset=ASCII

.
|-- adb
|-- app
|   |-- com.dti.cricket-1
|   |   |-- base.apk
|   |   |-- lib
|   |   `-- oat
|   |       `-- arm
|   |           `-- base.odex
|   |-- org.mozilla.firefox-1
|   |   |-- base.apk
|   |   |-- lib
|   |   |   `-- arm
|   |   |       |-- libfreebl3.so
|   |   |       |-- liblgpllibs.so
|   |   |       |-- libmozavcodec.so
|   |   |       |-- libmozavutil.so
|   |   |       |-- libmozglue.so
|   |   |       |-- libnss3.so
|   |   |       |-- libnssckbi.so
|   |   |       |-- libplugin-container.so
|   |   |       |-- libsoftokn3.so
|   |   |       `-- libxul.so
|   |   `-- oat
|   |       `-- arm
|   |           `-- base.odex
|   `-- # SNIP: All of my apps are in here
|-- app-asec
|-- app-lib
|-- app-private
|-- app-system
|-- audio
|-- backup
|   `-- # SNIP: System backup stuff
|-- bootchart
|-- bugreports -> /data/data/com.android.shell/files/bugreports
|-- camera
|-- connectivity
|   |-- bqe_hist.db
|   `-- icd_hist.db
|-- dalvik-cache
|   `-- # SNIP: Boooooring
|-- data
|   `-- # SNIP: Lots of app data for built-in apps and apps I installed
|-- dpm
|   `-- nsrm
|-- drm
|   `-- IDM
|       `-- HTTP
|-- factory
|-- font
|   |-- config
|   `-- download
|-- fota
|-- hostapd
|-- .layout_version
|-- lgdrm
|   |-- DUMP
|   |-- ID
|   |-- SQLDB
|   |   |-- DRMDB.bin
|   |   `-- DRMDB.bin-journal
|   `-- TRYSYNC
|-- local
|   `-- tmp
|       `-- # SNIP: This is not a tmpfs mount point, there were are files in here but nothing interesting
|-- logger
|   |-- kernel.log
|   |-- kernel.log.1
|   |-- modem_debug_info
|   `-- setup
|-- lost+found
|-- media
|   |-- 0
|   |   |-- Alarms
|   |   |-- Android
|   |   |   |-- data
|   |   |   |   |-- com.google.android.apps.maps
|   |   |   |   |   |-- cache
|   |   |   |   |   |-- files
|   |   |   |   |   `-- testdata
|   |   |   |   |-- com.google.android.gms
|   |   |   |   |   `-- cache
|   |   |   |   |       |-- googletrustagent_export.log
|   |   |   |   |       `-- googletrustagent_export.log.lck
|   |   |   |   |-- com.google.android.googlequicksearchbox
|   |   |   |   |   `-- files
|   |   |   |   |       `-- download_cache
|   |   |   |   |-- com.google.android.music
|   |   |   |   |   |-- cache
|   |   |   |   |   `-- files
|   |   |   |   |       `-- ._playmusicid
|   |   |   |   |-- com.google.android.videos
|   |   |   |   |   `-- files
|   |   |   |   |       `-- Movies
|   |   |   |   |-- com.google.android.youtube
|   |   |   |   |   |-- cache
|   |   |   |   |   |   `-- exo
|   |   |   |   |   `-- files
|   |   |   |   |-- deezer.android.app
|   |   |   |   |   |-- cache
|   |   |   |   |   `-- files
|   |   |   |   |-- .nomedia
|   |   |   |   `-- org.mozilla.firefox
|   |   |   |       `-- files
|   |   |   |           `-- Download
|   |   |   `-- media
|   |   |       `-- com.google.android.talk
|   |   |           |-- Notifications
|   |   |           |   `-- hangouts_message.ogg
|   |   |           `-- Ringtones
|   |   |               `-- hangouts_incoming_call.ogg
|   |   |-- DCIM
|   |   |-- Download
|   |   |   `-- # SNIP: These are my actual downloads in here, mostly sideloaded APKs
|   |   |-- Movies
|   |   |-- Music
|   |   |-- Notifications
|   |   |-- Pictures
|   |   |-- Podcasts
|   |   `-- Ringtones
|   `-- obb
|-- mediadrm
|   `-- IDM1013
|       `-- ay64.dat
|-- misc
|   `-- # SNIP: Nothing too interesting in here
|-- security
|-- shared
|-- ss
|-- system
|   |-- #SNIP: Lots of system setting stored in .xml files
|   `-- users
|       |-- 0
|       |   |-- accounts.db
|       |   |-- accounts.db-journal
|       |   |-- appwidgets.xml
|       |   |-- disclosure-permissions.dat
|       |   |-- package-restrictions.xml
|       |   |-- registered_services
|       |   |   |-- android.accounts.AccountAuthenticator.xml
|       |   |   `-- android.content.SyncAdapter.xml
|       |   |-- runtime-permissions.xml
|       |   |-- settings_global.xml
|       |   |-- settings_secure.xml
|       |   |-- settings_system.xml
|       |   |-- wallpaper
|       |   |-- wallpaper_info.xml
|       |   `-- wallpaper_pref.xml
|       |-- 0.xml
|       `-- userlist.xml
|-- time
|   |-- ats_1
|   |-- ats_12
|   |-- ats_13
|   `-- ats_2
|-- tombstones
|   |-- dsps
|   |-- lpass
|   |-- modem
|   `-- wcnss
`-- user
    `-- 0 -> /data/data/

858 directories, 1801 files

A total of 1801 files! Most of them are snipped out, but you get the picture: tons of information about me is all available in an unencrypted partition: my contacts, downloads, settings, WiFi passwords, usage data, and so much more.

Conclusion

I had a swipe lock configured for this phone and I remember calculating how long it would take to brute-force combinations depending upon how many dots I used in the pattern. I should not have wasted my time because all that was needed was a basic microscope and inexpensive rework gun to dump all the personal data off of the phone without a single thought given to that lock screen.

In all likelihood, a common phone thief would not have the equipment to do all this, but there’s definitely enough sensitive data on this phone to be worth their time if they were so inclined.

Tags: