之前文章已經(jīng)對(duì)LLDB進(jìn)行了介紹和使用。LLDB在我們調(diào)試應(yīng)用的時(shí)候確實(shí)很爽,但他每次都要斷住程序,這在分析并且修改APP的時(shí)候確實(shí)是一個(gè)優(yōu)勢(shì),但是在面對(duì)一個(gè)比較大型的項(xiàng)目,我們需要整體分析的時(shí)候,這樣調(diào)試就顯得有些力不從心了。而Cycript就可以彌補(bǔ)上這個(gè)需求。
Cycript是由Cydia創(chuàng)始人Saurik推出的一款腳本語(yǔ)言,Cycript混合了OC、JavaScript語(yǔ)法的解釋器,這意味著我們能夠在一個(gè)命令中使用Oc或者JavaScript,甚至兩者并用。它能夠掛鉤正在運(yùn)行的進(jìn)程,能夠在運(yùn)行時(shí)修改很多東西。
一、語(yǔ)言分類
編譯型語(yǔ)言(OC)
需要將源碼經(jīng)過(guò)編譯器編譯,生成對(duì)應(yīng)架構(gòu)的可執(zhí)行文件(二進(jìn)制)解釋型語(yǔ)言(Python)
源碼不需要編譯器提前編譯,而是在運(yùn)行的時(shí)候,經(jīng)過(guò)一套對(duì)應(yīng)的解釋器,臨時(shí)將源碼翻譯成二進(jìn)制讓CPU識(shí)別。
編譯型語(yǔ)言就相當(dāng)于一個(gè)英語(yǔ)嫻熟的人看一本英文書(shū)籍,不需要借助別的工具了。代價(jià)就是學(xué)英語(yǔ)這個(gè)過(guò)程很慢(編譯時(shí)間長(zhǎng))。
解釋型語(yǔ)言就相當(dāng)于一個(gè)不會(huì)英語(yǔ)的人看一本英文書(shū)籍,這時(shí)候就需要借助工具(字典)才能正常閱讀。好處的就是沒(méi)有學(xué)習(xí)(編譯)這么個(gè)耗時(shí)的過(guò)程。
理論上解釋型語(yǔ)言在運(yùn)行效率上會(huì)比解釋型語(yǔ)言慢很多,但實(shí)際上現(xiàn)在有很多牛逼的解釋器,在執(zhí)行特定的代碼的時(shí)候效率也非??臁T砭褪窃趫?zhí)行的的時(shí)候會(huì)將之前解釋過(guò)的代碼緩存起來(lái),之后就不需要重復(fù)解釋了。如:pypy3
這片文章的主角Cycript就是解釋型語(yǔ)言!
二、安裝
1、下載安裝
Cycript的安裝極其簡(jiǎn)單,在這里下載SDK,下載下來(lái)的就是一個(gè)可執(zhí)行文件。文件不大,只有2.9M。
打開(kāi)終端,CD進(jìn)入Cycript目錄直接運(yùn)行Cycript
./cycript
不出意外這個(gè)時(shí)候會(huì)有如下報(bào)錯(cuò):

這是因?yàn)楸镜豏uby版本和Cycript要求的版本不一樣導(dǎo)致(其實(shí)代碼都一樣,只是版本號(hào)換了就不認(rèn)識(shí)了,真蠢)。
2、解決Ruby
Step 1 查看本地Ruby版本:
cd /System/Library/Frameworks/Ruby.framework/Versions/
ls

本地顯示版本號(hào)為:2.3,而Cycript要求的版本號(hào)2.0。
解決方案:
復(fù)制一本Ruby源碼,將其版本號(hào)(文件夾名稱)改為2.0
Step 2 關(guān)閉系統(tǒng)的SIP
在 OS X El Capitan 中有一個(gè)跟安全相關(guān)的模式叫 SIP(System Integrity Protection ),它禁止讓軟件以 root 身份來(lái)在 Mac 上運(yùn)行,在升級(jí)到 OS X 10.11 中或許你就會(huì)看到部分應(yīng)用程序被禁用了,這些或許是你通過(guò)終端或者第三方軟件源安裝。對(duì)于大多數(shù)用戶來(lái)說(shuō),這種安全設(shè)置很方便,但是也有些開(kāi)發(fā)者或者高級(jí) Mac 用戶不需要這樣的設(shè)置。
- 電腦重啟按住command+R,進(jìn)入恢復(fù)模式
- 打開(kāi)終端,輸入
csrutil disable,重啟 - 如果想打開(kāi)SIP,重復(fù)上兩步,命令改為
csrutil enable
Step 3 直接把2.3的復(fù)制一份,改為2.0即可
重啟電腦后,運(yùn)行如下命令:
sudo mkdir -p /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/
sudo ln -s /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/libruby.2.3.0.dylib /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.2.0.0.dylib
注:根據(jù)每個(gè)人ruby版本不同,將上面第二條命令的/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/libruby.2.3.0.dylib中的2.3改成本機(jī)的ruby版本。
這里不是降級(jí)ruby,只是復(fù)制一份2.0的ruby的dylib,讓cycript運(yùn)行起來(lái)。


