iOS SpringBoard tweak插件,双击图标快速启动debugserver

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

0x00 懒是第一生产力

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

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

代码见:Github

https://github.com/TalkingDat...

运行界面

我们所用的开发环境是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等。

**
作者:TalkingData小张同学

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


TalkingData
TalkingData 开发同学们的经验与心得,欢迎一同探讨!

TalkingData成立于2011年,是国内领先的数据服务提供商。TalkingData秉承“数据改变企业决策,数据改善人...

528 声望
5.8k 粉丝
0 条评论
推荐阅读
流量聚拢、营销下沉,移动广告行业2020盘点与2021预测
TalkingData重磅发布《流量聚拢 营销下沉——疫情下的2020移动广告行业报告》,基于TalkingData数据中心数据,对2020移动广告行业数据进行盘点,并基于行业调研数据,对2021移动广告行业趋势进行预测,为广告主和广...

TalkingData1阅读 2.1k

封面图
iOS 健康共享失败如何解决
您要开始与之共享的对象必须已经连同他们的 iCloud 账户邮箱一起保存在您的“通讯录”中(iCloud 账户邮箱即 iCloud 账户绑定的邮箱信息,不是强制要求 @iCloud.com 邮箱)。

岚哲阅读 5.1k

探究 iOS 内存问题
本文从 Tagged Pointer、objc 源码、dealloc 原理、AutoreleasePool 原理、野指针探究等技术点展开聊了聊 iOS 内存相关问题。

杭城小刘1阅读 1.4k

封面图
iOS IDA逆向之patch
这里介绍的是ida的patch.1.搜索svc #0x80,回到IDA View-A界面,才能正确搜索点击图中T字按钮,弹出搜索框点击列表中进入2.修改svc #0x80,在IDA View-A界面中选中svc那一行,点击工具栏Edit-->Patch program--&gt...

宋冬野阅读 2k

社交场景下iOS消息流交互层实践
一款社交产品的诞生,离不开即时通讯(IM)场景。随着团队业务版图在社交领域的布局,诞生了多个社交场景APP,涉及的IM场景,包含私聊、群聊、聊天室等。

云音乐技术团队1阅读 438

封面图
SegmentFault 思否技术周刊 Vol.77 — 探究关于 iOS 的特性
本文从 Tagged Pointer、objc 源码、dealloc 原理、AutoreleasePool 原理、野指针探究等技术点展开聊了聊 iOS 内存相关问题。

Beverly阅读 1.4k

封面图
魔方带壳截图:让你的截图看起来更加高大上
我们在日常工作和生活中,往往需要截图去做汇报或分享。普通人的做法:手机或电脑截图,然后就拿去汇报或分享。这样你的截图显得平平无奇,没有给人眼前一亮的感觉。但是,如果我们给这张截图穿上一件“衣服”,把...

老人羽海阅读 1.2k

封面图

TalkingData成立于2011年,是国内领先的数据服务提供商。TalkingData秉承“数据改变企业决策,数据改善人...

528 声望
5.8k 粉丝
宣传栏