重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
工具名称用途区别备注
成都创新互联公司主营李沧网站建设的网络公司,主营网站建设方案,App定制开发,李沧h5成都小程序开发搭建,李沧网站营销推广欢迎李沧等地区企业咨询
theos、iosOpenDev生成dylib
insert_dylib、optool、yololib向二进制文件插入dylib
install_name_tool
修改dylib引用路径
iResign、sigh resign、codesign等重签名工具修改后的二进制文件是需要重签名的
二、过程
1、生成dylib
dylib的生成 可采用theos,也可采用iosOpenDev。
theos是越狱专门开发用的工具,生成的dylib可直接作用于越狱机器上。
但theos并不是apple源生支持的工具,它在Mac端编译生成deb包,安装进IOS系统,由IOS系统dpkg安装成插件模式 并随之生成dylib。theos在Mac端需要调用IOS开发SDK,目前无法调用9.3以上的SDK,theos工具没有更新。
iosOpenDev则是apple官方支持的插件生成工具,可直接由Xcode生成。
这种dylib由两种 CaptainHookTweak、Logos Tweak.
不过这两种没什么区别:Logos Tweak的语法较为简单 同theos的一致,CaptainHookTweak较为复杂。
2、插入dylib
这三种工具 均可向二进制文件插入dylib 不过各有千秋
yololib仅能对64位的二进制文件 插入 32位插入也能成功 但是 出现如下
insert_dylib既可以对64位 也可以对32位进行插入 同时 还会供选择 是否删除掉二进制文件原有的签名 即 LC_CODE_SIGNATURE
optool 则功能更强大 可供选择 是插入哪种LC LIB。本例暂用不上。
3、修改dylib引用
插入dylib后 需要对它添加cydiaSubstrate dylib的引用。即使用install_name_tool这个工具
之前就是这个地方没有做 导致签名后的文件 一直安装出现闪退 dylib也没有调用
由于目前手头没有越狱手机 之前没有调出过cydiaSubstrate dylib 所以这个步骤暂时中断(最主要 每个越狱版本系统的cydiaSubstrate dylib都是不一样的 目前没有可越狱的系统 也就没有对应的dylib)
不过 可细想 因为越狱手机上 是自己存在这个cydiaSubstrate dylib的 所以 theos插件本身不必再导入这个dylib,直接对其添加引用即可。
然而 在非越狱手机上 就需要自己把这个cydiaSubstrate dylib放进app包里 并手头添加它的引用路径了
既然这样 那apple 源生的iosOpenDev为什么还要出开发dylib的工具呢
那是因为apple 推出iosOpenDev生成dylib 根本不是让你这样玩的 apple是让你把这个dylib添加进IOS工程里 在工程里对其添加引用 如果以后该app有少量的更新 只需要更新这个dylib即可 而不必更新整个app。这个在IOS开发中 叫做 增量更新。
在完全不使用cydia提供的hook接口的基础上 也可以使用openDev使用的hook接口
操作如下:
a:将 dylib(如需要调用cydia substrate 的 MSHOOK函数 则 还需要添加cydia substrate dylib)到app包里;
b:insert工具插入。注意这里有一个坑 就是凡是复制到dylib里的包 除了使用install_name_tool对其添加引用外 插入到Mach-O LOAD COMMANDS里的dylib还需要添加可执行路径
首先需要cd进app包里
然后/Users/danchen/desktop/diff_hook/insert_dylib@executable_path/ios_hook.dylibhook_demo hook_demo
c:之后重签名
对app包里每一个修改的添加的文件进行签名
codesign -f -s "iPhone Developer: 694708086@qq.com (T4MM3JZDL2)" hook_demo
codesign -f -s "iPhone Developer: 694708086@qq.com (T4MM3JZDL2)" ios_hook.dylib
再对整个app包添加签名权限
codesign -f -s "iPhone Developer: 694708086@qq.com (T4MM3JZDL2)" --entitlements entitlements.plist hook_demo.app
直接安装app包即可,也可以使用xcrun将其打包成ipa 安装即可
dylib里的内容
4、重签名
完成这些步骤后
首先 要对 修改过的二进制文件、dylib、cydiaSubstrate dylib进行重签名 即把iPhone Developer: 694708086@qq.com (T4MM3JZDL2) 写入进去
然后 使用xcrun将app文件 打包成ipa 使用iResign、sigh resign等工具 对ipa包重签名 再安装进系统
重签名权限文件entitlements.plist
可使用ldid -e 二进制文件查看entitlements文件内容生成
三、区别
theos与iosOpenDev
区别theosiosOpenDev备注
来源越狱开发作者appletheos来自第三方开发,iosOpenDev则是apple官方Xcode支持的
UI无Xcodetheos没有开发UI界面,iosOpenDev的开发界面是Xcode
版本支持目前theos仅支持SDK IOS9.3以下都支持两者调用SDK,theos仅支持SDK9.3以下,目前theos作者尚未更新工具
hook 语言方式Logos TweakLogos Tweak、CaptainHookTweak
insert_dylib、optool、yololib工具差别
区别insert_dyliboptoolyololib备注
支持结构64、32位都支持64、32位都支持仅支持64位
四、总结
这种方式仅能hook app自身进程里所调用的函数 无法hook系统级别的进程
由于非越狱上的沙盒机制,本地app仅能访问本app数据,无法访问别的app的数据,访问系统数据(相册、地理位置等)也需要向用户请求权限。更别说去hook系统级别的进程。
当然 存在非越狱下 绕过沙盒机制的技术:
比如这个人 非越狱下一个app卸载另一个app、一个app获取领一个app里的文件内容。但这种漏洞技术没有公开 仅存在于越狱团队内部。而且这种漏洞技术也没能hook系统级进程。
理论上来讲 非越狱下hook系统级别的进程 是有可能的 只不过难度相当大(换言之 如果真有这种非越狱下就能hook系统级别的漏洞和技术的话 越狱团队干嘛还费那大力气去越狱呢)
iOS逆向 Reveal FLEXLoader 图层结构
对于iOS逆向,在我们拿到解密后的可执行文件后,我们研究的突破口其实就是界面的所在信息,毕竟在没有任何的针对信息的情况下,去在Hopper中看可执行文件的数据,无异于大海捞针。所以这时候我们需要针对的信息,需要我们hook的控制器或是类名,这样接下来的研究就会有自己的方向了。
学iOS的童鞋都知道这个神器,不管我们在正向还是逆向开发中都可以用到这个查看图层信息的工具,当然在两种情况的使用的方法是不一样的,这儿我主要介绍Reveal在逆向开发中的使用方法。
在用这个工具的时候,其实是踩了很大的坑的。
利用两种方式的使用Reveal工具,在打开需要逆向的APP后,提示The network connection was lost
至于这两种方式:
打开Reveal ,Reveal菜单-Help-Show Reveal Library in Finder -iOS Library
方式一:
注意,这个plist文件的格式不能出错,不然killall SpringBoard命令后出现白苹果,至于他们的bundleid ,直接到APP的目录下看info.plist文件即可。
方式二:
推荐方式
/Library/RHRevealLoader,在手机的Library下建立RHRevealLoader文件夹,之后把libReveal.dylib放进这个文件夹下。
在手机中的设置中找到Reveal-Enabled Applications-你需要的app
之后将mac和iOS设备中连接同一个局域网中,打开APP后,在Reveal中查看图层信息
当然如果你也出现了Reveal中无法显示问题时:
解决方法:这个是你的libReveal.dylib有问题,这时候你需要换一个
github下的v2.0中的Reveal.dylib地址
这样将新的libReveal.dylib在手机中替换原来的即可,当然还有一种可能就是连接的局域网网速太差了。
我们期待的结果是:
这个工具是在怎么安装Reveal都安装不了的情况下,去了解的一个可以看图层的工具,这个工具和Reveal不同的是不需要连接Mac电脑,只需要在Cydia中安装并且在设置中开启需要的查看的图层的APP。
可以看到这个工具可以查看APP的文件目录,整个APP的视图构架,当前视图的图层结构,当然还有很多功能等着你去发现。
这个是我们的目标视图的图层结构。
这样通过图层工具我们就比较快的找到我们需要研究的对象了。
[img]我们都知道在windows下可以通过API轻松的hook很多消息,IOS里面貌似还没有现成的API(可能是我还没发现吧),前段时间碰巧看到Objective-C运行时的一些东西,于是心想着是不是可以尝试一下实现hook的功能。
下面先直接上源码:1//2//TestHookObject.m3//TestHookMessage4//5//Created by mapleCao on 13-2-28.6//Copyright (c) 2013年 mapleCao. All rights reserved.7//89#import"TestHookObject.h"10#importobjc/objc.h11#importobjc/runtime.h1213@implementation
TestHookObject1415//this method will just excute once16+ (void)initialize17{18//获取到UIWindow中sendEvent对应的method19Method sendEvent = class_getInstanceMethod([UIWindowclass
], @selector(sendEvent:));20Method sendEventMySelf = class_getInstanceMethod([selfclass
], @selector(sendEventHooked:));2122//将目标函数的原实现绑定到sendEventOriginalImplemention方法上23IMP sendEventImp =
method_getImplementation(sendEvent);24class_addMethod([UIWindowclass
], @selector(sendEventOriginal:), sendEventImp, method_getTypeEncoding(sendEvent));2526//然后用我们自己的函数的实现,替换目标函数对应的实现27IMP sendEventMySelfImp =
method_getImplementation(sendEventMySelf);28class_replaceMethod([UIWindowclass
], @selector(sendEvent:), sendEventMySelfImp, method_getTypeEncoding(sendEvent));29}3031/*32* 截获到window的sendEvent33* 我们可以先处理完以后,再继续调用正常处理流程34*/35- (void)sendEventHooked:(UIEvent *)event36{37//do something what ever you want38NSLog(@"haha, this is my self sendEventMethod!!!!!!!");3940//invoke original implemention41[self performSelector:@selector(sendEventOriginal:) withObject:event];42}4344@end下面我们来逐行分析一下上面的代码:
首先我们来看19行,这一行主要目的是获取到UIWindow原生的sendEvent的
Method(一个结构体,用来对方法进行描述)
,接着第20行是获取到我们自己定义的类中的sendEvent的Method
(这两个方法的签名必须一样,否则运行时报错)
。第23行我们通过UIWindow原生的sendEvent的Method获取到对应的
IMP(一个函数指针)
,第24行使用运行时API Class_addMethod给UIWindow类添加了一个叫sendEventOriginal的方法,该方法使用UIWindow原生的sendEvent的实现,并且有着相同的方法签名
(必须相同,否则运行时报错)。
27行是获取我们自定义类中的sendEventMySelf的IMP,28行是关键的一行,这一行的主要目的是为UIWindow原生的sendEvent指定一个新的实现,我们看到我们将该实现指定到了我们自己定义的sendEventMySelf上。到了这儿我们就完成了偷梁换柱,大功告成。
执行上面这些行以后,我们就成功的将UIWindow的sendEvent重定向到了我们自己的写的sendEventMySelf的实现,然后将其原本的实现重定向到了我们给它新添加的方法sendEventOriginal中。而sendEventMySelf中,我们首先可以对这个消息进行我们想要的处理,然后再通过41行调用sendEventOriginal方法转到正常的执行流程。
为什么执行起来不报错,而且还会正常执行?因为sendEventMySelf是UIWindow的sendEvent重定向过来的,所以在运行时该方法中的self代表的就是UIWindow的实例,而不再是TestHookObject的实例了。加上sendEventOriginal是我们通过运行时添加到UIWindow的实例方法,所以可以正常调用。当然如果直接通过下面这种方式调用也是可以的,只不过编译器会提示警告
(编译器没那么智能)
,因此我们采用了performSelector的调用方式。
[self sendEventOriginal:event];以上就是Hook的实现,使用时我们只需要让TestHookObject类执行一次初始话操作就可以了,执行完以后。UIWindow的sendEvent消息就会会hook到我们的sendEventMySelf中了。
下面是调用代码:
Install Hook
代码中我们还专门添加了一个button来验证,hook完以后消息是否正常传递。经验证消息流转完全正常。
阿里妹导读:刚刚,阿里巴巴正式对外开源了基于 Apache 2.0 协议的协程开发框架 coobjc,开发者们可以在 Github 上自主下载。
coobjc是为iOS平台打造的开源协程开发框架,支持Objective-C和Swift,同时提供了cokit库为Foundation和UIKit中的部分API提供了 协程 化支持,本文将为大家详细介绍coobjc的设计理念及核心优势。
从2008年第一个iOS版本发布至今的11年时间里,iOS的异步编程方式发展缓慢。
基于 Block 的异步编程回调是目前 iOS 使用最广泛的异步编程方式,iOS 系统提供的 GCD 库让异步开发变得很简单方便,但是基于这种编程方式的缺点也有很多,主要有以下几点:
针对多线程以及尤其引发的各种崩溃和性能问题,我们制定了很多编程规范、进行了各种新人培训,尝试降低问题发生的概率,但是问题依然很严峻,多线程引发的问题占比并没有明显的下降,异步编程本来就是很复杂的事情,单靠规范和培训是难以从根本上解决问题的,需要有更加好的编程方式来解决。
上述问题在很多系统和语言开发中都可能会碰到,解决问题的标准方式就是使用协程,C#、Kotlin、Python、Javascript 等热门语言均支持协程极其相关语法,使用这些语言的开发者可以很方便的使用协程及相关功能进行异步编程。
2017 年的 C++ 标准开始支持协程,Swift5 中也包含了协程相关的标准,从现在的发展趋势看基于协程的全新的异步编程方式,是我们解决现有异步编程问题的有效的方式,但是苹果基本已经不会升级 Objective-C 了,因此使用Objective-C的开发者是无法使用官方的协程能力的,而最新 Swift 的发布和推广也还需要时日,为了让广大iOS开发者能快速享受到协程带来的编程方式上的改变,手机淘宝架构团队基于长期对系统底层库和汇编的研究,通过汇编和C语言实现了支持 Objective-C 和 Swift 协程的完美解决方案 —— coobjc。
核心能力
内置系统扩展库
coobjc设计
最底层是协程内核,包含了栈切换的管理、协程调度器的实现、协程间通信channel的实现等。
中间层是基于协程的操作符的包装,目前支持async/await、Generator、Actor等编程模型。
最上层是对系统库的协程化扩展,目前基本上覆盖了Foundation和UIKit的所有IO和耗时方法。
核心实现原理
协程的核心思想是控制调用栈的主动让出和恢复。一般的协程实现都会提供两个重要的操作:
我们基于线程的代码执行时候,是没法做出暂停操作的,我们现在要做的事情就是要代码执行能够暂停,还能够再恢复。 基本上代码执行都是一种基于调用栈的模型,所以如果我们能把当前调用栈上的状态都保存下来,然后再能从缓存中恢复,那我们就能够实现yield和 resume。
实现这样操作有几种方法呢?
上述第三种和第四种只是能过做到跳转,但是没法保存调用栈上的状态,看起来基本上不能算是实现了协程,只能算做做demo,第五种除非官方支持,否则自行改写编译器通用性很差。而第一种方案的 ucontext 在iOS上是废弃了的,不能使用。那么我们使用的是第二种方案,自己用汇编模拟一下 ucontext。
模拟ucontext的核心是通过getContext和setContext实现保存和恢复调用栈。需要熟悉不同CPU架构下的调用约定(Calling Convention). 汇编实现就是要针对不同cpu实现一套,我们目前实现了 armv7、arm64、i386、x86_64,支持iPhone真机和模拟器。
说了这么多,还是看看代码吧,我们从一个简单的网络请求加载图片功能来看看coobjc到底是如何使用的。
下面是最普通的网络请求的写法:
下面是使用coobjc库协程化改造后的代码:
原本需要20行的代码,通过coobjc协程化改造后,减少了一半,整个代码逻辑和可读性都更加好,这就是coobjc强大的能力,能把原本很复杂的异步代码,通过协程化改造,转变成逻辑简洁的顺序调用。
coobjc还有很多其他强大的能力,本文对于coobjc的实际使用就不过多介绍了,感兴趣的朋友可以去官方github仓库自行下载查看。
我们在iPhone7 iOS11.4.1的设备上使用协程和传统多线程方式分别模拟高并发读取数据的场景,下面是两种方式得到的压测数据。
从上面的表格我们可以看到使用在并发量很小的场景,由于多线程可以完全使用设备的计算核心,因此coobjc总耗时要比传统多线程略高,但是由于整体耗时都很小,因此差异并不明显,但是随着并发量的增大,coobjc的优势开始逐渐体现出来,当并发量超过1000以后,传统多线程开始出现线程分配异常,而导致很多并发任务并没有执行,因此在上表中显示的是大于20秒,实际是任务已经无法正常执行了,但是coobjc仍然可以正常运行。
我们在手机淘宝这种超级App中尝试了协程化改造,针对部分性能差的页面,我们发现在滑动过程中存在很多主线程IO调用、数据解析,导致帧率下降严重,通过引入coobjc,在不改变原有业务代码的基础上,通过全局hook部分IO、数据解析方法,即可让原来在主线程中同步执行的IO方法异步执行,并且不影响原有的业务逻辑,通过测试验证,这样的改造在低端机(iPhone6及以下的机器)上的帧率有20%左右的提升。
简明
易用
清晰
性能
程序是写来给人读的,只会偶尔让机器执行一下。——Abelson and Sussman
基于协程实现的编程范式能够帮助开发者编写出更加优美、健壮、可读性更强的代码。
协程可以帮助我们在编写并发代码的过程中减少线程和锁的使用,提升应用的性能和稳定性。
本文作者:淘宝技术
MachO文件。iOS是由苹果公司开发的移动操作系统。苹果公司最早于2007年1月9日的Macworld大会上公布这个系统,其中逆向hook文件根据系统默认的设置储存在MachO文件中。在JS逆向中,通常把替换原函数的过程都称为hook。
- (instancetype)init {
if ([super init]) {
// 使用 Aspects 进行方法的拦截
// AspectOptions 三种方式选择:在原本方法前执行、在原本方法后执行、替换原本方法
[UIViewController aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionAfter usingBlock:^(idaspectinfo aspectInfo, BOOL animated){
UIViewController * vc = [aspectInfo instance];
[self viewWillAppear:animated viewController:vc];
} error:NULL];
}
return self;
}/aspectinfo
这只是简单拦截原理