📜 ⬆️ ⬇️

Bypassing the protection of the iOS client Dropbox



What will the iOS developer first of all do if he is faced with the task of hiding user data from prying eyes? Of course, builds a password protection screen. A particularly tricky developer will not even store the user-defined password in NSUserDefaults , but neatly hide it in a keychain - in this case, the application is immediately transferred to the category of "ultra-secure" in the eyes of both him and the customer.
We will not delve into the description of the dangers of storing a key in the public domain - after all, there is a much more interesting way to bypass such protection.

Cycript is a console utility that allows you to connect to Mac OS X and iOS applications during their execution. To work with the code of the executable application uses a hybrid of Javascript and Objective-C ++. The project has been living since 2007, initially representing a bridge between Javascript and Objective-C. Cycript is interesting primarily because it allows you to explore the application “from the inside” by sending messages to any of its objects. By the way, the author of the project is saurik itself.

Attention: Jailbreak is required to work with Cycript (developers can, however, connect the library to their project in order to be able to test the application on a “clean” device).

Installing Cycript is extremely simple - download the latest version of the package and upload it via sftp to our device:
sftp>put cycript.deb 

after which we connect via ssh and install the package:
 iPad:/tmp root# dpkg -i cycript.deb 

As a test object, the Dropbox client was chosen, allowing you to set a password protection screen that appears every time you open the application. Launch Dropbox by pre-enabling the password request option.

')
We learn the process ID 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 is the rootViewController of the running application:
 cy# UIApp.keyWindow.rootViewController #"<DBSplitViewController: 0x16bc02a0>" 

Now let's check which controller is currently displayed on the screen:
 cy# UIApp.keyWindow.rootViewController.presentedViewController #"<PasscodeFullscreenController: 0x187c8b50>" 

The name is encouraging :) We turn to one of the strengths of using Cycript and define its function, which will show us all the methods defined for 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 is doing :
 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}] 

And now let's declare a variable containing the current instance of this class, and see a list of its variables:
 cy# var PasscodeFullscreenController = #0x187c8b50 #"<PasscodeFullscreenController: 0x187c8b50>" cy# *PasscodeFullscreenController 

 {isa:#"PasscodeFullscreenController",_view:#"<UIView: 0x187c9870; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x187c9800>>",_tabBarItem:null,_navigationItem:null,_toolbarItems:null,_title:null,_nibName:null,_nibBundle:#"NSBundle </private/var/mobile/Containers/Bundle/Application/93E2B5E6-B7EC-4D18-9697-021D24429D29/Dropbox.app> (loaded)",_parentViewController:null,_childModalViewController:null,_parentModalViewController:#"<DBSplitViewController: 0x183c3ca0>",_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:#"<PasscodeViewController: 0x187c8730>"} 

Apparently, we need straight into 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 #"<PasscodeViewController: 0x187c8730>" cy# [PasscodeViewController dismissPasscodeAnimated:YES] 

When this method is called, the password entry screen is magically hidden, and we get full access to the files of the logged in user.


However, every time entering a password is quite tedious, so our task is to turn it off completely. We explore the application settings:


When you select the “Passcode Lock” item, the already familiar password entry form appears. Let's use the method we already know to get rid of it:
 cy# var PasscodeController2 = #0x1992aab0 #"<PasscodeViewController: 0x1992aab0>" cy# [PasscodeController2 dismissPasscodeAnimated:YES] 



But this time the simple concealment of the form does not solve the problem, since the password menu does not appear. Let's try to find another way.
Let's look at all the messages that PasscodeViewController can receive (it also includes the methods of its parents and categories):
 cy# PasscodeViewController.messages 

Among the hundreds of different selectors of interest is the following:
 db_handleVerifyModeCorrectPasscodeEntered:0xb1bd5 

And his call closes the password entry screen and opens the settings. Repeat the same when confirming the password is disabled:


Now you can safely close the application - no more password input is required.

We didn’t consider all Cycript functionality - besides this, it allows you to define your classes, categories, work with blocks, import additional libraries, produce method swizzling - in a word, this is a very powerful tool for pentesting both your own and third-party applications.

And finally, a short list of links for further study:

Source: https://habr.com/ru/post/244143/


All Articles