iOS逆向課程筆記(十一)

Hook原理介紹

1.Objective-C消息傳遞(Messaging)

對(duì)于C/C++這類(lèi)靜態(tài)語(yǔ)言,調(diào)用一個(gè)方法其實(shí)就是跳到內(nèi)存中的某一點(diǎn)并開(kāi)始執(zhí)行一段代碼。沒(méi)有任何動(dòng)態(tài)的特性,因?yàn)檫@在編譯時(shí)就決定好了。

而在 Objective-C 中,[object foo] 語(yǔ)法并不會(huì)立即執(zhí)行 foo 這個(gè)方法的代碼。它是在運(yùn)行時(shí)給 object 發(fā)送一條叫 foo 的消息。這個(gè)消息,也許會(huì)由 object 來(lái)處理,也許會(huì)被轉(zhuǎn)發(fā)給另一個(gè)對(duì)象,或者不予理睬假裝沒(méi)收到這個(gè)消息。多條不同的消息也可以對(duì)應(yīng)同一個(gè)方法實(shí)現(xiàn)。這些都是在程序運(yùn)行的時(shí)候動(dòng)態(tài)決定的。

事實(shí)上,在編譯時(shí)你寫(xiě)的 Objective-C 函數(shù)調(diào)用的語(yǔ)法都會(huì)被翻譯成一個(gè) C 的函數(shù)調(diào)用 objc_msgSend() 。比如,下面兩行代碼就是等價(jià)的:

[people TailName:@"Test" Age:18];

objc_msgSend(people, @selector(TailName:Age:), "Test", 18);

在 Objective-C 中,類(lèi)、對(duì)象和方法都是一個(gè)C的結(jié)構(gòu)體,從 objc/objc.h 和 objc/runtime.h 頭文件中,我們可以找到他們的定義:

  typedef struct objc_class *Class;
  struct objc_object {
      Class isa  OBJC_ISA_AVAILABILITY;
  };
  typedef struct objc_object *id;
  
//Class 是一個(gè) objc_class 結(jié)構(gòu)類(lèi)型的指針, id是一個(gè) objc_object 結(jié)構(gòu)類(lèi)型的指針.

struct objc_class {
  Class isa  OBJC_ISA_AVAILABILITY;

  #if !__OBJC2__
      Class super_class                                        
      const char *name                                         
      long version                                             
      long info                                                
      long instance_size                                       
      struct objc_ivar_list *ivars                             
      struct objc_method_list **methodLists                    
      struct objc_cache *cache                                 
      struct objc_protocol_list *protocols                     
  #endif
} OBJC2_UNAVAILABLE;
  • isa
    是一個(gè) objective-c Class 類(lèi)型的指針. 實(shí)例對(duì)象有個(gè)isa的屬性,指向Class, 而Class里也有個(gè)isa的屬性, 指向meteClass. 這里就有個(gè)點(diǎn), 在Objective-C中任何的類(lèi)定義都是對(duì)象.

  • super_class
    指向該類(lèi)的父類(lèi), 如果該類(lèi)已經(jīng)是最頂層的根類(lèi)(如 NSObject 或 NSProxy),那么 super_class 就為 NULL.

  • name
    類(lèi)的名字

  • version
    類(lèi)的版本信息,默認(rèn)為0

  • info
    供運(yùn)行期使用的一些位標(biāo)識(shí)。

  • instance_size
    該類(lèi)的實(shí)例變量大小

  • ivars
    成員變量的鏈表

struct objc_ivar_list {
    int ivar_count                                          
    /* variable length structure */
    struct objc_ivar ivar_list[1]                           
}       
  • methodLists
    方法定義的鏈表
     struct objc_method_list {  
          struct objc_method_list *obsolete;
          int method_count;
    
          struct objc_method method_list[1];
     };
     
     struct objc_method {  
      SEL method_name;
      char *method_types;   
      IMP method_imp;
    

};


- objc_cache
指向最近使用的方法.用于方法調(diào)用的優(yōu)化  

struct objc_cache {
unsigned int mask /* total = mask + 1 */;
unsigned int occupied;
Method buckets[1];
};


- protocols
    協(xié)議的鏈表

struct objc_protocol_list {
struct objc_protocol_list *next;
long count;
Protocol *list[1];
};


objc_method_list 本質(zhì)是一個(gè)有 objc_method 元素的可變長(zhǎng)度的數(shù)組。一個(gè) objc_method 結(jié)構(gòu)體中:
- 函數(shù)名,也就是SEL
- 表示函數(shù)原型的字符串 (見(jiàn) Type Encoding) 
- 函數(shù)的實(shí)現(xiàn)IMP

#### 2. Method Swizzling示例
  以上面可知方法的名字(SEL)跟方法的實(shí)現(xiàn)(IMP,指向 C 函數(shù)的指針)一一對(duì)應(yīng)。Swizzle 一個(gè)方法其實(shí)就是在程序運(yùn)行時(shí)對(duì) objc_method_list 里做點(diǎn)改動(dòng),讓這個(gè)方法的名字(SEL)對(duì)應(yīng)到另個(gè)IMP。 
  
   Method Swizzling(方法調(diào)配技術(shù)),僅針對(duì)Objective-C方法有效。Method Swizzling 利用 Runtime 特性把一個(gè)方法的實(shí)現(xiàn)與另一個(gè)方法的實(shí)現(xiàn)進(jìn)行替換。

//涉及到的主要方法
class_addMethod
class_replaceMethod
method_exchangeImplementations

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,789評(píng)論 0 9
  • 前言 runtime其實(shí)在我們?nèi)粘i_(kāi)發(fā)過(guò)程中很少使用到,尤其是像我現(xiàn)在比較初級(jí)的程序猿就更用不到了。但是去面試很多...
    WolfTin閱讀 673評(píng)論 0 2
  • AdamLee007閱讀 237評(píng)論 1 5
  • 心里難過(guò)呢,怎么解。一直勸說(shuō)自己我會(huì)好好的。可是 越長(zhǎng)大越孤單,都說(shuō)人生是用來(lái)成長(zhǎng)的,可是經(jīng)歷了這么多,讓人是越來(lái)...
    Azsr閱讀 359評(píng)論 0 0
  • 如此幸福的一天 霧一早就散了,我在花園里干活 蜂鳥(niǎo)停在忍冬花上 這世上沒(méi)有一樣?xùn)|西我想占有 我知道沒(méi)有一個(gè)人值得我...
    東豐林波閱讀 221評(píng)論 0 0