热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

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

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,或点击文末 阅读原文 直接前往。

运行界面

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

我们所用的开发环境是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所有,如需转载请申请授权并注明来源

推荐阅读:

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

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

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

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

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

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

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

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


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 我们


推荐阅读
  • 本文详细介绍了 org.apache.commons.io.IOCase 类中的 checkCompareTo() 方法,通过多个代码示例展示其在不同场景下的使用方法。 ... [详细]
  • CentOS 6.5 上安装 MySQL 5.7.23 的详细步骤
    本文详细介绍如何在 CentOS 6.5 系统上成功安装 MySQL 5.7.23,包括卸载旧版本、下载安装包、配置文件修改及启动服务等关键步骤。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • Java项目分层架构设计与实践
    本文探讨了Java项目中应用分层的最佳实践,不仅介绍了常见的三层架构(Controller、Service、DAO),还深入分析了各层的职责划分及优化建议。通过合理的分层设计,可以提高代码的可维护性、扩展性和团队协作效率。 ... [详细]
  • 本文深入探讨了面向切面编程(AOP)的概念及其在Spring框架中的应用。通过详细解释AOP的核心术语和实现机制,帮助读者理解如何利用AOP提高代码的可维护性和开发效率。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 在尝试使用C# Windows Forms客户端通过SignalR连接到ASP.NET服务器时,遇到了内部服务器错误(500)。本文将详细探讨问题的原因及解决方案。 ... [详细]
  • 丽江客栈选择问题
    本文介绍了一道经典的算法题,题目涉及在丽江河边的n家特色客栈中选择住宿方案。两位游客希望住在色调相同的两家客栈,并在晚上选择一家最低消费不超过p元的咖啡店小聚。我们将详细探讨如何计算满足条件的住宿方案总数。 ... [详细]
  • JSOI2010 蔬菜庆典:树结构中的无限大权值问题
    本文探讨了 JSOI2010 的蔬菜庆典问题,主要关注如何处理非根非叶子节点的无限大权值情况。通过分析根节点及其子树的特性,提出了有效的解决方案,并详细解释了算法的实现过程。 ... [详细]
  • 本文介绍如何在Spring Boot项目中集成Redis,并通过具体案例展示其配置和使用方法。包括添加依赖、配置连接信息、自定义序列化方式以及实现仓储接口。 ... [详细]
  • Spring Boot单元测试中Redis连接失败的解决方案
    本文探讨了在Spring Boot项目中进行单元测试时遇到Redis连接问题的原因及解决方法,详细分析了配置文件加载路径不当导致的问题,并提供了有效的解决方案。 ... [详细]
  • Nginx 反向代理与负载均衡实验
    本实验旨在通过配置 Nginx 实现反向代理和负载均衡,确保从北京本地代理服务器访问上海的 Web 服务器时,能够依次显示红、黄、绿三种颜色页面以验证负载均衡效果。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 我有一个SpringRestController,它处理API调用的版本1。继承在SpringRestControllerpackagerest.v1;RestCon ... [详细]
author-avatar
woainimamamamama
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有