从那个夜晚我懂得了隐藏温暖——在凛冽的寒风中,身体中那点温暖节俭地用于此后多年的爱情和生活。我的亲人说我是个很冷的人,不是的,我把仅有的温暖全给了你们。
——刘亮程《寒风吹彻》
简介
Cycript allows developers to explore and modify running applications on either iOS or Mac OS X using a hybrid of Objective-C++ and JavaScript syntax through an interactive console that features syntax highlighting and tab completion.
(It also runs standalone on Android and Linux and provides access to Java, but without injection.)
Cycript
是由Cydia
创始人Saurik
推出的一款脚本语言,Cycript
混合了Objective-C
与javascript
语法的解释器,这意味着我们能够在一个命令中用Objective-C
或者javascript
,甚至两者兼用。- 它能够注入正在运行的进程,能够在运行时修改应用的很多东西。
了解更多:
Cycript安装
- 安装Cycript有两种方式(手机需越狱):
- 方式一:直接在
Cydia
搜索Cycript
安装,简单方便。 - 方式二:通过Linux包管理器安装:
- 首先在手机上
Cydia
搜索安装APT 0.6 Transitional
包管理工具。 - 使用
Terminal
(如果手机有安装)或者电脑SSH连接手机,通过包管理器安装apt-get install cycript
。
- 首先在手机上
- 终端输入
cycript
,出现cy#
提示符,说明已经成功启动了Cycript
(需要SSH连接手机)。 - 如果想要退出
Cycript
和断开远程登录:Control + D
快捷键可以退出Cycript
- 终端输入
logout
可以断开手机远程登录
Cycript基本用法
测试Cycript注入头条新闻
- 开始使用
Cycript
,注入一个正在运行(需要再前台)的程序。这里我们以今日头条为例。 - 首先使用电脑终端通过
SSH
连接到手机,不知道如何使用SSH
的请参考之前的文章,这里不再赘述。 - 获取今日头条app的进程ID,建议清空后台应用,只保留需要hook的App在前台即可。
News
即为今日头条进程名称
,如果想知道某个app在运行时候的进程名称,可以下载对应的应用安装包,解压缩找到Payload
目录下的xxx.app
,其中xxx
包名即是进程名称,如微信是WeChat
,网易云音乐是NeteaseMusic
。- 在运行的进程中查找过滤我们需要的进程名称,命名如下:
1 | ps -e | grep News |
- 成功之后,就可以看到今日头条应用进程的一些信息,如进程ID
9347
,进程的可执行文件路径等待。 - 拿到进程ID后,我们就可以注入住这个进程,从而对应用为所欲为了😈,如何注入进程,命令如下:
1 | cycript -p 9347 // 需要hook的程序打开到前台 |
- 此时,我们可以简单测下下是否hook成功:
1 | [[UIApplication sharedApplication] setStatusBarHidden:YES] // 隐藏状态栏 |
常用数据类型及类型判断
- 常用的数据类型(字符串、数组、字典、Bool, NSNumber)和我们在OC中使用的完全一样。
- 类型判断使用
instanceof
,如:
1 | cy |
字符串及数组截取
- 字符串及数组截取操作,分别使用
substr
和slice
。 - 下标从
x
开始截取y
个长度。
1 | cy |
创建及获取对象
- 注入程序后,我们可以根据需要创建需要用到的对象,或者根据内存地址获取到内存中的对象。
- 创建对象和OC语法差别不大。
- 根据内存地址获取对象,我们可以使用
#
或者使用Instance
。
1 | // 创建对象 |
获取对象信息
- 方法1: 简单基本获取方法。
- 直接在对象前面加个
*
- 直接在对象前面加个
1 | *controller() |
- 方法2:方法一无法获取,就使用方法2
1 | [i for (i in *UIApp)] |
- 方法3:建议方法三,方法三能获取到更多
1 | function tryPrintIvars(a){ var x={}; for(i in *a){ try{ x[i] = (*a)[i]; } catch(e){} } return x; } |
类与增加分类
- 类定义及使用
1 | @implementation MyClass : NSObject { |
- 增加分类
1 | // 定义 |
Block
1 | // 定义一个block |
查找内存中的类信息
- 使用
choose()
函数可以查找到内存中对应传递进去的类,如查找今日头条首页中的图片控件choose(UIImageView)
- 输入信息如下(数据太多删除一部分),此时我们就可以通过
UIImageView
控件的内存地址获取到实例对象,修改对象的各种信息等等。
1 | [ |
打印视图层次结构
- 如果我们想知道某个视图的层次结构信息,也可以不使用Reveal,使用下面指令查看整个层次的结构信息:
1 | UIApp.keyWindow.recursiveDescription().toString() |
获取某个类的所有内容
- 我们可以打印出某个类的所有内容信息:
- 定义执行下面的函数
- 定义后就可以获取指定类的信息,调用
printMethods(className, isa)
1 | function printMethods(className, isa) { |
获取当前控制器
- 可以直接打印可见控制器,如果获取不到可用下面的方法
1 | UIApp.keyWindow.rootViewController.visibleViewController |
- 也打印出当前控制器名称及内存地址
- 定义执行下面的函数
- 调用函数
var vc = currentVC()
,如输出信息#"<TTArticleTabBarController: 0x17a5bc00>"
1 | function currentVC() { |
加载系统动态库
- 定义执行下面获取系统动态库的函数
- 定义好后就可以调用函数如
loadFramework("UIKit")
,传递想要加载的框架名称加载对应的框架。
1 | function loadFramework(fw) { |
NSLog打印函数
1 | NSLog_ = dlsym(RTLD_DEFAULT, "NSLog") |
CG…Make函数
1 | cy |
使用Cycript一窥微信
- 这里综合上面的知识练练手:
- 修改微信登录界面按钮文字及背景颜色
- 在登录界面弹出一个Alert弹框
- 修改微信登录界面背景图片
注入进程
- 获取微信的进程ID,使用Cycript注入微信进程。
1 | ps -e | grep WeChat |
层次结构
- 查看微信登录界面的层次结构
1 | UIApp.keyWindow.recursiveDescription().toString() |
- 输出的层次结构信息:
1 | `<iConsoleWindow: 0x14f6e420; baseClass = UIWindow; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x14f6dea0>; layer = <UIWindowLayer: 0x14f6e7a0>> |
Command + F
搜索UIButton
,可以找到有两个UIButton对象,并且text属性是显示的Unicode编码(中文在里面显示的就是Unicode字符编码)。我们可以在在线的Unicode和中文互转网站转换一下,如这个网站,可以看到对应的刚好就是界面上显示的登录
和注册
。- 我们就可以拿到每一个的对应的按钮对象,改变按钮显示文字:
- 如我拿到的登录按钮内存地址:
0x19c87130
- 注册按钮内存地址:
0x19cd4470
- 注意设置中文时需要将中文转为Unicode编码。
- 如我拿到的登录按钮内存地址:
1 |
修改按钮文字背景颜色:
- 我们搜索上一步获取到的层次结构信息,可以找到叫
UIButtonLabel
的对象,修改按钮文字背景就是修改UIButtonLabel
的背景颜色 - 只需要根据
UIButtonLabel
地址修改即可
1 |
弹出一个Alert
弹框
- 如果对方法签名不熟悉,可以在
Xcode
中打出来后拷贝进终端 - 尽量不要有中文和表情
- 也可以在系统桌面弹出,需要注入到系统的桌面进程
SBHomeScreenWindow
1 | var alert = [[UIAlertView alloc] initWithTitle:@"Hack You" message:@"I've hacked you" delegate:nil cancelButtonTitle:@"No pay" otherButtonTitles:@"Pay", nil]; |
修改微信登录界面背景图片
- 如果我们想替换微信的某个图片,这里以登录界面背景为例子,只需要将我们自己的图片放在微信的某个目录下,如
Document
下,然后修改背景图片控件的图片即可。 将图片放入对应的文档目录下:
- 可以直接使用工具
iMazing
,也可以使用scp
命令远程传输(越狱第一篇文章SS部分),看个人爱好。
- 可以直接使用工具
获取微信的文档目录路径地址:
1 | [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0] |
- 综合效果图(没修改文字背景颜色)
- 其他好玩的大家可以自行测试:
1 | // 截屏 |
福利
- 如果感觉上面一些函数比较复杂,不想每次都去敲一次,那么福利来了,
MJRefresh
作者将一些Cycript实现的一些实用函数封装成一个脚本放在GitHub
上面,基本上囊括了我们上面的那些,还有一些其他的比较常用的函数。 - 需要的小伙伴们可以直接去在这里下载,至于如何使用大家看文档就可以了,比较简单,都是中文就没必要我在转述一遍了。
防
- 通过一系列文章的介绍及实战,可以看到我们的App面临的安全问题是多么的可怕,也意识到保护app数据的重要性。
- 但是既然知道了这么多可能导致不安全的点,就要做好相应的防,保护重要数据不被攻击者使用
Cycript
或者Runtime
修改,这里有一篇文章对如何防范介绍的很详细,大家可以参考下。