美文网首页
17 - Cycript

17 - Cycript

作者: 卡布奇诺_95d2 | 来源:发表于2021-06-07 13:53 被阅读0次

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

    安装

    • 下载Cycript官方文档
    • 下载完成之后,为了方便使用,可以将其拷贝至/opt目录下。
    cp ./cycript_0.9.594 /opt/cycript_0.9.594
    
    • 配置环境变量,在~/.bash_profile或者~/.zshrc文件中添加以下配置
    #Cycript配置
    export CYCRIPT_PATH=/opt/cycript_0.9.594
    

    使用

    附加进程

    Monkey中集成了Cycript,使用MonkeyDev重签名应用,会自动注入libcycript.dylib相关文件。

    当设备启动注入了Cycript的目标应用,应用进程会调用Cycript的方法,打开端口供第三方监听,如下:

    CYListenServer(6666);
    

    当设备启用监听时,第三方可以通过端口附加进程,进入cy环境,从而查看当前进程中的内存数据。假设端口IP为:172.20.10.14,则终端附加方式如下:

    cycript -r 172.20.10.14:6666
    cy#
    

    注意:进程运行的设备和附加进程的终端必须在同一网络环境

    常用指令

    • 获取keyWindow
    cy# UIWindow.keyWindow()
    
    #"<iConsoleWindow: 0x14ea6fee0; baseClass = UIWindow; frame = (0 0; 375 812); gestureRecognizers = <NSArray: 0x282279260>; layer = <UIWindowLayer: 0x282db4080>>"
    
    • 获取UIApplication
    cy# UIApp
    
    #"<UIApplication: 0x14ea28e00>"
    
    • 定义变量并赋值
    cy# var keyWd = UIWindow.keyWindow()
    
    #"<iConsoleWindow: 0x14ea6fee0; baseClass = UIWindow; frame = (0 0; 375 812); gestureRecognizers = <NSArray: 0x282279260>; layer = <UIWindowLayer: 0x282db4080>>"
    
    cy# keyWd.rootViewController
    
    #"<MMUINavigationController: 0x14f11f800> ChildViewControllers:(\n    \"<WCAccountLoginFirstViewController: 0x14f0fa600>\"\n)"
    cy#
    

    注意:当程序的进程结束了,定义的所有变量也会释放掉。

    • 获取对象
     //通过(#对象地址)获取对象
    cy# #0x14f11f800
     
    #"<MMUINavigationController: 0x14f11f800> ChildViewControllers:(\n    \"<WCAccountLoginFirstViewController: 0x14f0fa600>\"\n)"
    
    //通过(*定义的变量)获取对象
    cy# *keyWd
    {isa:iConsoleWindow,_responderFlags:@error,_constraintsExceptingSubviewAutoresizingConstraints:null...
    
    • 查看当前视图结构
    cy# keyWd.recursiveDescription()
     
    @"<iConsoleWindow: 0x14ea6fee0; baseClass = UIWindow; frame = (0 0; 375 812); gestureRecognizers = <NSArray: 0x282279260>; layer = <UIWindowLayer: 0x282db4080>>\n   | <UITransitionView: 0x14ea65650; frame = (0 0; 375 812);...
    
    cy# keyWd.recursiveDescription().toString()
    
    `<iConsoleWindow: 0x14ea6fee0; baseClass = UIWindow; frame = (0 0; 375 812); gestureRecognizers = <NSArray: 0x282279260>; layer = <UIWindowLayer: 0x282db4080>>
       | <UITransitionView: 0x14ea65650; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x282db5460>>
       |    | <UIDropShadowView: 0x14ea74650; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x282db5580>>
       |    |    | <UILayoutContainerView: 0x14ea2e280; frame = (0 0; 375 812); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x28227a040>; layer = <CALayer: 0x282db47c0>>
       |    |    |    | <UINavigationTransitionView: 0x14ea724f0; frame = (0 0; 375 812); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x282db4800>>
    
    • 查询当前进程中该类型的对象
    cy# choose(UIButton)
    
    [#"<FixTitleColorButton: 0x14ef05d40; baseClass = UIButton; frame = (20 18; 157.5 47); clipsToBounds = YES; opaque = NO; autoresize = RM; layer = <CALayer: 0x282d3d200>>",#"<FixTitleColorButton: 0x14ea2cfb0; baseClass = UIButton; frame = (197.5 18; 157.5 47); clipsToBounds = YES; opaque = NO; autoresize = LM; layer = <CALayer: 0x282dead20>>"]
    
    • 修改内存中的数据
      修改当前应用图标的通知气泡数目为999,假设当前使用Monkey安装并运行微信(WeChat8.0.2.ipa)
    cy# [UIApp setApplicationBadgeString:@"999"]
    
    修改结果如下: IMG_0104.jpg
    • 修改控件属性

    假设当前处于微信的登陆界面,打印keyWindow下所有视图

    UIWindow.keyWindow().recursiveDescription().toString()
    

    从当前界面中可以看到,有个+86的view,因此可以直接在打印的所有视图中查找+86所在的控件

    <WCUITextField: 0x116387c00; baseClass = UITextField; frame = (20 0; 73 44); text = '+86'; opaque = NO; autoresize = W+H; tintColor = UIExtendedSRGBColorSpace 0.027451 0.756863 0.376471 1; gestureRecognizers = <NSArray: 0x2817946f0>; borderStyle = None; background = <_UITextFieldNoBackgroundProvider: 0x2819310a0: textfield=<WCUITextField 0x116387c00>>; layer = <CALayer: 0x281b76700>>
    

    修改WCUITextField文本框的text属性,即:修改该控件的显示,将+86修改成+95

    #0x116387c00.text = @"+95"
    

    扩展指令

    MonkeyDev对一些常用方法进行了封装,提供给开发者使用,封装方法的实现在Mokey项目的Config目录下,找到MDConfig.plist文件

    image.png
    • 查看所有视图
    cy# pviews()
    
    `<iConsoleWindow: 0x115c4f020; baseClass = UIWindow; frame = (0 0; 375 812); gestureRecognizers = <NSArray: 0x283ab8720>; layer = <UIWindowLayer: 0x283517b80>>
       | <UITransitionView: 0x115866000; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x283517da0>>
       |    | <UIDropShadowView: 0x115851d10; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x283517900>>
    

    pviews等价如下指令:

    cy# pviews
    
    function (){return UIApp.keyWindow.recursiveDescription().toString()}
    
    • 获取当前控制器
    cy# pvcs()
    
    "<MMUINavigationController 0x116068000>, state: appeared, view: <UILayoutContainerView 0x115876ee0>\n   | <WCAccountLoginFirstViewController 0x1160c2a00>, state: appeared, view: <UIView 0x1158941a0>"
    

    pvcs等价如下指令

    cy# pvcs
    
    function (){return UIWindow.keyWindow().rootViewController._printHierarchy().toString()}
    

    cy文件

    Cycript是一门脚本语言,它可以加载封装好的\*.cy文件,因此,我们可以将常用的Cycript功能封装至\*.cy文件,在调试的时候可以直接使用\*.cy文件中封装的指令。

    在以上的扩展示例中,MonkeyDev也对常用的指令进行了封装。接下来我们来尝试封装自己的\*.cy文件

    示例1

    • 创建test.cy文件
    • test.cy文件添加至MonkeyDemo项目中。
    • test.cy文件中先添加简单的方法
    sum = function(a,b){
       return a + b;
    }
    
    • MokeyDemo项目中,使用Copy Files添加test.cy,注意:test.cy是脚本文件,不是MachO,因此不需要勾选签名。
      image.png
    • 运行MokeyDemo项目
    • 在终端对MokeyDemo项目进行附加
    cycript -r 172.20.10.14:6666
    
    • 导入test.cy脚本
    @import test
    
    • 调用sum方法
    sum(10,20)
    
    30
    

    示例2

    • 创建test.cy文件
    • test.cy文件添加至MonkeyDemo项目中。
    • test.cy文件中先添加简单的方法
    (function(exports){
       APPID = [NSBundle mainBundle].bundleIdentifier,
       APPPATH = [NSBundle mainBundle].bundlePath,
       APPHOME = NSHomeDirectory(),
    
       rootVC = function(){
           return UIApp.keyWindow.rootViewController;
       };
    
       keyWindow = function(){
           return UIApp.keyWindow;
       };
    
       getCurrentVC = function(rootVC){
    
           var currentVC;
           if([rootVC presentedViewController]){
               rootVC = [rootVC presentedViewController];
           }
    
           if([rootVC isKindOfClass:[UITabBarController class]]){
               currentVC = getCurrentVC(rootVC.selectedViewController);
           }
           else if([rootVC isKindOfClass:[UINavigationController class]]){
               currentVC = getCurrentVC(rootVC.visibleViewController);
           }
           else{
               currentVC = rootVC;
           }
    
           return currentVC;
       };
    
       currentVC = function(){
           return getCurrentVC(rootVC());
       };
    
    })(exports);
    
    • MokeyDemo项目中,使用Copy Files添加test.cy,注意:test.cy是脚本文件,不是MachO,因此不需要勾选签名。
      image.png
    • 运行MokeyDemo项目
    • 在终端对MokeyDemo项目进行附加
    cycript -r 172.20.10.14:6666
    
    • 导入test.cy脚本
    @import test
    
    • 获取APPID
    APPID
    
    @"com.hq.MokeyDemo"
    
    • 获取APPPATH
    APPPATH
    
    @"/private/var/containers/Bundle/Application/D620C178-5030-48E4-9276-981150FF7299/MokeyDemo.app"
    
    • 获取APPHOME
    APPHOME
    
    @"/var/mobile/Containers/Data/Application/C2ED1E99-47C4-4C29-8AE6-9C5C136CEE04"
    
    • 调用currentVC方法
    currentVC()
    
    #"<WCAccountLoginFirstViewController: 0x14b0b4200>"
    

    总结

    • Cycipt是一种脚本语言,混合了多种语法(混合多种语法的解释器),所以可以兼容。

    • Cycipt可以附加到进程,用来动态调试。

    • 可以将常用的功能封装成\*.cy文件,当附加进程后,导致\*.cy文件,即可使用封装的功能。

    相关文章

      网友评论

          本文标题:17 - Cycript

          本文链接:https://www.haomeiwen.com/subject/mshgsltx.html