Cycript is a scripting language developed by Saurik, the founder of Cydia. Cycript mixes OC with the interpreter for JavaScript syntax, which means that we can use OC or JavaScript, or both, in a single command. It can hook up to running processes and modify a lot of things at run time.

Refer to www.jianshu.com/p/de0beb21f…

The installation

Download the SDK from the official website to the local PC and configure it in the local shell for global use. Everyone uses a different shell. Generally, bash is used. I use ZSH and skip the steps. Installation success mark

$ cycript
cy#
Copy the code

Simple to use

LLDB requires a program to be stopped to debug, while CYcript can debug dynamically. The steps above already installed the Cycrip plugin on the local computer, so how do you install the Cycript plugin on the phone?

  • 1. If it’s a jailbroken phone, you can install the Cycript plugin directly on the jailbroken phone
  • 2. If you do not have a jailbroken phone, you can use MonkeyApp to re-sign the ipA package of wechat

I chose the second option here.

The connection

  • 1. Check out the Monkey connection port, which can be customized, of course.
  • 2. Connect your PC and mobile phone to the same LAN and check the current IP address of the network
  • 3. Connect the PC to the mobile phone. 10.89.3.114 is the IP address and port number
$cycript-r 10.89.3.114:6666The # symbol appears to indicate that the connection is successful, and you can debug happily
cy#
Copy the code

Exit cycript debug control + d; *** _syscall(connect(socket_, info->ai_addr, info->ai_addrlen)): / console. CPP (306):CYSocketRemote [errno=60], try a different wifi, change the phone (change IP). If that still doesn’t work, use your phone to turn your computer on. It’s an IP or port or Wi-Fi problem.

Note: Do not back your app to the background while debugging as this will cause the Cycript connection to fail

Cycript common commands

Using the example

// get keyWindow() cy# UIWindow.keyWindow()
#"
      
       ; layer = 
       
        >"
       
      

cy# [UIApplication sharedApplication]
#"<UIApplication: 0x10aa17610>"// The built-in cy command cy# UIApp
#"<UIApplication: 0x10aa17610>"// create a custom variable cy# var keyWd = UIWindow.keyWindow()
#"
      
       ; layer = 
       
        >"
       
      
cy# keyWd.rootViewController
#"<MMUINavigationController: 0x10b108600>"

//# pointer print
cy# #0x10b108600
#"<MMUINavigationController: 0x10b108600>"//* Prints the object variable attribute cy# *keyWd{isa:iConsoleWindow,_hasOverrideClient:0,_hasOverrideHost:0,_hasInputAssistantItem:0,_constraintsExceptingSubviewAutores izingConstraints:null,_cachedTraitCollection:null,_animationInfo:null,_layer:#"
      
       ",_layerRetained:#"
       
        ",_gestureRecognizers:@[#"<_UISystemGestureGateGestureRecognizer: 0x2827160d0; state = Possible; delaysTouchesEnded = NO;  view = 
        
         >",#"<_UISystemGestureGateGestureRecognizer: 0x2827161c0; state = Possible; delaysTouchesBegan = YES;  view = 
         
          >"],_window:null,_subviewCache:@[#"
          
           >"],_templateLayoutView:null,_pseudo_id:34,_viewDelegate:null,_backgroundColorSystemColorName:@"clearColor", _countOfMotionEffectsInSubtree:0,_unsatisfiableConstraintsLoggingSuspensionCount:0,_countOfTraitChangeRespondersInDirect Subtree:2,_cachedScreenScale:0,_viewFlags:@error,_layoutSubviewsCount:0,_imminentLayoutSubviewsCount:0,_retainCount:14,_ draggingSourceDelegate
          
         
        
       
      // Choose () gets all the objects cy of some type in the view# choose(UIButton)
[#"
      
       >",#"
       
        >",#"
        
       
      
Copy the code

Print view hierarchy

//recursiveDescription().toString() prints the view hierarchy 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>> ...Copy the code

The print view hierarchy method can be used to find a particular view

Automatic script connection

In the example above we typed $cycript -r 10.89.3.114:6666 for each connection, but we could script the connection automatically;

  • 1. Find a less modified location and create a script folder and cy script file
 $ cd/Users/ XXX // create a new script folder $mkdir RFShell // create a cy script file and edit $vim cylogin. shCopy the code

  • 2. Add the execute permission to the script file
chmod 777 cyLogin.sh
Copy the code
  • 3. Global configuration script
vi ~/.zshrc
Copy the code

  • 4. Test
$ sh cyLogin.sh
cy#
Copy the code

Cycript practice

// connect to cycript sh cylogin. sh cy# UIApp
#"<UIApplication: 0x12fe15150>"
cy# [UIApp setStatusBarHidden:YES]
Copy the code

cy# [UIApp setStatusBarHidden:NO]
Copy the code

cy# [UIApp setApplicationIconBageNumber:998]
Copy the code

Complex data modification

To find the object

cy# choose(UITableViewLabel)
Copy the code

#"<UITableViewLabel: 0x12fe95a10; Frame = (224.5 8; 65.5, 27.5); text = '+1876'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x2820a3e80>>"

Modify the object

cy# #0x12fe95a10.text = ""
Copy the code

Advanced use of cycript

Cy file

  • Cycript is a scripting language that loads packaged.cy files
  • By encapsulating common Cycript functionality into a.cy file, MonkeyDev itself integrates several.cy files on the network, so we can call them

Using the example

  • APPID
cy# APPID
@"riceFun.KTest"
Copy the code
  • Pactions Print object actions
cy# pactions(#0x131216a30)
"<WCAccountMainLoginViewController: 0x13001ea00> onSwitch"
Copy the code
  • The rp response chain
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>`Copy the code

Encapsulate your.cy file

  • Create a.cy File xcode-file-new-empty

  • Copy File to project

  • Edit the.cy file

    The following is the content of my CY file for your reference

//IIFE anonymous function self-executing expression (function(exports){K_APPID = [NSBundle mainBundle]. BundleIdentifier, K_APPPATH = [NSBundle mainBundle]. BundlePath, // if there are changes, usefunctionTo define!!!!! 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);
Copy the code
  • use

Run the program again before using it

// Remember to customize @import cy# @import appConvince
{}
cy# K_APPID
@"riceFun.KTest"
cy# K_APPPATH
@"/var/containers/Bundle/Application/DC9FADE7-6224-46AB-B596-F2CF127C4BBC/KTest.app"
Copy the code