-
Notifications
You must be signed in to change notification settings - Fork 1.2k
非越狱App集成
选真机编译运行!
第一步是准备好砸壳的ipa或者app,可以从某助手下载越狱应用(下载的也有没砸壳的QAQ)。
点击File - New - Project...
创建iOS项目,选择MonkeyApp
。
然后填写Product Name,对于非越狱设备可以不用管Target App,如果是越狱设备的话可以在Target App填写目标App的名字或者bundle id,工具将会自动使用frida-ios-dump提取ipa文件(注意:要先按frida-ios-dump repo的README配置好环境!),如下所示:
另外/opt/MonkeyDev/bin/dump.py
里面可以指定ip、port以及password。
创建完成之后,你会得到一个这样的工程:
这里我创建的项目名字就是MonkeyApp
,所以下面对应的都是MonkeyApp
,你自己创建的由你的项目名字而定!
MonkeyAppDylib
这个是将被注入目标App的动态库,你自己要hook的代码可以在MonkeyAppDylib.m
文件里面写,我在里面写了一些Demo代码,支持OC runtime的HOOK,C函数的fishhook。还支持theos logtweak的写法! 直接写在MonkeyAppDylib.xm
文件文件即可。
Config
这个是cycript的一些脚本下载以及methodtrace配置代码。
LLDBTools
这个是用于LLDB调试的代码,比如po pviews()
。
AntiAntiDebug
这个里面是反反调试的代码。
fishhook
这个是自动集成的fishhook模块。
创建的项目已经自动集成了RevealServer.framework
和libcycript.dylib
,如果选择Release编译的话是不会集成的。
我准备了一个砸壳了的ipa文件,然后我右键项目里面的TargetApp文件夹Show in Finder,把ipa文件拖入下面的位置(当然app文件夹也可以的):
或者支持直接将文件拖到Xcode项目TargetApp下面。
Xcode 8需要另外指定一下依赖,选择Build Phases
,点击Target Dependencies
增加需要注入的动态库即可。如下:
然后编译运行,打开电脑的Reveal
,就可以看到界面了:
从Cycript下载SDK,然后进去SDK目录运行如下命令,Cycript
查看界面也没有问题:
这里Cycript默认端口是6666
。
在MonkeyAppDylib.m
文件中写了自己的代码之后就可以直接下断点调试,效果如下:
MonkeyAppDylib.xm
文件也支持动态调试,在文件左侧点击下断点即可,第一次由于后缀Xcode不识别,下的断点不会显示出来,但是断点是生效的!在右侧将文件类型改成Object C++ 重新打开文件或重启Xcode,效果如下:
MonkeyApp
不拖入App或者ipa的情况下,会有一个默认的App,以供读者自己测试,样子大概是这个样子····
你可以自己修改MonkeyAppDylib.m
里面的代码,这个是笔者针对Demo
写的例子啦,另外注意的是MonkeyApp里面都是ARC,所以网上很多MRC的写法是有问题的,多多参考笔者的例子: https://github.com/AloneMonkey/WeChatPod
CHDeclareClass(CustomViewController)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wstrict-prototypes"
//add new method
CHDeclareMethod1(void, CustomViewController, newMethod, NSString*, output){
NSLog(@"This is a new method : %@", output);
}
#pragma clang diagnostic pop
CHOptimizedMethod0(self, NSString*, CustomViewController,getMyName){
//get origin value
NSString* originName = CHSuper(0, CustomViewController, getMyName);
NSLog(@"origin name is:%@",originName);
//get property
NSString* password = CHIvar(self,_password,__strong NSString*);
NSLog(@"password is %@",password);
[self newMethod:@"output"];
//set new property
self.newProperty = @"newProperty";
NSLog(@"newProperty : %@", self.newProperty);
//change the value
return @"AloneMonkey";
}
//add new property
CHPropertyRetainNonatomic(CustomViewController, NSString*, newProperty, setNewProperty);
CHConstructor{
CHLoadLateClass(CustomViewController);
CHClassHook0(CustomViewController, getMyName);
CHHook0(CustomViewController, newProperty);
CHHook1(CustomViewController, setNewProperty);
}
工程已集成class-dump导出可执行文件OC头文件的功能,可在build settings最下面开启该功能。
开启后build会自动进行class-dump的操作,然后会在项目的目录下生成一个头文件的文件夹:
一般应用发布后调试堆栈是没有符号信息的,由于OC语言的特性,需要保存类名和方法名,所以可以根据具体方法的地址填写到符号表中还原符号表。 具体可以阅读文章 iOS符号表恢复&逆向支付宝
开启该功能的方式和class-dump一样。
增加对方法跟踪的日志打印,代替烦人的logify.pl,只需配置一下即可,在新建项目中找到MD
- ENABLE: 设置为YES开启方法跟踪,默认为NO。
- CLASS_LIST: 设置需要跟踪的类或指定的方法,如果是对整个类进行跟踪只用写类名,对类里面特定的方法需要在加一个Array数组加上方法名,参考默认的写法。
主要代码来自qhd的ANYMethodLog。
新版已经迁移到OCMethodTrace,请到项目主页查看相关用法。
本工具会默认集成RevealServer.framework
和libcycript.dylib
,em…..
集成的RevealServer.framework
是最新版本的,所以你可能需要最新的Reveal
,否则使用自己的RevealServer.framework
替换掉/opt/MonkeyDev/frameworks
下面的RevealServer.framework
。
使用Release编译生成将不会集成reveal和cycript。
首先将需要注入的dylib或者framework按下面的方式拷贝到frameworks目录下:
然后在下图的位置add进去,emmm。。。。就可以了。
静态库的话,直接增加到上面,指定search path
就可以了,和正常开发没啥区别。。。
注意动态库本身的install_path,可以通过install_name_tool -id
修改其为@executable_path/Frameworks/xxxxx
通过配置CycriptConfig.plist可以导入从网络下载的cy脚本,比如通过如下的配置:
LoadAtLaunch
表示是否在启动的时候的时候默认加载脚本,默认加载的脚本就不用再@import xxx导入,可以直接使用。如果不是默认加载的脚本就需要@import xxx导入,xxx就是图中的key,比如@import md。
priority
表示加载的优先级,数字越小优先级越高,比如某些脚本需要依赖其它脚本就需要调整优先级,让被依赖的脚本先加载。
content
和url
脚本可以直接写到content
里面也可以是网络的url
,会自动下载下来。
➜ cycript_0.9.594 ./cycript -r 192.168.2.248:6666
cy# APPID
@"com.alonemonkey.TestCycript"
cy# pviews()
`<UIWindow: 0x105313b60; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x1c425bae0>; layer = <UIWindowLayer: 0x1c40394e0>>
| <UIView: 0x1053205d0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x1c403bd80>>
| | <UILabel: 0x10531e7d0; frame = (102.5 45; 170 40); text = 'AloneMonkey'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408c0d0>>
| | <UILabel: 0x1053207b0; frame = (97.5 110; 180 40); text = 'You are the best!!!'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408e150>>
| | <UITextView: 0x105836000; frame = (26 230; 343 427); text = '/opt/MonkeyDev/bin/md
- ...'; clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x1c0058fc0>; layer = <CALayer: 0x1c002f1a0>; contentOffset: {0, 0}; contentSize: {343, 317}; adjustedContentInset: {0, 0, 0, 0}>
| | | <<_UITextContainerView: 0x105318060; frame = (0 0; 343 317); layer = <__UITextTiledLayer: 0x1c40c42f0>> minSize = {0, 0}, maxSize = {1.7976931348623157e+308, 1.7976931348623157e+308}, textContainer = <NSTextContainer: 0x1c0105fa0 size = (343.000000,inf); widthTracksTextView = YES; heightTracksTextView = NO>; exclusionPaths = 0x1c40025e0; lineBreakMode = 0>
| | | | <__UITileLayer: 0x1c0240780> (layer)
| | | | <__UITileLayer: 0x1c0240720> (layer)
| | | | <__UITileLayer: 0x1c0240a20> (layer)
| | | <UIImageView: 0x105322260; frame = (3 421.5; 337 2.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x1c403c620>>
| | | <UIImageView: 0x105322490; frame = (337.5 380; 2.5 44); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x1c403c6e0>>
| | <UIButton: 0x1053163b0; frame = (127.5 175; 120 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x1c4039aa0>>
| | | <UIButtonLabel: 0x10540fcf0; frame = (2 6; 116.5 18); text = 'ShowChangeLog'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c0087b70>>
| | <_UILayoutGuide: 0x105320fa0; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x1c403bfe0>>
| | <_UILayoutGuide: 0x1053213a0; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x1c403bee0>>`
cy# pvcs()
"<CustomViewController 0x1053133f0>, state: appeared, view: <UIView 0x1053205d0>"
cy# pactions(#0x1053163b0)
"<CustomViewController: 0x1053133f0> showChangeLog:"
cy# rp(#0x1053163b0)
`<UIButton: 0x1053163b0; frame = (127.5 175; 120 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x1c4039aa0>>
<UIView: 0x1053205d0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x1c403bd80>>
<CustomViewController: 0x1053133f0>
<UIWindow: 0x105313b60; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x1c425bae0>; layer = <UIWindowLayer: 0x1c40394e0>>
<UIApplication: 0x105406120>
<AppDelegate: 0x1c002b1a0>`
cy# ?exit
如果自己集成第三方现成SDK的库也是一样的步骤,不过需要注意修改install path
:
install_name_tool -id @executable_path/Frameworks/xxxx.dylib xxxx.dylib
由于Frida的动态库太大了就没有默认集成在MonkeyDev,但是自己集成起来也是非常简单的就两步:
- 从FridaGadget.dylib下载动态库增加到App最后的Copy Files里面:
- 将FridaGadget.dylib链接到MonkeyDev注入动态库的依赖里面:
启动日志有: Frida: Listening on 127.0.0.1 TCP port 27042
就是集成成功。
把你需要嵌入的Bundle资源和storyboard拷贝到这个目录就可以了哦~
upadte: 更新增加资源方式,直接往MonkeyApp里面增加资源即可,比如新建test.plist文件选择MonkeyApp的Target,保证要增加的资源在如下列表中:
如果需要更改重签应用的显示名字和bundle id可以在Xcode设置即可,想使用原来的bundle id进行重签,设置build settings里面的MONKEYDEV_DEFAULT_BUNDLEID为YES。
运行之后在源代码的LatestBuild目录双击createIPA.command即可生成IPA文件。