iOS冰與火之歌番外篇 - 在非越獄手機上進行App Hook

wyzsk發表於2020-08-19
作者: 蒸米 · 2016/02/18 10:19

0x00 序


冰指的是使用者態,火指的是核心態。如何突破像冰箱一樣的使用者態沙盒最終到達並控制如火焰一般燃燒的核心就是《iOS冰與火之歌》這一系列文章將要講述的內容。但在講主線劇情前,我們今天先聊一聊分支劇情 - 在非越獄的iOS上進行App Hook。利用這個技術,你可以在非越獄的iOS系統上實現各種hook功能(e.g., 微信自動搶紅包,自動聊天機器人,遊戲外掛等),但寫這篇文章的目的並不是鼓勵大家使用外掛,更不是鼓勵大家去賣外掛,所以千萬不要用這個技術去做一些違法的事情。

《iOS冰與火之歌》系列的目錄如下:

  1. Objective-C Pwn and iOS arm64 ROP
  2. 在非越獄的iOS上進行App Hook(番外篇)
  3. █████████████
  4. █████████████
  5. █████████████

另外文中涉及程式碼可在我的github下載:
https://github.com/zhengmin1989/iOS_ICE_AND_FIRE

0x01 Mach-O LC_LOAD_DYLIB Hook


要是看過我寫的安卓動態除錯七種武器之離別鉤 – Hooking(上)/tips/?id=9300 和 安卓動態除錯七種武器之離別鉤 – Hooking(下)/papers/?id=10156 的同學應該知道在android進行hook的方法可以是五花八本的。其實在iOS上進行hook的方式也有很多,但是大多數都需要越獄後才能實現(比如大家最常用的Cydia Substrate),今天我就來介紹一種不需要越獄就能hook iOS app方法,也就是Mach-O LC_LOAD_DYLIB Hook。這種方法是透過修改binary本身來載入第三方dylib並實現hook,具體思路是:

提取ipa中的二進位制檔案 -> 修改二進位制檔案的Load Commands列表,加入要hook的dylib –> hook.dylib在函式constructor函式中完成對特定函式的hook->對修改後的ipa進行簽名,打包和安裝。

首先我們先來看一下我們將要進行注入的目標app,這個app非常簡單,就是呼叫上一章講過的talker這個類輸出一句”Hello, iOS!”。

p1

在Products資料夾中我們能夠看到IceAndFire.app這個檔案,也就是編譯完後的app:

p2

IceAndFire.app其實就是個資料夾,裡面可以看到很多的資原始檔(簽名資訊,圖片等),但最重要的東西就是與資料夾同名的IceAndFire這個二進位制檔案了。我們可以用xxd命令來看一下里面的內容:

p3

這個二進位制檔案裡儲存了IceAndFire這個app的所有邏輯,但是直接看二進位制編碼太辛苦了,這裡我推薦一個叫做MachOView的軟體(可以在我的github裡下載),透過這個軟體就可以看到整個MachO檔案的結構了:

p4

在Load Commands這個資料段裡,我們可以看到IceAndFire這個二進位制檔案會在啟動的時候自動載入Foundation, libobjc.A.dylib等動態庫。如果我們對MachO這個檔案的Load Commands結構體進行修改,是不是就可以讓IceAndFire這個app在啟動的時候載入我們自定義的用來hook的dylib呢?沒錯,這個想法是可行的。並且我們只要在dylib的建構函式里完成相應的hook邏輯,就可以在app啟動的時候對指定函式進行hook操作了。

那麼如何修改MachO的結構體呢?用010 editor等二進位制編輯器的確是一種方法,但實在是麻煩了點。好訊息是金正日小分隊已經把自動注入dylib的工具幫我們寫好了。這個叫yololib的工具可以幫我們直接進行dylib的注入:https://github.com/KJCracks/yololib。但作者只放出了原始碼沒有放出binary,我幫大家編譯了一份扔到了我的github上(https://github.com/zhengmin1989/iOS_ICE_AND_FIRE)。

