为什么会有这边博文?
因为公司原因,领导又让我捡起荒废了一年多的ios,了解对ios应用脱壳以及反编译hook相关知识.相比于安卓的hook来说(想了解安卓hook的可以参考我的另外一篇文章),ios的hook要麻烦的多,前人栽树后人乘凉,希望我的这边文章能给大家对ios的hook有个清晰的认识和思路.
一. 项目需求
本文以很久以前上架的一个练手app为例(app有点烂,将就一下吧,点击传送门). app大概是这个样子
点击生成二维码,会进入到一个生成二维码的界面.我们本次的任务就是篡改点击事件,实现点击生成二维码,弹出一个弹窗.
二. 项目流程
逻辑比较清晰,参考下图:
三. 工具准备
1. 一台越狱设备(不知道怎么越狱的自己先行百度,本人试验机是ipad 11.3.1系统)
2. 安装要脱壳的应用
四. 脱壳
以下是主流的目前三种脱壳方式,前两种貌似在高版本中都会出现问题,如果你的系统在9.0以下,可以考虑使用,如果是9.0以上,建议使用第三种.
1. Clutch工具静态砸壳
这个方式主要是利用Clutch工具进行砸壳,可以参考友军的文章,我就不重复造轮子了.(注意高版本ios系统可能会出现kill9错误,无法脱壳)
2.dumpdecrypted.dylib动态库 砸壳
从github上下载代码(传送门),编译动态库dumpdecrypted.dylib.利用该动态库进行脱壳,可以参考友军文章,缺点是低版本有效,高版本会出现各种问题.
3.frida-ios-dump 砸壳
由于该项目是个python项目,所以需要python环境.
++第一步++,
手机端
打开cydia 添加源: https://build.frida.re
打开刚刚添加的源 安装 frida
安装完成!检查是否工作可以可在手机终端运行 frida-ps -U 查看
++第二步:++
电脑端下载源码,千万注意这个源码是分3.x和2.x python版本的,一定要根据自己的ptthon环境版本下载相应版本的源码!!!
++第三步++
编译源码(可能会遇到各种安装第三方库错误,耐心解决近,或者下方私信我).修改dump.py文件,把ip改成手机端ip
++第四步++:
执行脱壳命令
./dump.py 应用名称
成功后就会在项目目录中产生相应的脱壳后的ipa文件,如下图
五. 使用Class-dump导出头文件
第一步:
下载
Class-dump
,得到Class-dump 运行库
第二步,解压我们刚才得到的ipa文件(修改成.zip解压即可),得到QrCode.app文件
第三步:
导出.h文件
执行命令
class-dump -H QrCode.app文件路径 -o 导出的文件夹路径
完成后就能看到导出的.h文件了
六. 分析源码
第一步.
安装MonkeyDev,如何安装请参考神器开源项目[传送门],里面有详细文档
第二步.
安装成功后您的xcode新建项目时就会出现如下图工程:
第三步:
选择MonkeyApp新建工程,将我们脱壳后的ipa文件放入项目对应文件夹,其他都不用修改,选择真机直接运行
第四步:
调试应用,得到扫描界面的控制器类MainController,我试图获取uiveiw的action,但发现他的action是动态写在代码中的
我们搜索我们上面得到的头文件,找到MainController.h文件,代码如下:
可以看到有个setListener方法和两个uiveiw,基本我们可以确定我们需要的点击事件就在setListener方法中.下面我们验证下.
第四步:
对刚才我们得到的QRCode.app文件显示包内容,可以得到moth-o类型的源码文件QRCode
下载Hopper工具,将QRCode文件拖进去,就可以查看响应的oc伪码,以及汇编代码.如下图
搜索MainController,找到setListener方法,查看oc伪码
发现他跳转了menuAction方法,我们双击点进去
可以看到,就是通过在这里处理跳转事件,控制程序跳转到下个控制,也验证了我们的猜想是正确的,我们只需要拦截 setListener方法,当他点击生成二维码这个图片view的时候,让他弹个窗即可.
七.编写hook拦截代码
回到我们新建的MonkeyApp工程,新建HookAlert.m文件,编写hook逻辑,拦截代码
运行后点击生成二维码查看效果:
出现弹窗,拦截成功!
补充说明:
MonkeyApp提供了多种hook的写法,这里我们使用的是CaptainHook的写法,我简单介绍下用法(官方竟然没有详细的api说明!)
一个单独的hook类,大概包含以下三部分,看一查看我写的注释
#import
#import
#import
CHDeclareClass(MainController) //声明hook的类
//声明hook的方法,数字代码参数个数,第一个参数一般是self,第二个参数代表返回值,第三个参数是类名,第四个是方法名,后面接方法参数以及类型
CHOptimizedMethod1(self, void, MainController, menuAction,id,arg1){
//获取类变量view的值
UIView* item2= CHIvar(self, _item2_bgview,__strong UIView*) ;
UIView* item=[arg1 view];
if(item2==item){
//拦截 点击事件
UIAlertView *alert=[UIAlertView new];
[alert setTitle:@"提示"];
[alert setMessage:@"拦截成功"];
[alert show];
NSLog(@"测试成功...%@ : %@",arg1,item2);
}else{
// 其他逻辑正常执行元源代码
CHSuper1(MainController, menuAction, arg1);
}
}
// 构造方法,
CHConstructor{
CHLoadLateClass(MainController); //再次声明hook的类
CHClassHook1(MainController, menuAction); //再次声明hook的方法
}
八. 总结
至此,我们的ios从脱壳到分析再到代码拦截就完成了,网上很多文章都是要么写怎么脱壳,要么怎么写hook,要么就是写怎么分析,很少有一个写全面流程的文章.希望这边文章对大家有帮助,喜欢就伸手点个关注吧.