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

#"<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文件,即可使用封装的功能。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容