編譯好yololib後,我們只需要在mac上執行:

#!bash
./yololib [binary] [dylib file]
./yololib [被插入dylib的二進位制檔案] [要插入的dylib]

命令即可完成dylib的注入,如圖所示:

p5

現在我們再用MachOView看一下IceAndFire這個二進位制檔案就會看到hook1.dylib已經被我們成功注入進去了:

p6

@executable_path/hook1.dylib”的意思是二進位制檔案會在當前目錄下對hook1.dylib進行載入,所以我們編譯好的hook1.dylib要和二進位制檔案一起放到IceAndFire.app資料夾裡,這樣才能保證我們在執行app的時候hook1.dylib能夠被正確的載入。

0x02 CaptainHook for Dylib


修改好了app二進位制檔案的Load Commands結構體後,我們再來看看如何構造進行hook的第三方dylib。因為app自己肯定不會主動呼叫第三方dylib中的函式,所以如果我們想要讓第三方dylib進行hook操作就要把hook的邏輯寫到建構函式里。實現建構函式很簡單,只要在函式前宣告 ”__attribute__((constructor)) static” 即可,我們先寫個”Hello, Ice and Fire!”測試一下:

p7

編譯好dylib檔案後,我們將這個dylib檔案與app一起簽名、打包、安裝。然後我們執行一下程式就可以看到我們注入的dylib庫已經在程式啟動的時候成功載入並執行了。

p8

下一步就是要實現對特定函式的hook。在這裡我推薦使用CaptainHook這個framework。作者已經幫我們實現了hook所需要的各種宏,只要按照如下步驟就可以完成針對特定函式的hook:

  1. 使用 CHDeclareClass() 宣告想要hook的class
  2. 在建構函式中用 CHLoadClass() 或 CHLoadLateClass() 載入宣告過的class
  3. 使用CHMethod() hook相應的method
  4. 在CHMethod()中可以使用CHSuper()來呼叫原函式
  5. 在建構函式中使用CHClassHook()來註冊將要hook的method

比如我們想要hook Talker這個class裡的say method,讓app在呼叫say的時候修改method的引數,讓say的話都變成”Hello, Android!”,我們只需要這樣編寫dylib的原始碼:

#!objc
#import <CaptainHook/CaptainHook.h>

CHDeclareClass(Talker);

CHMethod(1, void, Talker, say, id, arg1)
{
    NSString* tmp=@"Hello, Android!";
    CHSuper(1, Talker, say, tmp);
}

__attribute__((constructor)) static void entry()
{
    NSLog(@"Hello, Ice And Fire!");
    CHLoadLateClass(Talker);
    CHClassHook(1, Talker,say);
}

CHMethod()這個宏的格式是:引數的個數,返回值的型別,類的名稱,selector的名稱,selector的型別,selector對應的引數的變數名。

CHClassHook()這個宏的格式是:引數的個數,返回值的型別,類的名稱,selector的名稱。

編寫完程式碼後,我們對原始碼進行編譯,將生成的dylib檔案與app一起簽名、打包、安裝。然後我們執行一下程式就可以看到我們注入的dylib庫已經成功的hook了say method了,原本應該輸出”Hello, iOS!”,已經被我們成功的變成了”Hello, Android!”:

p9

0x03 簽名、打包和安裝


我們知道越獄後的iPhone有一個很重要的特性就是可以關閉app的簽名校驗,關掉簽名校驗後,App Store上的app(無論是收費的還是免費的)就可以隨意盜版並且免費安裝了。但是在非越獄的iPhone上,系統要求app必須要有合法的簽名,負責無法進行安裝。其實除了AppStore上的app有合法的簽名外,我們還可以使用開發者證書或者企業證書來讓沒有合法簽名的app擁有合法的簽名。

當我們擁有開發者帳號並且在機器上安裝了證書的話,就可以在Keychain Access這個工具中看到我們的簽名資訊:

p10

我們接下來要乾的事情就是使用這個開發者證書來對我們修改後的IceAndFire .app進行簽名。步驟如下:

  1. 首先先保證IceAndFire.app資料夾下有正確的embedded.mobileprovision檔案:

    如果沒有的話,可以去蘋果的開發者中心(developer.apple.com)生成。如果是個人開發者要注意將iOS裝置的UDID加到開發者的裝置列表中再生成embedded.mobileprovision檔案,如果是企業證書則沒有裝置數量的限制。

  2. 正確的編寫簽名時使用的Entitlements.plist:

    這裡最需要注意的就是application-identifier要包含正確的Team ID (可以在開發者中心檢視) 和對應的Bundle ID。

    p11

  3. 使用codesign對hook的dylib進行簽名:

    #!bash
    codesign -f -s "iPhone Developer: [email protected] (XXXXXXXXX)" IceAndFire.app/hook1.dylib
    
  4. 使用codesign對app進行簽名:

    #!bash
    codesign -f -s "iPhone Developer: [email protected] (XXXXXXXXX)" --entitlements Entitlements.plist IceAndFire.app
    
  5. 使用xcrun將IceAndFire.app打包成IceAndFire.ipa:

    #!bash
    xcrun -sdk iphoneos PackageApplication -v IceAndFire.app  -o ~/iOSPwn/hook/github/IceAndFire.ipa
    
  6. 使用itunes或者mobiledevice進行安裝。

enter image description here

成功的話會顯示”OK”。然後就可以在非越獄的手機上使用我修改後的app了。

0x04 Class-dump 和 ida


透過上面幾節的介紹,我們已經將非越獄app hook的流程走過一遍了,但這時候有人會問:”你hook的app是自己寫的,你當然知道應該hook哪個函式了,我想hook的app都是App Store上的,並沒有原始碼,我該怎麼辦?”其實這個問題也不難解決。只要用好class-dump和ida即可。

Class-dump是一款可以用來dump標頭檔案工具:

p13

比如我們想要dump XXX的標頭檔案,只需要執行:

#!bash
./class-dump -H -o header XXX

經過dump後,所有的標頭檔案都會儲存在”header”這個資料夾中:

p14

每個標頭檔案中都包含了類和方法的宣告:

p15

可以看到,利用class-dump能夠很好的幫助我們瞭解app的內部結構。但是class-dump只能獲取app的標頭檔案,並不能知道每個方法具體的邏輯,這時候我們就需要用到ida了。

利用ida我們可以獲取到一個方法具體的邏輯,不過這需要你對arm彙編有一定的瞭解:

p16

比如上圖所示的函式就是呼叫NSLog(@”%@\n”)來向控制檯輸出引數的內容。只有瞭解了某個函式具體是做什麼的,我們能才知道如何hook這個函式。

0x05 微信自動搶紅包的原理


至於微信自動搶紅包的外掛無非就是hook了接收微信訊息的函式,然後判斷訊息中有沒有紅包,有的話就直接呼叫開啟紅包的函式即可。但因為這篇文章的主要目的是介紹非越獄手機的app hook,而不是鼓勵大家使用外掛,所以具體實現的細節就不公佈了,有興趣的同學可以自己嘗試寫一個。雖然效果沒有機械流那麼酷炫,但的確省時省力啊。

p17

p18

0x06 總結


透過這篇文章我們可以看到,即使是在非越獄的iOS系統上依然可以玩出很多的花樣,因此各大it廠商不要盲目的相信非越獄iOS系統的安全性。針對紅包和支付等比較重要的邏輯一定要有混淆和加固,針對app本身一定要有完整性校驗。不然好心的白帽子可能只是寫個自動搶紅包的外掛玩玩,但是駭客就可能利用這種技術開發各種外掛來牟取暴利或者讓使用者在無意當中安裝上帶有後門的app,隨後會發生什麼就只有天知道了。

最後感謝我的同事黑雪和耀刺對這篇文章的幫助和指導。

PS: 文中涉及程式碼可在我的github下載:

https://github.com/zhengmin1989/iOS_ICE_AND_FIRE

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章