Brute forcing the unlock PIN on an android phone.

If at any point you get bored and just want the technical details you can read them and get the code on Github or a video of the whole thing in action.

About 6 months ago I had ordered a few things from mouser and decided to pick up the insanely cheap STM32F4Discovery Development Board. What for? I had nothing in mind and it just sat around in a box with other random electronics collecting dust. This past weekend however it was called into action.

My friend was so concerned about security that now even she can't access her phone. After changing the PIN on her phone, she could not remember what it was. She quickly enlisted my help to get it unlocked and avoid having to lose her pictures and other data that was not backed up. This presented a rather tough problem:

  • Encryption Enabled
  • Bootloader Locked
  • No permissions for Android Device Manager to change PIN
  • 6 Digit PIN

After doing some research I quickly concluded the only way short of her remembering the PIN was to try to brute force it. She at least gave me some boundary conditions to work with:

  • I think it was 6 digits
  • I'm pretty sure it didn't use 1, 2, or 3
  • I think it started with a 4 or 7
  • I don't think any digits were repeated

After some quick calculations we saw that we had gone from 1,000,000 possible permutations to around 5,000. Now at least we are in the realm of the possible.

I quickly got to work. First step was to investigate a solution by testing plugging a keyboard into my phone using a USB OTG cable. After a bit of Googling and some experimentation I found that not only could I unlock the phone with a keyboard I could send an email once it was unlocked, all using only the keyboard (Windows Key+g launches Gmail, and then c key to compose a new message).

Once I found A blog entry from Liviu it was rather easy to compile and flash firmware to the STM32F4Discovery board from my Ubuntu machine. With that out the way the fun could begin.

Without too much effort I was able to punch out some firmware that made the STM32F4Discovery act as a USB HID Keyboard device. All the low level USB drivers were ready to go straight from STMicro I just had to modify the USB Descriptor and send the correct HID report for a keyboard (the sample code comes with a mouse example so it wasn't too difficult to tweak the example to get a keyboard working). I tested this on the computer and it worked great. I loaded it up with my PIN and tried on my phone....Nothing. After several hours of banging my head against the wall I realized the USB OTG adapter was not making good contact with the cable connected the STM32F4Discovery. Some fiddling and 3 Micro USB cables later and I found that at least one cable I had on hand seemed to work well (coincidentally the keyboard and one Micro USB cable worked just fine, while the other 2 Micro USB cables did not fit securely into the cheap USB OTG adapter preventing the phone and development board from connecting).

Now that I had a reliable connection, I could get back to development. I needed a good USB Keyboard library first, being lazy (or good) engineer I found a good library in the Arduino Source and copied it. It was very easy to port from C++ to C and to get it working with the STM32F4Discovery USB Driver. Next for the proof of concept, unlock a phone with a known PIN and send and email. After debugging a few iterations, I got it working and it was time to get cracking.

I wrote a C library to generate permutations of 6 digit PINs that conformed to the above boundary conditions, then updated the software to run the following algorithm:

  1. Make 5 different guesses each followed by the enter key
  2. Attempt to send an email to my email address with the last guess that was made
  3. Wait 30 seconds
  4. Repeat>

The slowest part of this process was the fact that after 5 incorrect guess Android blocks further attempts for 30 seconds. This limited me to a guessing rate of about 510 guesses per hour. Slow but not too bad considering I only had about 5,000 guesses to try.

After a few rounds of testing on my phone, I was confident that the algorithm was solid and put it to work on my friend's phone. We quickly ran into a problem however, we could not charge the phone and keep the USB OTG cable connected at the same time. So we only had about 1.5 hours to run before we had to pause the whole operation and recharge the phone. This got old very quickly. The solution: pull the battery and power the phone directly from a power supply. A couple of grabber clips attached nicely to the spring loaded battery contacts and the phone was up and running with no more battery restrictions.

Of course things couldn't be that easy, this worked for a short while after which the STM32F4Discovery Board would disconnect. This puzzled me since thousands of guesses had already been logged successfully with the phone running from battery. I consulted an engineer friend who said it must be a grounding issue, since the phone and the STM32F4Discovery Board had different power supplies, I was confused since they should have a common ground through the USB cable. I tried grounding the STM32F4Discoovery Board to the power supply to no avail. I was ready to give up and when my friend again had a great idea, why don't I try to put a hub between the phone and the STM32F4Discoovery Board. That solved the problem was and I was back in business.

Astute readers may have noticed a lot of uncertainty in the language used to describe the boundary conditions above, this ended up being the straw that broke this project's back. After each run failed to unlock the phone, the boundary conditions were expanded. Eventually my friend decided that it may have been a 7 or 8 digit code. With that I was out of luck, after 3 days and 28,250 incorrect attempts it was time to give up and do a factory reset on the phone (we actually did try a small sample set of 7 and 8 digit combos).

All along the way I tested and retested the permutation algorithms and the overall system functionality by changing the PIN and running guesses on my phone and it worked great. I am fairly confident that the failure was due to simply having too large of a solution space to try with the rate limit of 510 guesses per hour. Nevertheless it was a fun project and it was pretty cool to look and see the phone screen display 28,250 incorrect attempts and know I had given a valiant effort before giving up.