6. Cycript

199 阅读2分钟

CycriptCydia的创始人Jay Freeman开发的可以查看和修改运行时App的内存信息的工具。它混合了OCJavaScript语法的解释器,所以我们可以在使用时混合使用两者的语言。 官网 (www.cycript.org/ ) 提供了一下Cycript的经典使用方法,如下图所示。

1. 安装Cycript

Cydia中搜索Cycript,并安装。

安装完成后,SSH连接手机,输入cycript命令,就能进入交互界面输入命令了。

2. 注入进程

使用ps -A命令查看所有进程,找到我们需要注入的进程。这里以爱思助手为例。 输入cycript -p + 进程名/进程id ,就可以对app进行调试了。下面一个弹窗为例:

cy# var alert = [[UIAlertView alloc] initWithTitle:@"hi" message:@"hello, world!" delegate:nil cancelButtonTitle:@"canel" otherButtonTitles:nil]
#"<UIAlertView: 0x13fcf6770; frame = (0 0; 0 0); layer = <CALayer: 0x283131260>>"
cy# [alert show]

3. 调试app

可以通过OC的语法直接查看app的一些信息。

cy# UIApp
#"<UIApplication: 0x11de03c90>"
cy# UIApp.delegate
#"<AsTools.AppDelegate: 0x281d7e8a0>"
cy# UIApp.keyWindow
#"<UIWindow: 0x11dd1c190; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x2830544b0>; layer = <UIWindowLayer: 0x283e68440>>"
cy# UIApp.keyWindow.rootViewController
#"<AsTools.NRViewController: 0x11dd03560>"
cy# UIApp.keyWindow.rootViewController.view
#"<RCTRootView: 0x11dd50390; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x283e6aaa0>>"

choose() 获取当前内存中某个类的所有实例对象

cy# choose(UILabel)
[#"<UILabel: 0x11fbc8c40; frame = (0 64; 375 24); text = '\xe9\xa6\x96\xe6\xac\xa1\xe5\x8f\x91\xe9\x80\x81\xe6\x88\x90\xe5\x8a\x9f {\"show\":1,\"showtim...'; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x281d305f0>>",#"<UILabel: 0x11de5b150; frame = (0 64; 375 12); text = '\xe6\x97\xa5\xe5\xbf\x97\xe6\xb5\x8b\xe8\xaf\x95'; hidden = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x281d58780>>"]

发现0x11fbc8c40是隐藏起来的,更改属性将他显示出来,并且更改一下字体颜色

cy# #0x11fbc8c40.hidden = false
false
cy# #0x11fbc8c40.textColor = [UIColor greenColor];
#"UIExtendedSRGBColorSpace 0 1 0 1"

cycript不支持中文显示,可以使用在线工具进行转换显示。

4.引用外部脚本

mjcript里面封装了一些实用的函数,方便我们在调试app的时候用到。下面介绍一下如何使用。

  • 首先下载到本地
  • 然后通过scp拷贝到手机上
    scp mjcript.cy root@192.168.9.53:/usr/lib/cycript0.9
  • 通过@import 引入mjcript
 @import mjcript

然后可以使用里面提供的方法了。

// 包名
MJAppId;

// bundle path
MJAppPath;

// document path
MJDocPath;

// caches path
MJCachesPath;

// 加载系统动态库(/System/Library/Frameworks/xxx.framework,/System/Library/Private/Frameworks/xxx.framework)
MJLoadFramework("BluetoothManager");

// keyWindow
MJKeyWin();

// 根控制器
MJRootVc();

// 找到显示在最前面的控制器
MJFrontVc();

// 递归打印UIViewController view的层级结构
MJVcSubviews(vc);

// 递归打印最上层UIViewController view的层级结构
MJFrontVcSubViews();

// 获取按钮绑定的所有TouchUpInside事件的方法名
MJBtnTouchUpEvent(btn);

// CG函数
MJPointMake(x, y);

MJSizeMake(w, h);

MJRectMake(x, y, w, h);

// 递归打印controller的层级结构
MJChildVcs(vc);

// 递归打印view的层级结构
MJSubviews(view);

// 判断是否为字符串 "str" @"str"
MJIsString(value);

// 判断是否为数组 []、@[]
MJIsArray(value);

// 判断是否为数字 666 @666
MJIsNumber(value);

// 打印所有的子类
MJSubclasses(className, reg);

// 打印所有的对象方法
MJInstanceMethods(className, reg);

// 打印所有的对象方法名字
MJInstanceMethodNames(className, reg);

// 打印所有的类方法
MJClassMethods(className, reg);

// 打印所有的类方法名字
MJClassMethodNames(className, reg);

// 打印所有的成员变量
MJIvars(obj, reg);

// 打印所有的成员变量名字
MJIvarNames(obj, reg);