Welcome to follow the official wechat account: FSA Full stack action 👋

A,Cycript

Cycript is a scripting language that combines OC and JS syntax interpreters (scripts can be written using OC and JS syntax). It is mainly used to inject runtime programs for debugging. After the program restarts, all changes made through Cycript are invalidated. There are no side effects to native programs and code.

Official website: www.cycript.org

Two, installation and simple use

Search Cycript in Cydia and find the installation.

Type cycript on an iOS device and the cy# prompt appears

lxf-iPad:~ root# cycript
cy#
Copy the code

This is a JS console, and the input is run by the JS kernel.

cy# var name = 'lxf'
"lxf"
cy# print(name)
lxf
Copy the code

Common Shortcut keys

shortcuts role
ctrl + c Cancels a command currently entered or interrupts execution
ctrl + d exitCycript
ctrl + l clearClear the screen

Use the -p parameter to inject the specified program, if your program is in progress.

Here’s a look at the sandbox path after you inject Twitter

lxf-iPad:~ root# cycript -p Twitter
cy# NSHomeDirectory(a)@"/var/mobile/Containers/Data/Application/2FA6975C-9DB0-4B08-9FE9-365473E86748"
cy#
Copy the code

Third, in actual combat

Goal: As shown above, let’s change linxunfeng.top to FullStackaction.com

To modify it, you must first find it, using the recursiveDescription function that recursively prints the hierarchy of any view

[[UIApp keyWindow] recursiveDescription].toString()
Copy the code

If we do not know the full function name, we can use the TAB key to list all matches

# cy# [[UIApp keyWindow] recursive

cy# [[UIApp keyWindow] recursive
recursiveDescription             recursivelyForceDisplayIfNeeded
Copy the code

Looking at the printout in the above image, which is annoying to anyone, you can use a simplified version of the _autolayoutTrace method

[[UIApp keyWindow] _autolayoutTrace].toString()
Copy the code

Compared to the above recursiveDescription, it will be much clearer

Scroll down to find the passage

\u2022T1ProfileHeaderViewContro... :0x1164bac50 UIView:0x1164bae30 | T1ProfileUserInfoViewCont... :0x117748050 | ProfileHeaderBio:0x116498070 | T1TranslateButton:0x116474cc0 | ProfileHeaderTranslatedBi... :0x11773ed70 | ProfileTranslationActivit... :0x11773f170 | UIImageView:0x11773f3f0 | ProfileHeaderLocation:0x11641f090 | UIButtonLabel:0x11641f3b0 | ProfileHeaderWebSite:0x113526840 | | UIImageView:0x1164e3b60 | | UIButtonLabel:0x11355bbe0'linxunfeng.top' | ProfileHeaderBirthday:0x11355bee0 | | UIButtonLabel:0x11355c200 | ProfileHeaderCreatedDate:0x11355c500 | | UIImageView:0x1164e4100 | | UIButtonLabel:0x11355c820'2017\u5e748\u6708 \u52a0\u5165' | TFNAttributedTextView:0x11641f6b0 | | T1AccessibilityProxyView:0x11641af00 T1ProfileFriendsFollowing... :0x1164dc870 | TFNSolidColorView:0x1164dca50 | T1FlexibleLayoutView:0x1135df410 | | TFNAttributedTextView:0x1135df810 | | | T1AccessibilityProxyView:0x1164e06a0 | | T1UserFacepileView:0x1164df730 | | TFNAttributedTextView:0x1164dfb50 | T1ProfileFriendsFollowingHighlightView:0x1164dff50Copy the code

For the record, Cycript is not very friendly to Chinese

You can copy the above output to some Unicode-to-Chinese tools and convert the output directly

• T1ProfileHeaderViewContro... :0x1164bac50 UIView:0x1164bae30 | T1ProfileUserInfoViewCont... :0x117748050 | ProfileHeaderBio:0x116498070 | T1TranslateButton:0x116474cc0 | ProfileHeaderTranslatedBi... :0x11773ed70 | ProfileTranslationActivit... :0x11773f170 | UIImageView:0x11773f3f0 | ProfileHeaderLocation:0x11641f090 | UIButtonLabel:0x11641f3b0 | ProfileHeaderWebSite:0x113526840 | | UIImageView:0x1164e3b60 | | UIButtonLabel:0x11355bbe0'linxunfeng.top' | ProfileHeaderBirthday:0x11355bee0 | | UIButtonLabel:0x11355c200 | ProfileHeaderCreatedDate:0x11355c500 | | UIImageView: 0 x1164e4100 | | UIButtonLabel: 0 x11355c820 'in August 2017 to join' | TFNAttributedTextView: 0 x11641f6b0 | | T1AccessibilityProxyView:0x11641af00 T1ProfileFriendsFollowing... :0x1164dc870 | TFNSolidColorView:0x1164dca50 | T1FlexibleLayoutView:0x1135df410 | | TFNAttributedTextView:0x1135df810 | | | T1AccessibilityProxyView:0x1164e06a0 | | T1UserFacepileView:0x1164df730 | | TFNAttributedTextView:0x1164dfb50 | T1ProfileFriendsFollowingHighlightView:0x1164dff50Copy the code