再次運(yùn)行
./cycript
如果出現(xiàn) cy#即代表進(jìn)入Cycript環(huán)境了。

3、配置環(huán)境變量
Step 1 移動(dòng)Cycript
/opt目錄是專門(mén)放置一些額外功能包的目錄,所以我們將Cycript也放在該目錄下。

Step 2 環(huán)境變量
進(jìn)入用戶的根目錄,里面有個(gè)文件.bash_profile,用文本編輯器打開(kāi)。

如果你們有這個(gè)文件,就用vim新建一個(gè)吧。注意一定要用vim新建哦!
輸入如下命令:
export CY=/opt/cycript_0.9.594/
export PATH = $CY:$PATH

Save保存。之后就可以在任意目錄下使用Cycript了。
三、簡(jiǎn)單使用
1、基本的語(yǔ)法

2、基本調(diào)試
在上篇文章中已經(jīng)介紹了Monkey,并且可以看出它已經(jīng)幫我們集成了Cycript的動(dòng)態(tài)庫(kù)。所以一下就配合著Monkey來(lái)進(jìn)行調(diào)試。
馬不停蹄,新建一個(gè)Monkey工程,將已經(jīng)砸殼成功的優(yōu)酷ipa包放入對(duì)應(yīng)的Target目錄下。詳情參考:
由于Monkey默認(rèn)開(kāi)放了一個(gè)端口號(hào)6666,如圖:

所以我們就使用Cycript連接端口號(hào)6666,找到手機(jī)連接的Wifi的IP地址:

我這的是:192.168.32.113
所里在終端輸入指令:
cycript -r 192.168.32.113:6666
如果你那一直停在這一步,沒(méi)有進(jìn)入Cycript環(huán)境

那么有三種可能
- 手機(jī)和電腦必須處于同一個(gè)wifi
- wifi有問(wèn)題,換一個(gè)wifi試試,或者直接使用手機(jī)開(kāi)個(gè)熱點(diǎn),電腦連上你的熱點(diǎn)
- 端口號(hào)被占用,需要換一個(gè)端口(先換Monkey開(kāi)放的端口,再換指令連接的端口)
一切正常后就可以開(kāi)始調(diào)試了,見(jiàn)如下圖:

// 查看當(dāng)前的KeyWindow
UIWindow.keyWindow()
// 自定義變量
var keyWindow = UIWindow.keyWindow()
keyWindow
// 隱藏狀態(tài)欄
[UIApp setStatusBarHidden:YES];
// 使用地址查看
#0x108e3cd80
// 查看一個(gè)對(duì)象下的所有變量
*#0x108e3cd80
// 查看一個(gè)對(duì)象下成員變量的名字
[i for(i in *keyWindow)]
// 格式化輸出當(dāng)前View的層級(jí)關(guān)系
keyWindow.recursiveDescription().toString()
// 顯示當(dāng)前View下的所有的Button
choose(UIButton)
3、高級(jí)用法
在之前的文章 LLDB,自制LLDB腳本,竄改微信紅包金額 中介紹了LLDB可以自己定義腳本以方便自己使用,同樣Cycript也是可以做到自定義API。
1、新建cy文件
新建一個(gè)cy文件,取名FYTest.cy

2、定義變量和函數(shù)
在FYTest.cy中定義變量和函數(shù)
// 獲取AppID
FYAPPID = NSBundle.mainBundle.bundleIdentifier;
// 獲取沙盒目錄
FYAPPPATH = NSBundle.mainBundle.bundlePath;
FYRootVC = function(){
return UIApp.keyWindow.rootViewController;
};
FYGetCurrentVCFromRootVC = function(rootVC){
var currentVC;
if([rootVC presentedViewController]){
rootVC = [rootVC presentedViewController];
}
if([rootVC isKindOfClass:[UITabBarController class]]){
currentVC = FYGetCurrentVCFromRootVC(rootVC.selectedViewController);
}else if([rootVC isKindOfClass:[UINavigationController class]]){
currentVC = FYGetCurrentVCFromRootVC(rootVC.visibleViewController);
}else{
currentVC = rootVC;
}
return currentVC;
};
// 獲取當(dāng)前VC
FYCurrentVC = function(){
return FYGetCurrentVCFromRootVC(FYRootVC());
};

3、導(dǎo)入Cy文件


4、使用Cy文件
FYTest.cy文件雖然已經(jīng)在我們的APP里面了,但是我們每次使用的時(shí)候還是需要導(dǎo)入一次。
@import FYTest

5、大神們封裝好的cy
Monkey默認(rèn)幫我們預(yù)裝好了幾個(gè)cy文件,分別在一下兩張圖的位置:
-
MachO中的cy
MachO中的cy -
通過(guò)網(wǎng)絡(luò)加載的cy
通過(guò)網(wǎng)絡(luò)加載的cy
具體有哪些變量可以用,哪些函數(shù)可以用都可以在這找到哦:ms,md
四、總結(jié)
到此,所有非越獄環(huán)境下的東西已經(jīng)整理完了,接下來(lái)將要開(kāi)啟新的篇章:手機(jī)越獄、砸殼、以及匯編?kù)o態(tài)分析。如果你覺(jué)得有幫助,就點(diǎn)個(gè)小心心吧

