[iOS 逆向 7] Hook

概述

前面經過分析與調試,瞭解了程序的執行邏輯。現在想改變執行邏輯,腦海裏也大致有了新邏輯,例如讓判斷是否是會員的函數始終返回 true。那麼怎麼把新邏輯應用到程序中呢?這是本文要介紹的。

Hook,鉤子,用來改變程序執行流程。iOS 中有以下幾種方式:

  • Method Swizzling:利用 OC runtime 特性,對 OC 方法重排。
  • fishhook:利用 Mach-O 格式程序加載原理修改符號表,對 C 函數重排。
  • Cydia Substrate:Cydia 底層框架,提供對 OC 方法、C 函數的重排接口。

Hook 原理

Method Swizzling

原理比較簡單,概括就是:OC 方法 = 方法名 + C 函數地址,我們交換兩個 OC 方法的實際 C 函數地址,即實現方法重排。細節可以直接看以前寫的文章

fishhook

fushhook 的核心思想就是修改懶加載和非懶加載符號表,源碼地址
前面提到過懶加載與非懶加載符號綁定過程,實際上就是蘋果的位置代碼獨立技術(PIC)。由於地址空間隨機化的存在,不能使用固定的地址,於是調用符號實際去調用函數樁,函數樁內讀取符號表上的值並調用。目標功能函數的真實地址由 dyld 獲取後寫入數據段中的符號表。fishhook 就是利用 PIC 技術的特點,實現 C 語言符號的“動態”特性。給定目標函數名和要替換的函數指針,fishhook 對目標函數在符號表中的值重新綁定,讓其指向要替換的函數地址,這樣就實現了 C 函數的重排。

Cydia Substrate

Cydia 底層框架,提供:
MSHookMessageEx 函數用來 hook OC 方法,原理就是對上述 Method Swizzling 的封裝。
MSHookFuntion 函數可以 hook 任意 C 函數,原理是直接修改了內存中的彙編指令,調用目標函數時,會直接跳轉到自定義函數。這種 hook 方式只能在越獄設備上使用,在非越獄設備上如果想使用這種思路,必須修改靜態文件中的指令。

Hook 工具

Theos

爲了更便捷地進行逆向開發,有人封裝了上面的 Hook 原理,編寫了注入、攔截工具 Theos。

安裝

先用 brew 安裝 ldid、fakeroot、dpkg,其中 dpkg 需要指定版本 1.18.10,可以通過執行 brew install --from-bottle https://raw.githubusercontent.com/Homebrew/homebrew-core/7a4dabfc1a2acd9f01a1670fde4f0094c4fb6ffa/Formula/dpkg.rb 安裝。最近 raw.githubusercontent.com 的 DNS 被污染,可能會出現 443 Connection Refused 的錯誤,可以修改系統中的 hosts 文件,添加該網站的 IP 地址 199.232.28.133 來恢復訪問。api.github.com 同理。

然後執行 git clone --recursive https://github.com/theos/theos.git 下載 Theos,下載後將 Theos 根目錄和 bin 目錄添加到環境變量,後面會用到。

export THEOS=/path/of/theos
export PATH=$THEOS/bin:$PATH
export THEOS_MAKE_PATH=$THEOS/makefiles

至此安裝完成。

使用

執行 nic.pl 開始創建項目,模版選擇 iphone/tweak,按提示輸入項目名,項目 ID,創建者,目標應用的 Bundle ID 等信息,創建完成後,自動生成四個文件:Makefile,編寫代碼的 Tweak.x,指定注入目標 Bundle ID 的 plist 文件,指定 deb 包的一些信息的 control。

Theos 爲了讓逆向開發更簡便,對前面的 hook 原理進行封裝,然後提供了一種新的語法。即使是沒有讀過 runtime 源碼、不瞭解程序加載等底層問題,使用 Theos 仍然可以寫 hook 代碼做逆向開發。例如,我要 hook 番茄Todo 應用中 SystemUtil 類中的 +shouldSH 函數,在 Tweak.x 中編輯如下:

%hook SystemUtil
+ (_Bool)shouldSH {
	return 1;
}  
%end

編譯時,Theos 語法會被轉換爲真正的代碼。其中 %hook 類名 用於指定要 hook 的類,然後在裏面寫需要 hook 的方法,如果參數或返回值涉及到閉包,則使用 id 類型替代。%log 打印日誌,%orig 調用原來的方法。

然後編輯 Makefile,Theos 已自動生成了部分內容,包括目標進程名,項目名,源碼文件,編譯參數。

INSTALL_TARGET_PROCESSES = TomatoTime
include $(THEOS)/makefiles/common.mk

TWEAK_NAME = MyTomato

MyTomato_FILES = Tweak.x
MyTomato_CFLAGS = -fobjc-arc