If the content is less, e.g

UIButtonLabel:0x11355c820'2017\u5e748\u6708 \u52a0\u5165'
Copy the code

You can use echo -e to convert output

Echo -e '2017\ U5E748 \ U6708 \ U52A0 \ U5165Copy the code

Now that we’ve found the destination control, it’s time to modify it

UIButtonLabel:0x11355bbe0'linxunfeng.top'
Copy the code

In Cycript, if we know the memory address of an object, we can retrieve it with the # operator.

But it’s of type UIButtonLabel, and we can look at its parent control

   |   ProfileHeaderWebSite:0x113526840
   |   |   UIImageView:0x1164e3b60
   |   |   UIButtonLabel:0x11355bbe0'linxunfeng.top'
Copy the code

Print ProfileHeaderWebSite: 0 x113526840 this object

cy# #0x113526840
#"
      
       ; layer = 
       
        >"
       
      
Copy the code

You can see it’s a UIButton, isn’t it clear how to change the title?

[#0x113526840 setTitle:@"fullstackaction.com" forState:UIControlStateNormal]
Copy the code

But there is no effect ~, ok, then change the setting of rich text try

var siteAttr = [[NSAttributedString alloc] initWithString:@"fullstackaction.com" attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:10].NSForegroundColorAttributeName: [UIColor blueColor]}];

[#0x113526840 setAttributedTitle:siteAttr forState:UIControlStateNormal]
Copy the code

Done 😃

Advanced usage

1.choose– Find objects

Usage: choose(class name)

Sometimes the above recursiveDescription and _autolayoutTrace outputs are too much for us, and we know the target object’s class name. We can use the choose function to retrieve all records that match the condition (current class and subclass). To quickly get the address of the object to operate the object

cy# choose(UILabel)
[#"
       
        ; layer = <_UILabelLayer: 0x2803585a0>>"
       .#"
       
        >",#"
        
         >",#"
         
          >",#"
          
           >",#"
           
            ; layer = <_UILabelLayer: 0x28035d9f0>>"]
           
          
         
        
       
Copy the code

2. Classification expansion

OC’s categories can also be used in Cycript to extend methods for classes such as

cy# @implementation NSString (LXF)
    + website { return "fullstackaction.com"; }
    @end
Copy the code
cy# [NSString website]
@"fullstackaction.com"
Copy the code

3. Encapsulate functions

In practice, we often encounter some deep level situations, if we rely on our own manual to find the loop, it will become very troublesome, such as the current top controller, we can use Cycript to write custom functions to solve this problem

cy# function topVc(vc) {
        if (vc.presentedViewController) {
              return _topVc(vc.presentedViewController);
        } else if ([vc isKindOfClass:[UITabBarController class]]) {
                return _topVc(vc.selectedViewController);
        } else if ([vc isKindOfClass:[UINavigationController class]]) {
                return _topVc(vc.visibleViewController);
        } else {
              var count = vc.childViewControllers.count;
              for (var i = count - 1; i >= 0; i--) {
                    var childVc = vc.childViewControllers[i];
                    if (childVc && childVc.view.window) {
                          vc = _topVc(childVc);
                          break; }}returnvc; }}Copy the code

Print the top controller

cy# topVc(UIApp.keyWindow.rootViewController)
#"<T1TabBarViewController: 0x107864270>"
Copy the code

Wouldn’t it be very troublesome to write it in the terminal every time? We can write this code to a.cy file

We can be in/usr/lib/cycript0.9 / com/saurik/substrate/find a called Ms. Cy file

(function(exports) {

exports.getImageByName = MSGetImageByName;
exports.findSymbol = MSFindSymbol;

exports.hookFunction = function(func, hook, old) {... };exports.hookMessage = function(isa, sel, imp, old) {
    ...
};

})(exports);
Copy the code

I’ll just refer to it and write one. Attached is the cy file wrapped by myself: github.com/LinXunFeng/…

After download, the LXF. Cy copied to/usr/lib/cycript0.9 / com/LXF/directory

Then execute in the CYcript environment:

cy# @import com.lxf.lxf; 0
Copy the code

Note: The 0 after the semicolon is used to hide the output of the script content after the script is imported

After the import, use lxf. function name ()

cy# lxf.topVc()
#"<T1TabBarViewController: 0x107864270>"
Copy the code

If you don’t remember the function name, use the TAB key

Cy# LXF.【 TAB 】 __defineGetter__ __lookupSetter__ appPath classMethods findVc isString keyWindow methods rootVc toLocaleString valueOf __defineSetter__ __proto__ cachesPathconstructor           hasOwnProperty        ivarNames             loadFramework         printIvars            subViews              toString
__lookupGetter__      appId                 classMethodNames      documentPath          isPrototypeOf         ivars                 methodNames           propertyIsEnumerable  subViewsSimple        topVc
cy# lxf.
Copy the code