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]
#"<UIApplication: 0x14df29bd0>"
cy#
複製程式碼
- 在Cycript中,內建了UIApp指令,就等價於[UIApplication sharedApplication]
508SC:~ root# cycript -p Aweme
cy#
508SC:~ root# cycript -p 852
cy# [UIApplication sharedApplication]
#"<UIApplication: 0x14df29bd0>"
cy# UIApp
#"<UIApplication: 0x14df29bd0>"
cy#
複製程式碼
定義變數
在Cycript中,定義變數通過var來定義,不支援OC定義變數的方式
var app = UIApp
複製程式碼
使用記憶體地址獲取物件
在Cycript中可以使用#地址資訊來獲取物件資訊
cy# UIApp
#"<UIApplication: 0x14df29bd0>"
cy# UIApp.keyWindow.rootViewController
#"<AWETabBarController: 0x14e230200>"
cy# #0x14e230200.view
#"<UILayoutContainerView: 0x14f1638a0; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x14f163c70>>"
cy#
複製程式碼
ObjectiveC.classes
使用ObjectiveC.classes來顯示當前App已載入的所有OC類
使用(*物件),來獲取物件的所有成員變數
遞迴列印View的所有子控制元件
使用如下指令篩選出某種型別的物件
#篩選出抖音中所有UIViewController型別的物件
choose(UIViewController)
#篩選出抖音中所有UITableViewCell型別的物件
choose(UITableViewCell)
複製程式碼
Cycript工具庫的使用
- 首先下載對應的工具庫github.com/CoderMJLee/…
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,30)
......
複製程式碼
字串查詢
由於在終端打印出來的UILabel裡面顯示的中文都是經過Unicode編碼的,所以如果我們需要根據當前頁面上的中文字元找到其所對應的編碼後的字元,可以藉助Python來進行中文和編碼後的轉換。
- 第一種格式
- 第二種格式
UI除錯神器-Reveal
Reveal是iOS開發中除錯UI介面的神器,可以點選官網檢視Reveal介紹和使用方式,可以點選下載Reveal
Reveal4以上的版本支援USB連結除錯,除錯速度快。Reveal4以下版本只支援wifi除錯,速度慢
Reveal除錯環境配置
- 首先需要在iPhone上使用Cydia安裝Reveal Loader,新增軟體源apt.so/codermjlee,並且下載Reveal Loader
- 安裝完Reveal Loader後,開啟【設定】,下拉找到Reveal選項,點選進入,選擇【Enable Applications】,開啟你想要除錯的App
- 找到Mac的Reveal中的RevealServer檔案,覆蓋iPhone上的/Library/RHRevealLoader/RevealServer檔案,具體路徑如下:
如果不是下載的此軟體源的Reveal Loader,可以通過檢視Cydia中已安裝的Reveal Loader,在Description中會告訴你RevealServer.framework所在具體位置,將Mac上的RevealServer覆蓋此位置的RevealServer檔案即可。
- 重啟SpringBoard或者重啟手機,可以在iPhone上輸入終端命令
//重啟SpringBoard
killall SpringBoard
//重啟手機
reboot
複製程式碼
- 開啟Reveal,同時開啟iPhone上的任意App,這時在Reveal上就會顯示出你要除錯的應用,點選應用圖示即可檢視App的UI結構