50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

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

  • 2020-04-10
  • 本文字数:2346 字

    阅读完需:约 8 分钟

只需双击,老铁!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/TalkingData/tap2debug


运行界面



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


2020-04-10 18:33958

评论

发布
暂无评论
发现更多内容

推荐|海泰信创浏览器安全解决方案 全面适配安全可靠

电子信息发烧客

推荐|海泰政务移动办公系统密码应用解决方案 打造移动办公安全

电子信息发烧客

安势清源SCA助力超大规模高科技企业加速开源风险治理

安势信息

开源 腾讯 SCA SBOM 软件供应链安全

人人能读懂redux原理剖析

夏天的味道123

React

2022年10月中国数据库排行榜:达梦冲刺IPO热度不减,PolarDB立足创新夺锦才

墨天轮

数据库 opengauss tdsql TiDB 国产数据库

议程剧透!1个主论坛4场Workshop,龙蜥操作系统峰会盛大来袭 | 2022 云栖大会

OpenAnolis小助手

开源 报名 云栖大会 论坛 龙蜥操作系统峰会

redis实现分布式锁(二)

zarmnosaj

10月月更

5个技巧让CIO最大化提升IT项目投资回报率

雨果

CIO ROI

如何将 SAP Business Application Studio 里开发的 Java 应用部署到 SAP BTP 上

汪子熙

云原生 Cloud 云平台 SAP 10月月更

企业云安全的6个最佳实践

HummerCloud

10月月更

OPPO 引力计划全方位升级,与开发者共建折叠屏上繁荣生态

极客天地

保10万涨薪、保Offer、保大厂,1V1私教服务上线啦!

霍格沃兹测试开发学社

微服务是开发架构对三高场景的妥协吗?

NoGirlfriendDeFoundException

架构 微服务 单体架构 云平台

React-Hook最佳实践

xiaofeng

React

【荣耀云调试FAQ】一个帐号可以同时使用多部手机吗?

荣耀开发者服务平台

开发者 手机 安卓 荣耀 honor

年度大促将至,企业如何进行性能压测

阿里巴巴云原生

阿里云 云原生 性能压测 PTS

解React框架核心原理

夏天的味道123

React

Gartner 权威解读: SBOM 采用率将于2025年达到60%

SEAL安全

DevSecOps Gartner SBOM 软件供应链安全

JS继承有哪些,你能否手写其中一两种呢?

helloworld1024fd

JavaScript

CentOS下搭建Gitea-自己的git服务器

麦洛

git Gitea

经常被问到的react-router实现原理详解

夏天的味道123

React

利器| Cypress 强大全新的 Web UI 测试框架应用尝鲜

霍格沃兹测试开发学社

欧美开源法案频出,你准备好了吗?

安势信息

出海 #开源 SBOM 软件供应链安全 开源合规

自定义注解判断参数为空

派大星

几个你必须知道的React错误实践

xiaofeng

React

长安链源码分析之网络模块 net-liquid(3)

保10万涨薪、保Offer、保大厂,1V1私教服务上线啦!

测吧(北京)科技有限公司

测试

STM32 HAL库串口同时收发,接收卡死?

矜辰所致

串口 STM32L051 10月月更

哪些数据类岗位不容易失业?

雨果

开发数据 数据科学 数据工程师

React-hooks+TypeScript最佳实战

xiaofeng

React

Redis 底层数据结构说明

water

只需双击,老铁!debugserver快速启动插件_文化 & 方法_TalkingData小张同学_InfoQ精选文章