iOS逆向实战--025:Cycript

Cycript是由Cydia创始人Saurik推出的一款脚本语言,Cycript混合了OCJavaScript语法的解释器,这意味着我们能够在一个命令中使用OC或者JavaScript,甚至两者并用。它能够挂钩正在运行的进程,能够在运行时修改很多东西。

安装

下载后使用Cycript可执行文件

  • 可以存放在/opt/cycript_0.9.594opt目录有可选的意思

为了方便使用,可以在~/.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()
-------------------------
#"; layer = >"

获取UIApplication单例对象

UIApp
-------------------------
#""

定义变量并赋值

var keyWd = UIWindow.keyWindow()
-------------------------
#"; layer = >"
keyWd.rootViewController
-------------------------
#" ChildViewControllers:(\n    \"\"\n)"
  • 当程序的进程结束,定义的所有变量会一起释放

#对象地址:拿到该对象,可用于调用方法

#0x1270e9200
-------------------------
#" ChildViewControllers:(\n    \"\"\n)"

*对象:可以取出对象的成员变量

*keyWd
-------------------------
{isa:iConsoleWindow,_responderFlags:@error,_constraintsExceptingSubviewAutoresizingConstraints:null,...

查看视图结构

keyWd.recursiveDescription()
-------------------------
@"; layer = >\n   | >\n...

格式化打印,遇\n换行

keyWd.recursiveDescription().toString()
-------------------------
`; layer = >
  | >
  |    | >
  |    |    | ; layer = >
  |    |    |    | >
  |    |    |    |    | >
...

查询当前进程中该类型的对象

choose (UIButton)
-------------------------
[#">",#">",...
脚本的封装和使用

一些常用的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

; borderStyle = None; background = <_UITextFieldNoBackgroundProvider: 0x2819310a0: textfield=>; layer = >

修改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文件

你可能感兴趣的:(iOS逆向实战--025:Cycript)