0%

【iOS逆向】使用Cycript调试应用

Cycript是由Cydia创始人Saurik推出的一款脚本语言,Cycript混合了OC、JavaScript语法的解释器,这意味着我们能够在一个命令中使用Oc或者JavaScript,甚至两者并用。它能够附加到正在运行的进程,能够查看和修改运行时的数据

基本使用

  1. 通过cydia安装,自带的源https://apt.bingner.com/就有cycript

  2. 打开 App ,通过 ssh 连接设备,然后进入Cycrypt调试模式

    1
    2
    3
    4
    5
    6
    7
    8
    # 调试进程(PID=323)
    cycript -p 323

    # 调试进程(进程名)
    cycript -p SpringBoard
    cycript -p neteasemusic

    # `Control+D`退出cycript模式
  3. 获取进程Id

    需要先安装插件:adv-cmds(在自带源https://apt.bingner.com/可找到)

    1
    2
    3
    4
    5
    # 查看所有进程
    ps -A

    # 搜索进程
    ps -A | grep neteasemusic
  4. 常用语法

    • UIApp:[UIApplication sharedApplication]
    • 定义变量:var 变量名 = 变量值
    • 通过内存获得对象:#内存地址
    • 查看对象的所有成员:*对象
    • 获取所有已加载的OC类:ObjectiveC.classes
    • 获取当前内存中所有UITableViewCell(包含子类)的实例:choose(UITableViewCell)
    • 递归打印所有的子控件:[view recursiveDescription].toString()
    • 查看 bundleId: [[NSBundle mainBundle] bundleIdentifier]
  5. 函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function KenPrintIvars(objc){
    var x = {};
    for(i in *objc){
    try {
    x[i] = (*objc)[i];
    } catch(e) {
    }
    }
    return x;
    }

引用外部脚本

这里使用mjcript作为外部脚本引入,下载得到mjcript.cy

把文件拷贝到手机上

1
scp mjcript.cy root@xx.xx.xx.xx:/usr/lib/cycript0.9/mjcript.cy

把手机的文件拷贝到本地

1
scp root@xx.xx.xx.xx:/usr/lib/cycript0.9/mjcript.cy ~/Desktop/mjcript.cy

加载脚本

1
2
3
4
5
6
7
8
9
# 附加到进程
cycript -p XXX

# 加载
cy# @import mjcript

# 使用脚本
cy# MJFrontVc()
#"<ZTPersonCenterViewController: 0x10520ba00>"

mjcript功能列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 包名
MJAppId;

// bundle path
MJAppPath;

// document path
MJDocPath;

// caches path
MJCachesPath;

// 加载系统动态库(/System/Library/Frameworks/xxx.framework,/System/Library/Private/Frameworks/xxx.framework)
MJLoadFramework("BluetoothManager");

// keyWindow
MJKeyWin();

// 根控制器
MJRootVc();

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

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

// 递归打印最上层UIViewController view的层级结构
MJFrontVcSubViews();

// 获取按钮绑定的所有TouchUpInside事件的方法名
MJBtnTouchUpEvent(btn);

// CG函数
MJPointMake(x, y);

MJSizeMake(w, h);

MJRectMake(x, y, w, h);

// 递归打印controller的层级结构
MJChildVcs(vc);

// 递归打印view的层级结构
MJSubviews(view);

// 判断是否为字符串 "str" @"str"
MJIsString(value);

// 判断是否为数组 []、@[]
MJIsArray(value);

// 判断是否为数字 666 @666
MJIsNumber(value);

// 打印所有的子类
MJSubclasses(className, reg);

// 打印所有的对象方法
MJInstanceMethods(className, reg);

// 打印所有的对象方法名字
MJInstanceMethodNames(className, reg);

// 打印所有的类方法
MJClassMethods(className, reg);

// 打印所有的类方法名字
MJClassMethodNames(className, reg);

// 打印所有的成员变量
MJIvars(obj, reg);

// 打印所有的成员变量名字
MJIvarNames(obj, reg);

Cycript默认不支持中文,可以使用 unicode 字符表示中文\**\**\**\**
技巧:使用python把中文转成unicode字符

1
unicode("登录", "UTF-8")

封装cycript脚本

1
2
3
4
5
6
7
8
9
(function(exports) {
exports.sum = function(a, b) {
return a + b;
};
exports.minus = function(a, b) {
return a - b;
};
exports.age = 10;
})(exports);

导入(/usr/lib/cycript0.9/test.cy),并引用

1
2
3
4
@import test

test.sum(1, 30) // 31
test.minus(6, 2) // 4

通过目录引用/usr/lib/cycript0.9/com/mj/cycript.cy

1
@import com.mj.mjcript

小结

Cycript 可以直接附加到App 进行内存调试,可以查看和修改 UIViewController,UIView,可以动态修改和分析应用的业务逻辑,用起来非常方便

引用