17 - Cycript

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()

#"; layer = >"
  • 获取UIApplication
cy# UIApp

#""
  • 定义变量并赋值
cy# var keyWd = UIWindow.keyWindow()

#"; layer = >"

cy# keyWd.rootViewController

#" ChildViewControllers:(\n    \"\"\n)"
cy#

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

  • 获取对象
 //通过(#对象地址)获取对象
cy# #0x14f11f800
 
#" ChildViewControllers:(\n    \"\"\n)"

//通过(*定义的变量)获取对象
cy# *keyWd
{isa:iConsoleWindow,_responderFlags:@error,_constraintsExceptingSubviewAutoresizingConstraints:null...
  • 查看当前视图结构
cy# keyWd.recursiveDescription()
 
@"; layer = >\n   | ; layer = >
   | >
   |    | >
   |    |    | ; layer = >
   |    |    |    | >
  • 查询当前进程中该类型的对象
cy# choose(UIButton)

[#">",#">"]
  • 修改内存中的数据
    修改当前应用图标的通知气泡数目为999,假设当前使用Monkey安装并运行微信(WeChat8.0.2.ipa)
cy# [UIApp setApplicationBadgeString:@"999"]

修改结果如下:
IMG_0104.jpg
  • 修改控件属性

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

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

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

; borderStyle = None; background = <_UITextFieldNoBackgroundProvider: 0x2819310a0: textfield=>; layer = >

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

#0x116387c00.text = @"+95"

扩展指令

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

image.png

  • 查看所有视图
cy# pviews()

`; layer = >
   | >
   |    | >

pviews等价如下指令:

cy# pviews

function (){return UIApp.keyWindow.recursiveDescription().toString()}
  • 获取当前控制器
cy# pvcs()

", state: appeared, view: \n   | , state: appeared, view: "

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()

#""

总结

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

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

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

你可能感兴趣的:(17 - Cycript)