美文网首页
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