iOS逆向学习之三(Cycript)

什么是Cycript?

  • Cycript是Objective-C++、ES6(JavaScript)、Java等语法的混合物.
  • 可以点击官网来查看,可以点击Cycript文档来查看Cycript的使用方式。
  • 需要在iPhone上通过Cydia安装Cycript,才能在iPhone上来调试运行中的App。

注意:App必须在启动时才能进行调试

ps命令

在介绍Cycript使用之前,先来学习一个ps指令,ps命令是process status的缩写,使用ps命令可以列出系统当前的进程

  • 首先需要在iPhone上安装adv-cmds插件
  • 使用如下命令可以列出iPhone正在运行的所有进程
ps -A
ps aux
  • 如果进程较多,想要根据关键字搜索的话,可以使用grep
ps -A | grep '关键词'
  677 ??         0:00.04 /System/Library/CoreServices/CacheDeleteSystemFiles
  679 ??         0:00.09 /System/Library/CoreServices/CacheDeleteITunesStore
  681 ??         0:00.41 /Applications/MobileSafari.app/webbookmarksd
  683 ??         0:00.27 /System/Library/CoreServices/CacheDeleteAppContainerCaches
  700 ??         0:00.59 /Applications/SiriViewService.app/SiriViewService
  707 ??         0:00.08 /System/Library/PrivateFrameworks/CoreFollowUp.framework/followupd
  724 ??         0:01.58 /usr/libexec/ptpd -t usb
  729 ??         0:00.09 /usr/libexec/companion_proxy
  810 ??         0:00.31 /System/Library/PrivateFrameworks/SafariShared.framework/XPCServices/com.apple.Safari.History.xpc/com.apple.Safar
  845 ??         0:00.23 sshd: root@ttys000
  849 ??         0:00.85 /System/Library/PrivateFrameworks/AssistantServices.framework/assistant_service
  852 ??         0:07.95 /var/mobile/Containers/Bundle/Application/5617B333-7DC7-48D1-B7D0-A4EC07B8EE93/Aweme.app/Aweme
  854 ??         0:00.05 /System/Library/Frameworks/UIKit.framework/Support/pasteboardd
  857 ??         0:00.18 /System/Library/PrivateFrameworks/SyncedDefaults.framework/Support/syncdefaultsd
  860 ??         0:00.20 /usr/libexec/rtcreportingd
  847 ttys000    0:00.04 -sh
  863 ttys000    0:00.01 ps -A
508SC:~ root#

如上所示,当前最左侧的数字代表进程的id,右侧.app结尾表示进程的可执行文件,最右侧表示进程的名称,例如图中的Aweme代表抖音的进程

如何使用Cycript?

通过ps -A指令,我们可以看到iPhone中运行的所有进程的信息。使用如下指令,可以对指定的进程进行调试。

cycript -p 进程id或进程名称

终端执行指令后效果如下:

  849 ??         0:00.85 /System/Library/PrivateFrameworks/AssistantServices.framework/assistant_service
  852 ??         0:07.95 /var/mobile/Containers/Bundle/Application/5617B333-7DC7-48D1-B7D0-A4EC07B8EE93/Aweme.app/Aweme
  854 ??         0:00.05 /System/Library/Frameworks/UIKit.framework/Support/pasteboardd
  857 ??         0:00.18 /System/Library/PrivateFrameworks/SyncedDefaults.framework/Support/syncdefaultsd
  860 ??         0:00.20 /usr/libexec/rtcreportingd
  847 ttys000    0:00.04 -sh
  863 ttys000    0:00.01 ps -A
508SC:~ root# cycript -p Aweme
cy#
508SC:~ root# cycript -p 852
cy#

cycript还可以进行如下操作

#退出
control + D
#取消输入
control + C
#清屏
command + R

Cycript常用语法

UIApp

由于cycript支持OC、JS等语法,所以我们可以直接使用OC语法来对App进行调试

  • 使用[UIApplication sharedApplication]可以打印出当前抖音App中的UIApplication的名称和内存地址信息
508SC:~ root# cycript -p Aweme
cy#
508SC:~ root# cycript -p 852
cy# [UIApplication sharedApplication]
#""
cy#
  • 在Cycript中,内置了UIApp指令,就等价于[UIApplication sharedApplication]
508SC:~ root# cycript -p Aweme
cy#
508SC:~ root# cycript -p 852
cy# [UIApplication sharedApplication]
#""
cy# UIApp
#""
cy#

定义变量

在Cycript中,定义变量通过var来定义,不支持OC定义变量的方式

var app = UIApp

使用内存地址获取对象

在Cycript中可以使用#地址信息来获取对象信息

cy# UIApp
#""
cy# UIApp.keyWindow.rootViewController
#""
cy# #0x14e230200.view
#">"
cy#

ObjectiveC.classes

使用ObjectiveC.classes来显示当前App已加载的所有OC类

image

使用(*对象),来获取对象的所有成员变量

image

递归打印View的所有子控件

image

使用如下指令筛选出某种类型的对象

#筛选出抖音中所有UIViewController类型的对象
choose(UIViewController)
#筛选出抖音中所有UITableViewCell类型的对象
choose(UITableViewCell)

