Debugserver + LLDB is nice to use, but too cumbersome to start? We developed an iOS SpringBoard Tweak widget to simplify the debugServer startup process. Lao Tie, please double click!


0x00 Laziness is the first productive force

We often need to debug the App through the DebugServer, there are books and forums on the relevant technology and practice, but the actual application is still some trouble. First, you need to re-sign the copy, and then start the terminal by SSH to iPhone to start the debugServer. Then, you need to add ls and grep to find the application you want to debug, and run the command to start the debugServer. Then, you need to start the LLDB on the Mac terminal. This requires at least two terminals, and sometimes more. There is an ISsh tool on GitHub that encapsulates and optimizes the above operations, but you still need to type the command to find the App and then run the debugServer.

Make a tweak to boost productivity. You can start the DebugServer by double-clicking the application icon.

See the code at Github
https://github.com/TalkingData/tap2debug

Operation interface


The development environment we used was iOS 13.3, but we did not use the special version of the API, the lower version of the phone should be OK.

Here’s a quick look at the development process:



0x01 Application execution Path Is Found by icon

The icon of SpringBoard is SBIconView. And one attribute applicationBundleIdentifierForShortcuts returns the icon of the corresponding App Bundle ID. The LSApplicationProxy object is constructed with the Bundle ID, and the canonicalExecutablePath property, which is the executable file path of the application, is obtained.

Class LSApplicationProxy_class = objc_getClass("LSApplicationProxy"); NSObject* proxyObj = [LSApplicationProxy_class performSelector:@selector(applicationProxyForIdentifier:) withObject:bundle]; NSString * canonicalExecutablePath = [proxyObj performSelector:@selector(canonicalExecutablePath)];Copy the code


0x02 Find injection point to add extension

The SBIconView icon has two gesture objects:

  • Click to start the App.

  • Hold down to edit ICONS and delete or arrange ICONS.

So, let’s add a double click extension to icon interaction.

%hook SBIconView

- (void)didMoveToWindow{    %orig;    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleClick:)];    [doubleTap setNumberOfTapsRequired:2];    [self addGestureRecognizer:doubleTap];    NSArray * ges = self.gestureRecognizers;    for(UITapGestureRecognizer * each in ges){        if([each isKindOfClass:[UITapGestureRecognizer class]]){ [each requireGestureRecognizerToFail: doubleTap]; }}}Copy the code

Here, extra [each requireGestureRecognizerToFail: doubleTap] added double-click gesture command, because internal iOS maintained the gestures of State machine, when we click operation, actually had two Possible State. The first is to identify it as a click and then end. The second one is to recognize the first double click and wait for the second one to happen, and then judge whether the double click is legitimate according to the time interval threshold of the two clicks.

So we manually add constraints, which are equivalent to specifying the priority of recognition, and only proceed with the click callback if the double click fails. This operation introduces an almost unobserved flaw: the delay after a click until the double click recognition fails. The value of the delay is the threshold for double click recognition execution (approximately a few tenths of a second).



0x03 The DebugServer starts or shuts down



Debugserver is a binary file, dog god tutorial has how to re-sign, issh to simplify these processes. Check the debugServer permissions:


-rwxr-xr-x 1 root admin 9876848 Jan 19 11:28 /iOSRE/tools/debugserver*

-rwxr-xr-x 1 root wheel 71264 Dec 5 13:15 SpringBoard*

The owner user is root. Find a function to call:

  1. The system function

  2. Posix_spawn function

  3. NSTask, object oriented, easy to manage, asynchronous execution, no block UI, just use it.

The code is as follows:

task = [[NSTask alloc]init]; [tasksetLaunchPath:bin_serverpath]; [tasksetArguments:args]; [task launch];Copy the code

Each time a server launches a task, it terminates the previous task.

- (void)interrupt; // Not always possible. Sends SIGINT.Copy the code

- (void)terminate; // Not always possible. Sends SIGTERM.Copy the code

The NSTask header tells me Not always possible. As a matter of fact, possible was really not good when it was called. In the actual test, the server started normally in the first time, but failed to shut down in the subsequent time, so it could not be started in the second time.

So let’s switch it off. The simple and crude kill function:

NSTask * task = [TaskManager sharedManager].runningTask;if(task){    kill(task.processIdentifier,SIGKILL); task = nil; }Copy the code


0x04 Add UI Interaction

I’m just going to call Alert, which has buttons and input fields, but UIAlertView is obsolete, so I’m going to use UIAlertController. Since ejected Controller requires parent Controller, find the current Controller from View.

@implementation UIView(find)-(UIViewController*)findViewController{    UIResponder* target= self;    while (target) {        target = target.nextResponder;        if ([target isKindOfClass:[UIViewController class]]) {            break; }}return(UIViewController*)target; }@endCopy the code


0x05 Optimize user experience

The IP in the input box and the path of the debugServer are different from each other, so after the first input, these values are stored in NSUserDefault persistence, next time directly read and fill.



0 x06 afterword.

Before, I read a post about running App with Root identity in relevant technical forums. After learning the skills in the post and enhancing my understanding and practice of operating system, I found that SpringBoard itself is a RootApp if I really want to run RootApp. We treat SpringBoard as a RootViewController, making it easy to interface system tools to improve productivity. For example, crack shell, re-sign, copy App and so on.




Author: TalkingData Xiao Zhang

The copyright of this article belongs to TalkingData, all rights reserved