Cycript
是由Cydia
创始人Saurik
推出的一款脚本语言,Cycript
混合了OC
、JavaScript
语法的解释器,这意味着我们能够在一个命令中使用OC
或者JavaScript
,甚至两者并用。它能够挂钩正在运行的进程,能够在运行时修改很多东西。
安装
下载后使用
Cycript
可执行文件
- 可以存放在
/opt/cycript_0.9.594
,opt
目录有可选的意思为了方便使用,可以在
~/.bash_profile
、~/.zshrc
中配置环境变量
cycript
可以使用官方的,也可以使用MonkeyDev
中集成的详情可查看:官方文档
基本使用
cy
文件
Cycript
是一门脚本语言,它可以加载封装好的.cy
文件- 将常用的
Cycript
功能封装到.cy
文件中,便于调试非越狱设备,导入
.cy
文件
- 利用
MonkeyDev
工具导入.cy
文件MonkeyDev
本身集成了Cycript
。我们只需要将.cy
文件,通过Xcode
导入Framworks
目录即可进入
Cycript
环境
cycript
-------------------------
cy#
使用
control + d
退出环境
MonkeyDev
中集成了Cycript
,使用MonkeyDev
重签名应用,会自动注入libcycript.dylib
相关文件
当
Cycript
注入到目标应用,应用进程就会调用Cycript
的方法,开启相应的端口,以供第三方监听第三方可通过端口链接进程,进入
cy
环境,HOOK
当前进程中的内存数据案例1:
附加进程
使用
MonkeyDev
安装并运行wx8.0.2.ipa
设备和
Mac
在同一网络环境,来到终端,使用设备ip + 端口
附加进程
cycript -r 10.165.44.19:6666
-------------------------
cy#
- 端口号默认为
6666
案例2:
常用命令
获取
keyWindow
UIWindow.keyWindow()
-------------------------
#"<iConsoleWindow: 0x125f560b0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x283f09680>; layer = <UIWindowLayer: 0x283179fc0>>"
获取
UIApplication
单例对象
UIApp
-------------------------
#"<UIApplication: 0x14aa16c80>"
定义变量并赋值
var keyWd = UIWindow.keyWindow()
-------------------------
#"<iConsoleWindow: 0x125f560b0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x283f09680>; layer = <UIWindowLayer: 0x283179fc0>>"
keyWd.rootViewController
-------------------------
#"<MMUINavigationController: 0x1270e9200> ChildViewControllers:(\n \"<WCAccountLoginFirstViewController: 0x1270d7600>\"\n)"
- 当程序的进程结束,定义的所有变量会一起释放
#对象地址
:拿到该对象,可用于调用方法
#0x1270e9200
-------------------------
#"<MMUINavigationController: 0x1270e9200> ChildViewControllers:(\n \"<WCAccountLoginFirstViewController: 0x1270d7600>\"\n)"
*对象
:可以取出对象的成员变量
*keyWd
-------------------------
{isa:iConsoleWindow,_responderFlags:@error,_constraintsExceptingSubviewAutoresizingConstraints:null,...
查看视图结构
keyWd.recursiveDescription()
-------------------------
@"<iConsoleWindow: 0x125f560b0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x283f09680>; layer = <UIWindowLayer: 0x283179fc0>>\n | <UITransitionView: 0x125f51960; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x28317a500>>\n...
格式化打印,遇
\n
换行
keyWd.recursiveDescription().toString()
-------------------------
`<iConsoleWindow: 0x125f560b0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x283f09680>; layer = <UIWindowLayer: 0x283179fc0>>
| <UITransitionView: 0x125f51960; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x28317a500>>
| | <UIDropShadowView: 0x125f59770; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x28317a680>>
| | | <UILayoutContainerView: 0x125e71790; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x283f0ff90>; layer = <CALayer: 0x283140140>>
| | | | <UINavigationTransitionView: 0x125e7a190; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x283140360>>
| | | | | <UIViewControllerWrapperView: 0x125f37540; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x28315abc0>>
...
查询当前进程中该类型的对象
choose (UIButton)
-------------------------
[#"<FixTitleColorButton: 0x125e2b280; baseClass = UIButton; frame = (20 18; 177 47); clipsToBounds = YES; opaque = NO; autoresize = RM; layer = <CALayer: 0x2831463c0>>",#"<FixTitleColorButton: 0x125e55b20; baseClass = UIButton; frame = (217 18; 177 47); clipsToBounds = YES; opaque = NO; autoresize = LM; layer = <CALayer: 0x283138820>>",...
脚本的封装和使用
一些常用的
Cycript
功能,我们会将其进行封装,做成脚本文件,方便调式案例1
将自动链接功能封装脚本
创建
cyShell
目录在
cyShell
目录下,创建cyConnect.sh
脚本打开
cyConnect.sh
脚本,写入以下代码:
cycript -r 10.165.44.19:6666
在终端为脚本增加可执行权限
chmod +x cyConnect.sh
案例2
配置环境变量
终端使用
vim ~/.zshrc
定义
CyShell
变量
export CyShell=/Users/zang/Zang/Tools/cyShell
加入到
PATH
中
export PATH=$CyShell:$THEOS/bin:$MonkeyDevPath/bin:$PATH
打开终端,在任意目录下,都可使用
cyConnect.sh
cyConnect.sh
-------------------------
cy#
高级用法
案例1:
修改应用图标的红点数
使用
MonkeyDev
安装并运行wx8.0.2.ipa
使用
cyConnect.sh
附加进程修改
BadgeString
[UIApp setApplicationBadgeString: @"999"]
- 修改当前内存中的数据,应用重复挂起唤醒,数据会被刷新
案例2:
修改控件的属性
延用上述案例,进入登录页
打印
keyWindow
下所有视图
UIWindow.keyWindow().recursiveDescription().toString()
在终端使用
command + f
,搜索+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
属性
#0x116387c00.text = @"+95"
Cycript
对一些常用方法进行了封装查看所有视图
pviews()
pviews
方法的代码实现
pviews
-------------------------
function (){return UIApp.keyWindow.recursiveDescription().toString()}
拿到当前控制器
pvcs()
pvcs
方法的代码实现
pvcs
-------------------------
function (){return UIWindow.keyWindow().rootViewController._printHierarchy().toString()}
上述方法,由
MonkeyDev
封装,提供给开发者使用找到封装的方法
打开
Mokey
项目,在Config
目录下,找到MDConfig.plist
文件
MonkeyDev
封装的.cy
文件,里面存储了它提供的常用方法使用
Cycript
找到指定控制器的某个控件,过程比较繁琐。更好的方式:在非越狱设备上,使用应用重签名,通过Debug View Hierarchy
快速定位控件,找到对应的地址,然后使用Cycript
对其进行修改
cy文件的封装
案例1:
封装自定义
cy
文件在
MokeyDemo
项目中,创建test.cy
文件将
test.cy
文件拖入项目打开
test.cy
文件,写入以下代码:
sum = function(a,b){
return a + b;
}
在
MokeyDemo
项目中,使用Copy Files
添加test.cy
test.cy
是脚本文件,不是MachO
,不需要勾选签名重新运行项目
使用
cyConnect.sh
附加进程导入脚本
@import test
-------------------------
{}
调用
sum
方法
sum(10,20)
-------------------------
30
案例2:
实现获取当前控制器的代码封装
打开
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);
> 重新运行项目
> 使用`cyConnect.sh`附加进程
> 导入脚本
>
@import test
{}
> 获取`APPID`
>
APPID
@”com.lg.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
文件