Method Swizzle
利用OC的Runtime特性,動態改變SEL(方法編號)和IMP(方法實現)的對應關係,達到OC方法呼叫流程改變的目的。主要用於OC方法。
關於Runtime,如果大家不瞭解,可以看看Cooci老師的文章——iOS底層原理(二):Runtime研究(一),簡單瞭解一下。
在OC中,SEL 和 IMP 之間的關係,就好像一本書的“目錄”。
SEL 是方法編號,就像“標題”一樣。
IMP是方法實現的真實地址,就像“頁碼”一樣。
他們是一一對應的關係
SEL(標題)————————IMP(頁碼)
Runtime提供了交換兩個SEL和IMP對應關係的函式。通過函式交換、改變兩個SEL和IMP關係的技術,我們稱之為Method Swizzle(方法欺騙)。
多種Hook方式
- class_addMethod
- class_replaceMethod
- method_setImplementation
程式碼示例
一、註冊
之前我們有講過程式碼注入,本文不再過多贅述,需要的同學,點選iOS逆向——shell重簽名及程式碼注入跳轉。那麼上手直接擼程式碼啦。
1、新建專案,生成新的證書和描述檔案,在手機上跑一遍,保證描述檔案可以正確安裝到手機中。
2、執行Xcode,指令碼重籤APP
3、TARGETS建立Framework,並建立.h .m,這裡我們命名Inject
4、執行app, lldb動態除錯,分析程式碼邏輯。
5、如下圖所示,因為Xcode版本不同,有的Target 和 Action 會直接顯示類名,如果不直接顯示類名的,可以用po命令+物件地址看到ClassName。p是執行指令,o是object的意思。
6、找到相關名稱,就可以用class-dump這個工具把二進位制檔案所有的類的描述copy出來(相當於標頭檔案,但是不僅僅是標頭檔案)
class-dump -H 二進位制檔案 -o 目標資料夾複製程式碼
7、根據clas-dump匯出的檔案,考慮相關邏輯。關於檢視class-dump匯出的檔案,建議使用輕量級的sublime,使用更快速。
8、那麼接下來就是程式碼了。如下圖所示:
9、執行Xcode,重籤app,這裡要注意一點,上一章我寫的指令碼,在最後一行'#程式碼注入'是註釋狀態。那麼這次執行放開,才能注入成功。Framework的名字也要改成程式碼中對應的名字。
10、鐺鐺鐺鐺
二、登入
同理,登入的的業務邏輯我們要結合動態除錯(lldb)以及靜態分析(class-dump匯出的檔案)
- class-dump匯出檔案
2、根據檔案分析業務邏輯,找出相關類。先判定控制器,是WCAccountBaseViewController,通過找WCAccountBaseViewController的屬性,判斷WCAccountTextFieldItem *_textFieldUserPwdItem與密碼相關。
通過WCAccountTextFieldItem找其父類WCBaseTextFieldItem,
在WCBaseTextFieldItem下,查到WCUITextField *m_textField。以上僅是分析,但不能判斷是否就是我們需要的UITextField,所以首先,我們要lldb除錯。
3、lldb除錯如下
4、所以最終我們需要拿到textField,最後textField.text拿到pwd.
(1)方法交換
這是在inject類中增加新的方法,再實現方法交換,但WCAccountMainLoginViewController並不存在Maxy_onNext呼叫方法,要想真正的根據業務需求實現方法交換,需要給WCAccountMainLoginViewController增加新的方法,在inject實現方法交換。
這樣並不破壞wc的登入邏輯。關於引數type,請檢視官方文件,有明確的說明。
(2)方法替換
(3)setIMP和getIMP(推薦)
三種不同的方法,都能實現。最後推薦使用setIMP、getIMP。如果我哪裡寫的不對、不清楚,還希望你能指正出來,我們共同探討進步,如果你喜歡此文章,就動一動小手點個贊吧。