语言混合物,用来修改调试正运行在内存中的app的。
Cycript是什么,做什么用的?
- Cycript是Objective-C++、ES6(JavaScript)、Java等语法的混合物
- 可以用来
探索、修改、调试
正在运行的Mac\iOS APP - 官网: http://www.cycript.org/
文档: http://www.cycript.org/manual/
安装插件
- 在Cydia上安装Cycript和adv-cmds两个插件,前者可在iPhone上调试运行中的APP;后者可以列出系统当前的进程;
- 连接、登录到iPhone服务端;
adv-cmds插件使用(用于搜索iPhone进程)
- 连接登录到iPhone服务端,
-
ps –A
或ps aux
列出所有的进程
-
ps –A | grep 关键词
搜索关键词
Cycript语法使用
注意要调试的那个APP要保证打开,内存中运行,如果退到后台会很容易从内存中清除
> 开启Cycript监听(进入iPhone服务端操作)
cycript
cycript -p 进程ID
【不推荐,进程ID每次都会变】
cycript -p 进程名称
【推荐使用,进程名不会变】
> Cycript的语法
-
Ctrl + C
:取消输入 -
Ctrl + D
:退出Cycript监听 -
Command + R
:清屏 -
UIApp
:[UIApplication sharedApplication] -
var 变量名 = 变量值
:定义变量 -
#内存地址
:用内存地址获取对象 -
ObjectiveC.classes
:当前app已加载的所有OC类 -
*对象
:查看对象的所有成员变量 -
view.recursiveDescription().toString()
:递归打印view的所有子控件(跟LLDB一样的函数) -
choose(UIViewController)
:查看当前界面中,存在内中的UIViewController类型的对象 -
choose(UITableViewCell)
:筛选出UITableViewCell类型的对象
实战:定位登录方法
1、先从Mac端拷贝个MJ的cy封装文件到iPhone端,scp -P 10011 [文件] root@localhost:/usr/lib/cycript0.9/MJTool.cy
2、连接登录到iPhone端,cycript监听网易云音乐进程(注意保持网易云音乐app是开启状态)
3、导入封装文件,查看当前界面
- @import MJTool
- 调用MJFrontVc(),查看网易云音乐当前界面的控制器
4、打印控制器的所有方法
注意:方法里面传的是对象5、调用登录方法
控制器对象调用登录方法,手机上弹框提示:手机号不能为空!操控成功!!!
6、找到账号框和密码框
app账号框输入:6666
app密码框输入:8888
打印控制器的子view:找到6666和8888,即找到了账号框和密码框:
找到账号框和密码框验证:拿到账号框对象,账号框输入7777,app的输入框数字也变为7777,说明这个账号框是对的
7、用MJTool.cy看下该控制器的其他的东西
7.1 类方法:MJClassMethodNames(#0x129c57f60)
该控制器没类方法7.2 对象方法:MJInstanceMethodNames(#0x129c57f60)
对象方法8、提个需求:把『登录』按钮删掉
找到『登录』两个字:
上面已经遍历控制器的子view了,只要找到登录这两个字就行了,但是文字都是unicode,『登录』的unicode是什么呢?可借助python,新建个终端,python
, unicode('登录','UTF-8')
,即可得出『登录』的unicode :
command + F 搜索 \u767b\u5f55,找到对应的button:
执行删除操作:[#0x129c4c6c0 removeFromSuperview]
,app上的登录按钮不见了。
注意:我们只是删掉了内存中的登录按钮,关掉app再次启动,登录按钮依然在。
上面的这些,只是在内存中动态调试。如何永久的删掉登录呢,后面还要学很多东西
10、添加个红色的view,用到MJTool
cy# MJFrontVc()
#"<NMPhoneLoginViewController: 0x129c57f60>"
cy# var redV = [[UIView alloc] init]
#"<UIView: 0x129ba8010; frame = (0 0; 0 0); layer = <CALayer: 0x1294e6350>>"
cy# redV.backgroundColor = [UIColor redColor]
#"UIDeviceRGBColorSpace 1 0 0 1"
cy# redV.frame = MJRectMake(10,100,100,100)
{0:{0:10,1:100},1:{0:100,1:100}}
cy# [#0x129c57f60.view addSubview:redV]
cy#
11、MJTool工具中正则表达式使用——筛选
cy# MJFrontVc()
#"<NMPhoneLoginViewController: 0x129c57f60>"
// 筛选带有login的对象方法,注意是匹配大小写的
cy# MJInstanceMethodNames(#0x129c57f60,/login/)
[&"loginButtonClicked:",&"loginView"]
// 筛选以View结尾的对象方法,注意大小写
cy# MJInstanceMethodNames(#0x129c57f60,/View$/)
[&"loginView",&"loadView"]
12、实战:封装Cycript文件
本次用sublime封装好了后,拷贝到iPhone中,两种拷贝方式:
12.1、终端拷贝:scp -P 10011 ~/Desktop/test.cy root@localhost:/usr/lib/cycript0.9
12.2、利用iFunBox,直接拖拽到cycript0.9文件夹下。
注意,如果Cycript文件修改了,重新拷贝到cycript0.9文件夹后,需要1、control+d退出监视、2、退出app、3、重启操控的app,4、重新监视app喜马拉雅cycript -p ting
5、@import test
即可看到外界可用的内容。
12.3 两种写法的区别,获取一次和每次都重新获取的写法,比如:UIApp.keyWindow.rootViewController
a. 获取一次:
exports.rootVc = UIApp.keyWindow.rootViewController;
b.每次都重新获取,写成函数:
exports.rootVc = function() {
return UIApp.keyWindow.rootViewController;
};
12.4 进入喜马拉雅APP的本地沙盒看看
Cycript文件内容:
(function(exports) {
// JS的语法和OC的语法混在一起
exports.sum = function(a,b){
return a + b;
};
exports.minus = function(a,b){
return a - b;
};
exports.age = 18;
// appId是一成不变的,获取一次就行
exports.appId = [NSBundle mainBundle].bundleIdentifier;
// 根控制器是变化的,每次都应该重新获取,写成函数
exports.rootVc = function() {
return UIApp.keyWindow.rootViewController;
};
// 沙盒路径是固定的值,获取一次就行
exports.docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
})(exports);
服务器终端执行本地缓存路径结果:
cy# test.docPath
@"/var/mobile/Containers/Data/Application/5C9D8696-C8FF-4233-96AD-213F514BCCA3/Documents"
cy#
利用iFunBox进入沙盒,这样就可以查看到喜马拉雅的本地存储结构是怎么做的
:
- 在执行test.docPath能不能去掉test文件名——弄成全局
可以,写成全局的,如何写成全局的:
在cy文件中去掉exports,就是全局的了,无需用文件名来调用了。
弄成全局后,要注意2点:
- 导入test文件的时候不会提示文件中的全局,勿慌;
- cy文件多了以后,全局名可能会重复——解决办法:加前缀。
导入test后,写成全局的LFSum和LFDocPath没有提示了。
- 作者saurik也有个cy文件,放在如下路径,这是为了防止重名。我们也可以效仿,用反域名来设置文件夹层级。不过这样很麻烦,我们放在cycript0.9文件夹下就行了。
15、如果有东西创建失败,说明要导入某个库MJLoadFramework('XXX')
16、想知道控制器是如何划分结构的——使用MJTool.cy:
MJRootVc()
,MJChildVcs(#0x14801f600)
,或者一步到位MJChildVcs(MJRootVc())
17、想知道当前view是如何划分结构的——使用MJTool.cy:
18、想知道控制器有哪些对象方法——使用MJTool.cy:
MJInstanceMethodNames(#0x12324432)
MJInstanceMethodNames(#0x12324432,/click/)
// 筛选出带有click的
19、控制器有哪些成员变量——使用MJTool.cy:
MJIvarNames(#0x12324432)
MJIvarNames(#0x12324432,/click/)
// 筛选出带有click的
20、获取某个类的所有子类——使用MJTool.cy:
//当前app有哪些UIViewController的子类
MJSubclasses(UIViewController)
MJSubclasses("UIViewController",/NMR/)
//查看app有哪些自定义导航控制器
MJSubclasses(UINavigationController)
MJSubclasses("UINavigationController")
MJSubclasses("UINavigationController",/NMR/)
21、改微信钱包零钱
大致步骤:
- 连接登录iPhone服务端,打开微信,进入微信钱包页面,搜索进程
ps -A
,监视微信进程cycript -p WeChat
,导入工具@import MJTool
; -
MJFrontVc()
:当前控制器 -
MJVcSubviews(#0x13e90c200)
:当前控制器的所有子view -
command + F
搜索零钱的数字,确定是哪个对象 -
(#0x14065f880).text = '\xa5848,340.00'
,修改零钱 -
(#0x14065f880).backgroundColor = [UIColor redColor]
,修改背景 -
(#0x14065f880).frame = MJRectMake(0,85,320,13)
,修改宽高
到这里为止,都还只是借用cycript的封装,修改调试内存中的东西,还不能达到永久修改的目的。
总结
操作步骤:
1、连接登录iPhone端;
2、打开app,ps -A
列出iPhone所有进程,找到app进程名称;
3、监视进程cycript -p 进程名词
;
4、用Cycript(一般用封装好的cy工具,方便),对app进行增、删、改、查。
网友评论