Hook之 Method Swizzling

Method Swizzling利用了Objective-C的runtime特性邀层,使得我們能動(dòng)態(tài)替換方法的實(shí)現(xiàn)返敬,實(shí)現(xiàn)hook。

runtime

從敲下NSlog(@"hello world!")開始寥院,就不斷看到runtime這個(gè)詞劲赠。對(duì)于之前沒(méi)接觸過(guò)動(dòng)態(tài)語(yǔ)言的學(xué)習(xí)者來(lái)說(shuō),runtime聽(tīng)起來(lái)陌生又晦澀秸谢。

Objective-C不同于C語(yǔ)言凛澎,它是一門動(dòng)態(tài)語(yǔ)言,這就意味著它將C語(yǔ)言等靜態(tài)語(yǔ)言在編譯和鏈接時(shí)所做的一些工作留到了運(yùn)行時(shí)再處理钮追。比如预厌,在C語(yǔ)言中,編譯時(shí)就可以確定真正調(diào)用哪些函數(shù)元媚;而Objective-C并不能在編譯時(shí)確定轧叽,只有在運(yùn)行時(shí)才會(huì)由名稱找到對(duì)應(yīng)方法。

因?yàn)檫@種特性刊棕,Objective-C需要一種機(jī)制在運(yùn)行時(shí)來(lái)處理編譯后的代碼炭晒,這種機(jī)制就是runtime。Runtime從實(shí)質(zhì)來(lái)講甥角,就是一套用C語(yǔ)言和匯編寫成的底層API恬叹,用于處理編譯后的代碼晚岭。

method

method結(jié)構(gòu)體

method_name 表示的是方法的名稱赠法,用于唯一標(biāo)識(shí)某個(gè)方法对雪;
method_types 表示的是方法的返回值和參數(shù)類型;
method_imp 是一個(gè)函數(shù)指針当犯,指向方法的實(shí)現(xiàn)垢村。
方法的名稱 name 和方法的實(shí)現(xiàn) imp 是一一對(duì)應(yīng)的。而且可以發(fā)現(xiàn)方法的名稱和參數(shù)類型是分離的嚎卫。
在我們調(diào)用一個(gè)方法時(shí)

[someObject messageName:paremeter]

在runtime底層會(huì)轉(zhuǎn)換成

Objc_msgSend(someObject, @selector(messageName), paremeter)

調(diào)用方法其實(shí)是向一個(gè)對(duì)象發(fā)送消息嘉栓,而查找方法實(shí)現(xiàn)的唯一依據(jù)是selector后接的方法名稱。所以拓诸,利用這一特性侵佃,我們就可以實(shí)現(xiàn)在運(yùn)行時(shí)更改selector對(duì)應(yīng)的方法實(shí)現(xiàn),也就實(shí)現(xiàn)了HOOK奠支。

method swizzling

原理

類和方法列表
替換

以上兩圖來(lái)自:念茜

每個(gè)類都維護(hù)著一個(gè)方法列表馋辈,里面存放著selector的名字與方法實(shí)現(xiàn)間的映射關(guān)系。Method Swizzling就是改換了這種對(duì)應(yīng)關(guān)系胚宦。

可以調(diào)用三種方法來(lái)實(shí)現(xiàn)method swizzling:
method_exchangeImplementations 交換2個(gè)方法中的IMP(IMPlication)首有;
class_replaceMethod 修改類燕垃;
利用 method_setImplementation直接設(shè)置某個(gè)方法的IMP枢劝。
這些方法的聲明都寫在runtime.h中井联。

1.method_exchangeImplementations

method_exchangeImplementations通過(guò)交換兩個(gè)方法的IMP實(shí)現(xiàn)hook的,通過(guò)
method_exchangeImplementations(A_Method, B_Method);
可以實(shí)現(xiàn)如下圖的交換您旁。

2.method_setImplementation

method_setImplementation直接設(shè)置更改某個(gè)方法的IMP烙常。
如下圖,假設(shè)有方法A鹤盒,我們想要把它的實(shí)現(xiàn)替換為方法B的實(shí)現(xiàn)蚕脏,但又不想改變方法B的實(shí)現(xiàn),就可以使用method_setImplementation侦锯,直接把A的IMP設(shè)置為B的IMP驼鞭。

3.class_replaceMethod

class_replaceMethod其實(shí)相當(dāng)于class_addMethodmethod_setImplementation的一個(gè)結(jié)合。

當(dāng)調(diào)用
class_replaceMethod(cls, name, imp, types)
時(shí)尺碰,將把屬于cls類的name方法實(shí)現(xiàn)指向imp挣棕。
如果cls類原本沒(méi)有name方法,就相當(dāng)于調(diào)用class_addMethodcls類增添了一個(gè)方法及其實(shí)現(xiàn)亲桥,這個(gè)方法的返回類型由types給定洛心。
如果cls類原本就有name方法,就相當(dāng)于調(diào)用method_setImplementation更改了name方法的實(shí)現(xiàn)為imp题篷,返回類型由替換的實(shí)現(xiàn)imp決定词身,給定types將被忽略。

參考

Objective-C的hook方案(一): Method Swizzling
Hook 原理之 Method Swizzling

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末番枚,一起剝皮案震驚了整個(gè)濱河市法严,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌葫笼,老刑警劉巖深啤,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異渔欢,居然都是意外死亡墓塌,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門奥额,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)苫幢,“玉大人,你說(shuō)我怎么就攤上這事垫挨『危” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵九榔,是天一觀的道長(zhǎng)哀峻。 經(jīng)常有香客問(wèn)我涡相,道長(zhǎng),這世上最難降的妖魔是什么剩蟀? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任催蝗,我火速辦了婚禮,結(jié)果婚禮上育特,老公的妹妹穿的比我還像新娘丙号。我一直安慰自己,他們只是感情好缰冤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布犬缨。 她就那樣靜靜地躺著,像睡著了一般棉浸。 火紅的嫁衣襯著肌膚如雪怀薛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天迷郑,我揣著相機(jī)與錄音枝恋,去河邊找鬼。 笑死三热,一個(gè)胖子當(dāng)著我的面吹牛鼓择,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播就漾,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼呐能,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了抑堡?” 一聲冷哼從身側(cè)響起摆出,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎首妖,沒(méi)想到半個(gè)月后偎漫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡有缆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年象踊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棚壁。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杯矩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出袖外,到底是詐尸還是另有隱情史隆,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布曼验,位于F島的核電站泌射,受9級(jí)特大地震影響粘姜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜熔酷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一孤紧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纯陨,春花似錦坛芽、人聲如沸留储。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)获讳。三九已至阴颖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丐膝,已是汗流浹背量愧。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帅矗,地道東北人偎肃。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像浑此,于是被迫代替她去往敵國(guó)和親累颂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355