17

只需双击,老铁!debugserver快速启动插件

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MjM5MDAxMTE0MA%3D%3D&%3Bmid=2652053124&%3Bidx=1&%3Bsn=5513626ecc574fc11b9e83c1fcadc86f
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Ev2Q3uM.jpg!web

debugserver+lldb很好用,但启动起来太麻烦?我们开发了一款iOS SpringBoard tweak小插件,简化debugserver启动过程。老铁,请双击!

0x00 懒是第一生产力

我们经常要通过debugserver对App进行调试,有书籍和论坛对相关的技术和实践进行了说明,但实际应用起来还是有些麻烦。先要重签拷贝,再要启动终端ssh到iPhone启动debugserver,各种ls加grep找到想调试的应用,敲命令启动debugserver,然后Mac本地终端启动lldb。这样折腾下来,至少要开两个终端,有的时候甚至更多。GitHub上有个issh工具对上述操作有封装和优化,但是还是需要敲命令找App,再运行debugserver。

所以做个tweak提升一下生产力。只需 双击应用图标,即可一键启动debugserver

代码见:G ithub  https://github.com/TalkingData/tap2debug,或点击文末 阅读原文 直接前往。

运行界面

rEBVbuN.png!web

我们所用的开发环境是iOS 13.3,但是并没有用到特殊版本的API,低版本手机应该也OK。

下面简单分享开发过程:

0x01 通过图标找到应用执行路径

从界面找逻辑,逆向发现SpringBoard的图标是 SBIconView 。并且有一个叫属性  applicationBundleIdentifierForShortcuts  返回的是图标对应的App的Bundle ID。通过Bundle ID构造 LSApplicationProxy 对象,并且获得 canonicalExecutablePath 属性,也就是应用的可执行文件路径。

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

0x02 寻找注入点添加扩展

接续看 SBIconView ,图标上有两个手势对象:

  • 单击,用来启动App。

  • 长按,进入编辑状态,执行删除和排列图标等操作。

所以,我们来给图标交互加个双击扩展。

%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];
}
}
}

这里额外说一句, [each requireGestureRecognizerToFail: doubleTap]  添加了双击手势指挥,由于iOS内部维护了手势的状态机,我们进行单击操作的时候,其实产生了两种Possible State。第一种是识别为单击,然后结束。第二种是识别为双击的第一下并等待第二下的发生,然后根据两次点击之时间间隔阈值来判断是不是合法的双击。

所以我们手动增加了约束,相当于指定了识别的优先级,只有双击失败了,才继续执行单击回调。这种操作会带来一点几乎无感的瑕疵:单击后等待双击识别失败的延迟,延迟的值就是双击识别执行的阈值(大约零点几秒)。

0x03 debugserver启动和关闭

debugserver是一个二进制文件,狗神的教程里有如何重签,issh把这些过程给简化了。先看一下debugserver的权限:
-rwxr-xr-x 1 root admin 9876848 Jan 19 11:28 /iOSRE/tools/debugserver*

再来看一下SpringBoard的权限:
-rwxr-xr-x 1 root wheel 71264 Dec 5 13:15 SpringBoard*

属主用户都是root,没毛病。找个函数调用一下:

  1. system函数

  2. posix_spawn函数

  3. NSTask ,面向对象方便管理,异步执行,不会block UI,就用它了。

代码如下:

task = [[NSTask alloc]init];
[task setLaunchPath:bin_serverpath];
[task setArguments:args];
[task launch];

每次server在launch之前,要把之前的task结束掉。

- (void)interrupt; // Not always possible. Sends SIGINT.
- (void)terminate; // Not always possible. Sends SIGTERM.

NSTask 头文件里竟然告诉我  Not always possible 。事实上,在调用的时候,还真的不怎么possible,实际测试第一次server正常启动,后续由于没成功关闭,所以第二次就没法启动了。

所以还是换种方式关闭吧。简单粗暴的 kill 函数:

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

0x04 添加UI交互

直接用Alert,又有按钮又有输入框,不过UIAlertView已经被废弃掉了,需要用UIAlertController。由于弹出Controller需要父Controller,通过View找到当前的Controller,做正向的应该都写过这段代码吧:

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

0x05 优化一下用户体验


输入框里的IP和debugserver的path,每个人都不一样,所以在第一次输入完成之后,把这些值用NSUserDefault持久化存储起来,下次直接读取填充。

0x06后记

之前在相关技术论坛读到讨论用Root身份运行App的帖子,学习完帖子里的技巧,增强对操作系统的理解以及实践之后,发现如果真的想RootApp运行,其实SpringBoard本身就是一个RootApp,我们把SpringBoard当做RootViewController,很容易把一些系统工具做出界面,从而提升生产力。比如砸壳、重签、拷贝App等。

参考资料:

籍:https://book.douban.com/subject/25826902/

论坛:http://bbs.iosre.com/t/debugserver-lldb-gdb/65

issh工具:https://github.com/4ch12dy/issh

作者:TalkingData小张同学

本文版权归TalkingData所有,如需转载请申请授权并注明来源

推荐阅读:

rQvYFvE.png!web

技术专栏 | 数据偏移、分区陷阱……我们这样避开DynamoDB的5个坑

J7zYjez.jpg!web

技术专栏 |Flink的迁移之路,2年处理效果提升5倍

aiumQvb.jpg!web

技术专栏丨Flink Slot详解与Job Execution Graph优化

QrYrQn7.jpg!web

↓↓↓点击阅读原文在GitHub上查看插件


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK