開源Hook框架-whale-實現淺析(1)

Android安全交流群:478084054

whale是lody大神開源的一個Hook框架,支持ART下Java方法的HOOK,也支持native InlineHook。

本文走馬觀花一下。

whale支持Xposed-Style Method Hook。

Xposed Hook的代碼通常這么寫:

在whale的java/com/lody/whale/xposed目錄中存放的是兼容Xposed風格的代碼。

所以,先看一下whale的XposedHelpers.findAndHookMethod和XC_MethodHook的實現源碼。

其中,findAndHookMethod用來完成Method Hook,XC_MethodHook對象用于回調。

簡單看一下class XC_MethodHook:

重寫XC_MethodHook的beforeHookedMethod或者afterHookedMethod,這兩個方法相當于是在原方法的調用前后插樁。根據需要,把我們邏輯代碼放在這兩個函數中就可以了。

重點看一下XposedHelpers.findAndHookMethod。

findAndHookMethod先調用findMethodExact得到要Hook的Method對象,然后調用XposedBridge.hookMethod完成Hook。

getParameterClasses用于獲取參數的Class類型:

從getParameterClasses的實現來看,參數類型不僅可以傳Class,還可以直接傳String。

如:Bundle.class或"android.os.Bundle "。

有了方法名和參數類型,以及實現該方法的clazz,findMethodExact的實現就很簡單了:

這里還維護了一個methodCache,用于存儲所有已經find過的method。

回到findAndHookMethod,繼續跟蹤代碼,看XposedBridge.hookMethod的實現。

所有已經Hook過的method及其對應的callbacks,全部存儲在sHookedMethodCallbacks中,這是一個HashMap。如果該method已經Hook過,那直接把callback回調對象加入到其對應的callbacks集合中就可以了。這樣在該method被調用時,callbacks集合中所有回調都會被遍歷執行。

如果該method沒有被Hook過,那就調用WhaleRuntime.hookMethodNative進行Hook。

這是一個native方法,對應的代碼在whale/src/android/art/native_on_load.cc中。

繼續跟蹤ArtRuntime::HookMethod,完成Hook的關鍵代碼就在這里了。

這里省略了大量細節代碼。先抓主干,了解基本原理。

ArtRuntime::HookMethod將被Hook的method設置為native方法,然后將Jni入口點設置為一個closure。這樣當該method被調用時,就會執行這里設置的closure。因為被Hook的method已經為native,所以ArtMethod結構中的dex_code_item_offset_成員就沒用了,直接清0。

另外,將quick_compiled_code和interpreter的入口點分別設置為quick_generic_jni_trampoline_和artInterpreterToCompiledCodeBridge,這樣無論被Hook的方法從解釋器執行,還是直接以本地指令的方式執行,最終都會執行Jni入口點,都會執行這里設置的closure。

所以,ArtRuntime::HookMethod執行之后,被Hook方法的執行就由closure接管了,這個closure是由BuildJniClosure構造的,繼續跟蹤該方法。

這里利用libffi根據原method的參數和返回類型構造一個jni-closure(jni函數相比原Java method會多兩個參數,一個是JNIEnv*,另一個是jclass或者jobject)。

libffi是一個開源項目,可以用于動態生成遵守特定調用約定的代碼。android系統源碼中也有這個庫(android/platform/external/libffi)。

當被Hook的method被調用時,就會執行這里構造的closure的callback,也就是FFIJniDispatcher,并將原參數傳入。另外,這里創建closure時,還將ArtHookParam*類型的參數param作為userdata傳入,所以FFIJniDispatcher被調用的時候,這里的參數param也會作為userdata傳入。

看一下FFIJniDispatcher的實現:

FFIJniDispatcher先利用QuickArgumentBuilder將傳給原methhod的所有參數存放到一個jobjectArray參數數組中。然后根據原method的返回類型,調用InvokeJavaBridge或InvokeVoidJavaBridge。

繼續跟蹤ArtRuntime::InvokeHookedMethodBridge:

這里是直接調用java_class_的bridge_method_方法。

java_class_和bridge_method_是在ArtRuntime::OnLoad中初始化的:

而ArtRuntime::OnLoad是被libwhale.so的JNI_Onload方法調用的。

所以,這個bridge_method_就是com/lody/whale/WhaleRuntime的handleHookedMethod方法。

繼續看XposedBridge.handleHookedMethod:

beforeHookedMethod和afterHookedMethod的調用就在這里了,相當于在原函數的調用點前后各插了一個樁。

這里的callbacks是通過參數additionalInfo得到的,而參數additionalInfo是早在XposedBridge.hookMethod方法中就創建的,并一路傳到了XposedBridge.handleHookedMethod。

再把上面的圖重復貼一下:


在XposedBridge.handleHookedMethod中,通過XposedBridge.invokeOriginalMethod來調用原方法,繼續跟蹤一下:

XposedBridge.invokeOriginalMethod又調用了WhaleRuntime.invokeOriginalMethodNative。

這是一個native方法,對應源碼在whale/src/android/art/native_on_load.cc中。

繼續ArtRuntime::InvokeOriginalMethod:

ArtRuntime::InvokeOriginalMethod先通過參數拿到原始的method,然后通過java.lang.reflect.Method.Invoke()反射調用。

參數slot是在ArtRuntime::HookMethod方法中創建的,類型是“ArtHookParam*”,param->origin_method_中保存原method對象。

至此,Java method的Hook流程基本上跟蹤完了。不過,忽略了很多值得關注和學習的細節,后面筆記再寫。

除了Java method的Hook之外,whale還支持對native函數的InlineHook。

whale/include/whale.h:

在built目錄下還有編譯好的libwhale.so可以直接使用。

看一下WInlineHookFunction的實現:

看一下arm平臺下的Hook實現ArmInlineHook:

繼續看ArmInlineHook::StartHook:

native層的InlineHook都是通過在目標方法的指令開始處加跳轉指令來實現的。

這塊很復雜,先不看了。

ArmInlineHook的實現借助了vixl,這是一個arm平臺的運行時代碼生成庫。android系統源碼也有這個庫(android/platform/external/vixl)。

文/十八坰

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379