Cycript工具库的使用

  • 首先下载对应的工具库https://github.com/CoderMJLee/mjcript

mjcript就是将一些常用的Cycript方法进行了封装,具体可参考源码

  • 找到其中的mjcript.cy文件,保存到本地目录,同时使用如下命令将mjcript.cy拷贝到iPhone的/usr/lib/cycript0.9目录下
#将本机的mjcript.cy拷贝到iPhone的/usr/lib/cycript0.9目录下
scp -P 10088 ~/Desktop/Cycript/mjcript.cy root@localhost:/usr/lib/cycript0.9

注意:此处的-P一定要大写

  • 也可以通过mac上的iFunBox直接将mjcript.cy拖拽到iPhone的/usr/lib/cycript0.9目录下
  • 在终端使用Cycript监听App,同时使用@import导入mjcript
#监听抖音App
cycript -p Aweme
#导入mjcript库
@import mjcript
  • 然后就可以使用mjcript中封装好的一些函数了,具体使用如下
//获取App的bundleId
MJAppId

//获取App可执行文件路径
MJAppPath

//获取keyWindow
MJKeyWin()

//获取根控制器
MJRootVc()

//找到显示在最前面的控制器
MJFrontVc()

//递归打印UIViewController view的层级结构
MJVcSubviews(MJFrontVc())

//打印所有的对象方法,需要传入参数,以抖音App首页为例
MJInstanceMethods(MJFrontVc()) 或者  
MJInstanceMethods(#0x15f2d3600)

//打印所有对象方法的名字
MJInstanceMethodNames(MJFrontVc())

//打印所有的类方法
MJClassMethods(MJFrontVc())

//打印所有的类方法名字
MJClassMethodNames(MJFrontVc())

//打印所有的成员变量
MJIvars(MJFrontVc())

//打印所有的成员变量名字
MJIvarNames(MJFrontVc())

//由于Cycript不支持OC中的CGRectMake等函数的使用,所以mjcript提供了CG函数的封装
MJPointMake(x,y)
MJSizeMake(w,h)
MJRectMake(x,y,w,h)

更多的方法使用,请参考mjcript.cy的源码。

小试牛刀

既然我们知道了这么多关于cycript的用法,那么就可以尝试对现有的项目进行调试。

微信

尝试修改微信钱包的余额,核心就是获取金额所在的UILabel

  • 首先在iPhone上打开微信,进入到钱包页面
  • 在终端使用如下指令连接iPhone,同时监听微信进程
//第一步:映射mac 10088端口到iPhone的22端口
./itnl --lport 22 --lport 10088

//第二步:通过连接10088端口远程登录到iPhone
ssh root@localhost -p 10088

//第三步:监听微信进程
cycript -p WeChat
  • 现在,我们可以使用终端来对微信的App进行调试
//第一步:获取当前钱包页面的ViewController
MJFrontVc()

//第二步:打印钱包页面中所有的subViews
MJSubviews(MJFrontVc().view)

//第三步:根据当前钱包页面显示的余额找到对应的UILabel(找到对应的内存地址即可)
var moneyLabel = #0x12e7b35e0

//第四步:拿到了目标Label,就可以为所欲为了
moneyLabel.text = "¥10000000"
moneyLabel.textColor = [UIColor redColor]
moneyLabel.frame = MJRectMake(20, 100, 100, 30)
......

字符串查找

由于在终端打印出来的UILabel里面显示的中文都是经过Unicode编码的,所以如果我们需要根据当前页面上的中文字符找到其所对应的编码后的字符,可以借助Python来进行中文和编码后的转换。

  • 第一种格式
image
  • 第二种格式
image

UI调试神器-Reveal

Reveal是iOS开发中调试UI界面的神器,可以点击官网查看Reveal介绍和使用方式,可以点击下载Reveal

Reveal4以上的版本支持USB链接调试,调试速度快。Reveal4以下版本只支持wifi调试,速度慢

Reveal调试环境配置

  • 首先需要在iPhone上使用Cydia安装Reveal Loader,添加软件源http://apt.so/codermjlee,并且下载Reveal Loader
  • 安装完Reveal Loader后,打开【设置】,下拉找到Reveal选项,点击进入,选择【Enable Applications】,打开你想要调试的App
  • 找到Mac的Reveal中的RevealServer文件,覆盖iPhone上的/Library/RHRevealLoader/RevealServer文件,具体路径如下:
image

如果不是下载的此软件源的Reveal Loader,可以通过查看Cydia中已安装的Reveal Loader,在Description中会告诉你RevealServer.framework所在具体位置,将Mac上的RevealServer覆盖此位置的RevealServer文件即可。

  • 重启SpringBoard或者重启手机,可以在iPhone上输入终端命令
//重启SpringBoard
killall SpringBoard

//重启手机
reboot
  • 打开Reveal,同时打开iPhone上的任意App,这时在Reveal上就会显示出你要调试的应用,点击应用图标即可查看App的UI结构
image

你可能感兴趣的:(iOS逆向学习之三(Cycript))