include $(THEOS_MAKE_PATH)/tweak.mk 

一般還需要手動添加目標架構和目標系統版本:

ARCHS = arm64
TARGET = iphone:latest:8.0

在命令行執行 make,沒有錯誤的話會生成一個 .theos 文件夾,裏面包含一個 MyTomato.dylib。可以手動把這個 dylib 注入到目標 App,當然 Theos 肯定也封裝了這個步驟,執行 make package 打包成 deb,成功後會生成 packages 文件夾,裏面包含一個 deb 文件。現在要把該文件安裝到手機中,如果用 ssh 傳輸則用手機的 IP 以及端口號 22,如果用 USB 連接,先用 iproxy 轉發iproxy 3333 3333,端口號是 3333,IP 用 localhost。然後編輯 Makefile,添加對應方式的值:

export THEOS_DEVICE_IP=localhost
export THEOS_DEVICE_PORT=3333

執行 make install 即可安裝。安裝成功後在手機的 /Library/MobileSubstrate/DynamicLibraries 目錄下可以看到 MyTomato.dylib 和 plist 文件。如果想查看動態庫有沒有被加載,除了直接觀察 App 運行外,電腦打開 Console.app,USB 連接手機後打開 App 就可以看到 App 的日誌。編譯前在代碼文件裏寫一個 __attribute__((constructor))函數,函數中打印自定義的信息,即可在日誌中觀察到。或者用 lldb 給原函數打斷點,觀察函數執行邏輯是否已改變。

更多語法

逆向工程中可能有更復雜的需求,下面介紹一些常用語法。

獲取類對象 %c

使用原 App 內的類時,必須使用 runtime 函數動態獲取:Class objc_getClass(const char *aClassName),Theos 將其封裝成了一個簡潔的語法 %c(aClassName)

個別文件應用 MRC

如果源文件有兩個,MyTomato_FILES = Tweak.x MySwizzle.m,其中 MySwizzle.m 必須用 MRC,則單獨爲其指定編譯參數:MySwizzle.m_CFLAGS = -fno-objc-arc

給類添加方法 %new

在要 hook 的類內,聲明 %new,下面寫方法即可。添加的是實例方法,熟悉 runtime 的話可以猜出來實際是封裝的 class_addMethod 函數。如果想給某個類添加靜態方法呢?根據 runtime 原理,需要依次用 objc_getClass 和 object_getClass 獲取元類對象,然後 class_addMethod 給元類添加方法。由此可見,Theos 並不是萬能的,只有熟悉 runtime 才能靈活地編寫代碼。

添加資源文件

如果有添加圖片等文件需求,則需要在項目根目錄新建 layout 文件夾,這個文件夾將來實際映射到手機根目錄。因此一般都會在 layout 裏建多層目錄使用,例如 layout/Library/Application Support/TomatoTime/。

使用第三方庫

和命令行編譯差不多,將庫文件複製到項目中自定義的目錄下,指定 CFLAGS、LDFLAGS、LIBRARIES、FRAMEWORKS,在代碼中直接可以導入頭文件即可使用。

快速生成代碼

如果要對某個類中的所有方法進行 hook,監控該類所有的函數調用,則對 class-dump 得到的頭文件使用 logify.pl 命令,輸出所有方法的 hook 函數。如果涉及到未知的類,手動添加 @class 聲明。輸出結果保存到一個 .xm 文件或其他位置,將該文件添加到 Makefile 編譯文件集合。

MonkeyDev

Theos 是一個命令行工具,對於習慣使用 Xcode 的 iOS 開發者並不友好。於是《iOS 應用逆向與安全》的作者開發了 MonkeyDev,相當於對 Theos 再次封裝,讓越獄開發更人性化,是一款插件開發集成神器。

安裝

在完成 Theos 安裝後,下載 MonkeyDev,然後執行 sudo ./MonkeyDev/bin/md-install。該文件夾下也有卸載、更新腳本。

使用

打開 Xcode 創建項目,在 iOS 一欄最下面選擇 Logos Tweak,創建完成後即可看到 Theos 中熟悉的幾個文件,按照 Theos 項目的規則編輯即可。其中的 Makefile 被 Xcode 工程代替,讓不熟悉 make 的開發者也可以開發越獄插件。因此前面修改 Makefile 的內容現在改爲修改項目文件,在項目 Build Settings 最後一塊,主要是設置設備 IP 和端口號。需要注意的是,項目默認 theos 和 MonkeyDev 的路徑保存在 /opt/theos 和 /opt/MonkeyDev,修改項目文件或者把對應的文件放到 /opt 目錄下。項目編寫完成後,只需要 Build 就完成了 Theos 的三步操作:make,make package,make install。

注意

第八九章還沒寫,有機會再補充,不過不重要。
八 其他知識
九 一些工具的源碼解讀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章