Hook英文意思爲鉤子,顧名思義就是像鉤子同樣改變程序原有的運行流程。好比一段程序的執行流程是 A --> B --> C,如今咱們在 A 和 B 之間插入一段代碼或者直接改變 B ,這樣程序原有的執行流程就發生了改變。以下圖所示: app
iOS逆向中,若是咱們但願對一個OC方法進行Hook,主要應用了OC的運行時特性,在程序運行時動態改變方法的實現。在OC中,用於實現運行時特性的是一套基於C/C++以及彙編的API,即咱們常說的Runtime。而咱們Hook過程當中用到的主要是一下幾個方法:函數
一、方法交換
OBJC_EXPORT void
method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
二、替換方法
OBJC_EXPORT IMP _Nullable
class_replaceMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp,
const char * _Nullable types)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
三、setIMP & getIMP
OBJC_EXPORT IMP _Nonnull
method_setImplementation(Method _Nonnull m, IMP _Nonnull imp)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
OBJC_EXPORT IMP _Nullable
class_getMethodImplementation(Class _Nullable cls, SEL _Nonnull name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
複製代碼
在平時的開發中,咱們也會用到這幾個方法,但它們是怎麼實現方法交換/替換的呢?觀察這幾個方法的參數,咱們發現主要有 Class、SEL、IMP、Method 這幾種類型,咱們分別來看一下this
一、Class 一個 objc_class 類型的結構體指針,用於說明對象是哪一個類;spa
二、Method 一個 objc_method 類型的結構體指針,用於定義一個方法,在objc源碼中定義以下:3d
三、SEL 能夠發如今 Method 的定義中,也能看見SEL。咱們看下在蘋果官方文檔中如何定義這種類型指針
四、IMP 一樣在 Method 的定義中也能看到,在蘋果官方文檔的定義以下: code
咱們發現其實上訴方法都包含 SEL 和 IMP 這兩種類型的信息。根據上文中蘋果文檔中的介紹咱們能夠發現cdn
SEL: Method selectors are used to represent the name of a method at runtime. A method selector is a C string that has been registered (or 「mapped「) with the Objective-C runtime.對象
IMP: This data type is a pointer to the start of the function that implements the method. This function uses standard C calling conventions as implemented for the current CPU architecture. The first argument is a pointer to self (that is, the memory for the particular instance of this class, or, for a class method, a pointer to the metaclass). The second argument is the method selector. The method arguments follow.blog
SEL是一個C String,用於表示一個方法的名稱,IMP是一個方法實現首地址,默認有兩個參數 self 和 _cmd。其實SEL和IMP的關係咱們能夠類比一本書的目錄,SEL就是目錄中的內容標題,IMP是後面的頁碼。一個方法調用時,經過SEL找到對應的IMP,進而找到方法的實現。以下圖:
逆向中,Hook一個OC方法其實就是改變其SEL所指向的IMP,從而找到另外一個實現地址,執行另外一個方法實現。但這種方法的侷限在於,其只能針對OC方法進行Hook,對於C函數則沒法Hook。在下一篇文章中,咱們將探索如何Hook一個C函數以及fishhook庫的使用及原理。