非越狱App集成

Alone_Monkey edited this page Sep 25, 2018 · 47 revisions

选真机编译运行!

准备好砸壳的ipa或者app

第一步是准备好砸壳的ipa或者app,可以从某助手下载越狱应用(下载的也有没砸壳的QAQ)。

创建MonkeyApp项目

点击File - New - Project...创建iOS项目,选择MonkeyApp

image

然后填写Product Name,对于非越狱设备可以不用管Target App,如果是越狱设备的话可以在Target App填写目标App的名字或者bundle id,工具将会自动使用frida-ios-dump提取ipa文件(注意:要先按frida-ios-dump repo的README配置好环境!),如下所示:

image

另外/opt/MonkeyDev/bin/dump.py里面可以指定ip、port以及password。

创建完成之后,你会得到一个这样的工程:

image

这里我创建的项目名字就是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.frameworklibcycript.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,效果如下:

Demo App

MonkeyApp不拖入App或者ipa的情况下,会有一个默认的App,以供读者自己测试,样子大概是这个样子····

image

你可以自己修改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

工程已集成class-dump导出可执行文件OC头文件的功能,可在build settings最下面开启该功能。

image

开启后build会自动进行class-dump的操作,然后会在项目的目录下生成一个头文件的文件夹:

image

restore-symbol

一般应用发布后调试堆栈是没有符号信息的,由于OC语言的特性,需要保存类名和方法名,所以可以根据具体方法的地址填写到符号表中还原符号表。 具体可以阅读文章 iOS符号表恢复&逆向支付宝

开启该功能的方式和class-dump一样。

方法跟踪日志

增加对方法跟踪的日志打印,代替烦人的logify.pl,只需配置一下即可,在新建项目中找到MD

  • ENABLE: 设置为YES开启方法跟踪,默认为NO。
  • CLASS_LIST: 设置需要跟踪的类或指定的方法,如果是对整个类进行跟踪只用写类名,对类里面特定的方法需要在加一个Array数组加上方法名,参考默认的写法。

主要代码来自qhd的ANYMethodLog

默认集成的库

本工具会默认集成RevealServer.frameworklibcycript.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

集成网络cy脚本

通过配置CycriptConfig.plist可以导入从网络下载的cy脚本,比如通过如下的配置:

image

LoadAtLaunch表示是否在启动的时候的时候默认加载脚本,默认加载的脚本就不用再@import xxx导入,可以直接使用。如果不是默认加载的脚本就需要@import xxx导入,xxx就是图中的key,比如@import md。

priority表示加载的优先级,数字越小优先级越高,比如某些脚本需要依赖其它脚本就需要调整优先级,让被依赖的脚本先加载。

contenturl 脚本可以直接写到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

集成Frida

如果自己集成第三方现成SDK的库也是一样的步骤,不过需要注意修改install path:

install_name_tool -id @executable_path/Frameworks/xxxx.dylib xxxx.dylib

由于Frida的动态库太大了就没有默认集成在MonkeyDev,但是自己集成起来也是非常简单的就两步:

  1. FridaGadget.dylib下载动态库增加到App最后的Copy Files里面:

image

  1. 将FridaGadget.dylib链接到MonkeyDev注入动态库的依赖里面:

image

启动日志有: Frida: Listening on 127.0.0.1 TCP port 27042 就是集成成功。

增加资源

把你需要嵌入的Bundle资源和storyboard拷贝到这个目录就可以了哦~

upadte: 更新增加资源方式,直接往MonkeyApp里面增加资源即可,比如新建test.plist文件选择MonkeyApp的Target,保证要增加的资源在如下列表中:

更改名字和bundleid

如果需要更改重签应用的显示名字和bundle id可以在Xcode设置即可,想使用原来的bundle id进行重签,设置build settings里面的MONKEYDEV_DEFAULT_BUNDLEID为YES。

image

生成IPA

运行之后在源代码的LatestBuild目录双击createIPA.command即可生成IPA文件。

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.