iOS-应用安全11 cycript

920 阅读7分钟

Cycript是由Cydia创始人Saurik推出的一款脚本语言,Cycript混合了OC、JavaScript语法的解释器,这意味着我们能够在一个命令中使用Oc或者JavaScript,甚至两者并用。它能够挂钩正在运行的进程,能够在运行时修改很多东西。

引用 www.jianshu.com/p/de0beb21f…

安装

官网上下载SDK到本地,并配置到本地shell中以便全局使用。每个人配置用的shell不一样,一般都是使用bash,我使用是的zsh,就不举步骤了;安装成功标志

$ cycript
cy#

简单使用

lldb需要把程序停下来才能调试,而cycript可以动态的调试;上面已经的步骤已经把cycrip插件安装到了本地电脑上了,那么如何把cycript插件安装到手机呢?

  • 1.如果是越狱手机,那么可以直接在越狱手机中安装cycript插件
  • 2.如果没有越狱手机,那么可以使用MonkeyApp重签微信的ipa包

我这里选择的是第二种。

连接

  • 1.查看Monkey连接端口,当然这端口可以自定义。
  • 2.将你的电脑和手机连上同一个局域网,查看当前网络ip地址
  • 3.将电脑和手机连接上,10.89.3.114 是ip地址,是端口号
$ cycript -r 10.89.3.114:6666
//有cy#这个符号出现就代表连接成功了,就可以愉快调试了
cy#

退出cycript调试 control + d; 如果遇到这个错误:*** _syscall(connect(socket_, info->ai_addr, info->ai_addrlen)):../Console.cpp(306):CYSocketRemote [errno=60],换一个wifi试试、换个手机(换ip)。还是不行的话就用手机给电脑开热点。就是ip或端口或Wi-Fi的问题。

注意:在调试的时候不要将app退到后台,会导致cycript连接失败

Cycript 常用命令

使用例子

//获取keyWindow()
cy# UIWindow.keyWindow()
#"<iConsoleWindow: 0x10aa4e090; baseClass = UIWindow; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x281719860>; layer = <UIWindowLayer: 0x2818b0680>>"

cy# [UIApplication sharedApplication]
#"<UIApplication: 0x10aa17610>"

//内置的cy命令
cy# UIApp
#"<UIApplication: 0x10aa17610>"

//自定义变量
cy# var keyWd = UIWindow.keyWindow()
#"<iConsoleWindow: 0x10aa4e090; baseClass = UIWindow; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x281719860>; layer = <UIWindowLayer: 0x2818b0680>>"
cy# keyWd.rootViewController
#"<MMUINavigationController: 0x10b108600>"

//# 指针打印
cy# #0x10b108600
#"<MMUINavigationController: 0x10b108600>"

//*打印对象变量属性
cy# *keyWd
{isa:iConsoleWindow,_hasOverrideClient:0,_hasOverrideHost:0,_hasInputAssistantItem:0,_constraintsExceptingSubviewAutoresizingConstraints:null,_cachedTraitCollection:null,_animationInfo:null,_layer:#"<UIWindowLayer: 0x2818b0680>",_layerRetained:#"<UIWindowLayer: 0x2818b0680>",_gestureRecognizers:@[#"<_UISystemGestureGateGestureRecognizer: 0x2827160d0; state = Possible; delaysTouchesEnded = NO; view = <iConsoleWindow 0x10aa4e090>>",#"<_UISystemGestureGateGestureRecognizer: 0x2827161c0; state = Possible; delaysTouchesBegan = YES; view = <iConsoleWindow 0x10aa4e090>>"],_window:null,_subviewCache:@[#"<UITransitionView: 0x10a916ab0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x28193b860>>"],_templateLayoutView:null,_pseudo_id:34,_viewDelegate:null,_backgroundColorSystemColorName:@"clearColor",_countOfMotionEffectsInSubtree:0,_unsatisfiableConstraintsLoggingSuspensionCount:0,_countOfTraitChangeRespondersInDirectSubtree:2,_cachedScreenScale:0,_viewFlags:@error,_layoutSubviewsCount:0,_imminentLayoutSubviewsCount:0,_retainCount:14,_draggingSourceDelegate 

//choose() 获取视图中所有的某种类型的对象
cy# choose(UIButton)
[#"<UIButton: 0x10aa5bfb0; frame = (232 20; 88 49); opaque = NO; autoresize = LM; layer = <CALayer: 0x2818d1a20>>",#"<UIButton: 0x10aab7720; frame = (193 13; 19 19); opaque = NO; layer = <CALayer: 0x281972980>>",#"<UICalloutBarButton: 0x10aabb980; frame = (0 0; 30 34); hidden = YES; opaque = NO; layer = <CALayer: 0x281971a20>>",#"<FixTitleColorButton: 0x10a918940; baseClass = UIButton; frame = (20 76; 280 47); clipsToBounds = YES; opaque = NO; autoresize = W; layer = <CALayer: 0x281956820>>",#"<MMBarButton: 0x10a92e120; baseClass = UIButton; frame = (0 0; 40 44); opaque = NO; autoresize = H; layer = <CALayer: 0x281956a80>>",#"<UIButton: 0x10a92e460; frame = (0 0; 58 19); opaque = NO; layer = <CALayer: 0x2819572e0>>",#"<UIButton: 0x10a92f880; frame = (73 0; 58 19); opaque = NO; layer = <CALayer: 0x2819574e0>>",#"<FixTitleColorButton: 0x10a93e9f0; baseClass = UIButton; frame = (20 15; 130 47); clipsToBounds = YES; opaque = NO;

打印视图层级

//recursiveDescription().toString()打印视图层级 
cy# keyWd.recursiveDescription().toString()
`<iConsoleWindow: 0x10aa4e090; baseClass = UIWindow; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x281719860>; layer = <UIWindowLayer: 0x2818b0680>>
   | <UITransitionView: 0x10a916ab0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x28193b860>>
   |    | <UILayoutContainerView: 0x10a944110; frame = (0 0; 320 568); autoresize = W+H; gestureRecognizers = <NSArray: 0x2817dee20>; layer = <CALayer: 0x281935ba0>>
   |    |    | <UINavigationTransitionView: 0x10a97d8d0; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x281936100>>
   |    |    |    | <UIViewControllerWrapperView: 0x10aa50cb0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x281953920>>
   |    |    |    |    | <UIView: 0x10aa33260; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x281925260>>
...

打印视图层级这个方法可以用于查找特定视图

脚本自动连接

在上面的演示中我们每次连接都要输入$ cycript -r 10.89.3.114:6666,其实我们可以用脚本自动连接;

  • 1.找一个不太被修改的位置,新建脚本文件夹和cy脚本文件
 $ cd /Users/xxx
 //新建脚本文件夹
 $ mkdir RFShell
 //新建cy脚本文件并编辑
 $ vim cyLogin.sh

  • 2.给脚本文件添加执行权限
chmod 777 cyLogin.sh
  • 3.全局配置脚本
vi ~/.zshrc

  • 4.测试
$ sh cyLogin.sh
cy#

cycript 练习

//连接cycript
sh cyLogin.sh
cy# UIApp
#"<UIApplication: 0x12fe15150>"
cy# [UIApp setStatusBarHidden:YES]

cy# [UIApp setStatusBarHidden:NO]

cy# [UIApp setApplicationIconBageNumber:998]

复杂数据修改

查找对象

cy# choose(UITableViewLabel)

拿到对象 #"<UITableViewLabel: 0x12fe95a10; frame = (224.5 8; 65.5 27.5); text = '+1876'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2820a3e80>>"

修改对象

cy# #0x12fe95a10.text = "博特尔"

cycript高级用法

cy文件

  • cycript是一门脚本语言,它可以加载封装好的.cy文件
  • 将常见的Cycript功能封装到.cy文件,就可以很方便的调用 MonkeyDev本身集成了几个网络上的.cy文件,所以我们可以调用

使用例子

  • APPID
cy# APPID
@"riceFun.KTest"
  • pactions 打印对象action
cy# pactions(#0x131216a30)
"<WCAccountMainLoginViewController: 0x13001ea00> onSwitch"
  • rp 响应链
cy# rp(#0x131216a30)
`<UIButton: 0x131216a30; frame = (20 18; 181 22); opaque = NO; autoresize = LM; layer = <CALayer: 0x2802e5360>>
<UIView: 0x12fe53d60; frame = (0 0; 320 123); autoresize = LM+RM; layer = <CALayer: 0x2802e4040>>
<UIView: 0x12fe59750; frame = (0 181; 320 123); layer = <CALayer: 0x2802e5e20>>
<WCTableView: 0x130192800; baseClass = UITableView; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x280ceb9f0>; layer = <CALayer: 0x280245dc0>; contentOffset: {0, -64}; contentSize: {320, 304}; adjustedContentInset: {64, 0, 0, 0}>
<UIView: 0x12feaa6f0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x280244200>>
<WCAccountMainLoginViewController: 0x13001ea00>
<UIViewControllerWrapperView: 0x12fd79c90; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x2802e1960>>
<UINavigationTransitionView: 0x12fd5de90; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x28029d500>>
<UILayoutContainerView: 0x12fd7b900; frame = (0 0; 320 568); autoresize = W+H; gestureRecognizers = <NSArray: 0x280c99470>; layer = <CALayer: 0x280293aa0>>
<MMUINavigationController: 0x13087ac00>
<MMUINavigationController: 0x1308d5800>
<UITransitionView: 0x12fdd61b0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x2802e1820>>
<iConsoleWindow: 0x12fd4de20; baseClass = UIWindow; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x280cd6970>; layer = <UIWindowLayer: 0x28036ef20>>
<UIApplication: 0x12fe15150>
<MicroMessengerAppDelegate: 0x283fdf100>`

自己封装.cy文件

  • 新建.cy文件 Xcode - File - New - Empty文件

  • copy File 到工程中

  • 编辑.cy文件

    下面是我的cy文件的内容,便于大家参考

//IIFE 匿名函数自执行表达式

(function(exports){

    K_APPID = [NSBundle mainBundle].bundleIdentifier,
    K_APPPATH = [NSBundle mainBundle].bundlePath,

    //如果有变化,就用function去定义!!
    K_Rootvc = function(){
        return UIApp.keyWindow.rootViewController;
    };


    K_KeyWindow = function(){
        return UIApp.keyWindow;
    };

    K_GetCurrentVCFromRootVc = function(rootVC){
        var currentVC;
        if([rootVC presentedViewController]){
            rootVC = [rootVC presentedViewController];
        }

        if([rootVC isKindOfClass:[UITabBarController class]]){
            currentVC = K_GetCurrentVCFromRootVc(rootVC.selectedViewController);
        }else if([rootVC isKindOfClass:[UINavigationController class]]){
            currentVC = K_GetCurrentVCFromRootVc(rootVC.visibleViewController);
        }else{
            currentVC = rootVC;
        }
        return currentVC;
    };

    K_CurrentVC = function(){
        return K_GetCurrentVCFromRootVc(K_Rootvc());
    };

})(exports);
  • 使用

使用之前要重新跑下程序

//记得自定义的一定要@import
cy# @import appConvince
{}
cy# K_APPID
@"riceFun.KTest"
cy# K_APPPATH
@"/var/containers/Bundle/Application/DC9FADE7-6224-46AB-B596-F2CF127C4BBC/KTest.app"