發布:九月3,2024
像威脅行為者一樣思考:iOS 二進位檔案修改
二進制修改簡介:本文的動機
本文是 iOS 網路安全攻擊系列文章的第二部分。您可以在這裡找到第一篇文章。 此處其中解釋了 iOS IPA 套件的格式和應用程式側載。我們建議您在繼續閱讀本文之前先熟悉這些背景資訊。
攻擊應用程式的威脅行為者通常希望修改他們攻擊的二進位檔案。然而,在修改之前,攻擊者可以採取多種步驟對二進位進行逆向工程和除錯。威脅行為者可以使用多種技術來了解二進位文件,還可以使用更多技術來創建巧妙的修改,從而繞過現有功能或添加惡意行為。即使是僅更改應用程式中幾個位元組的簡單修改,也可能造成重大影響。
本文將提供一份逐步指南,介紹如何在 iOS 應用程式中尋找並修改一條簡單的 4 位元組指令,從而完全繞過身份驗證檢查。我建議學習多種攻擊向量的基礎知識,並像攻擊者一樣思考,因為了解攻擊者將使防禦變得更加容易。這些技術可用於驗證 Digital.ai 保護措施,或學習和理解為什麼需要應用程式安全來抵禦這些攻擊。
威脅行為者的動機
威脅行為者可能出於多種原因修改應用程序,本文僅舉一例。以下列舉了一些現實可行的動機:
- 繞過數位版權管理(DRM)或許可證檢查。
- 以惡意軟體、間諜軟體、比特幣挖礦程式或其他任何惡意活動替換原有功能。
- 禁用線程或禁用監視機制。
- 嘗試停用應用程式安全產品中插入的保護措施。
遵循本指南所需的工具
- 拆卸工具: 本指南使用 Ghidra 11.1.2。其他可選版本包括 IDA、Hopper 或 Binary Ninja。
- 代碼: 本指南使用 Xcode 15.4,但支援更廣泛的版本。
- Git: iOS應用程式使用的原始碼位於 點擊此處。
- Python 3: 用於編寫解包和修改 iOS 二進位檔案的腳本。
- iOS版: 應用程式簽名或側載設定。
- 用於測試應用程式的 iPhone: 本指南使用實體 iPhone,但您也可以使用 iPad 或搭載 PlayCover 的 Apple 晶片 Mac,或調整本指南以建立和攻擊 Apple 晶片 macOS 應用程式。
- 可選: XXD 命令列工具,用於檢查您的工作。
工作調度員申請樣本
Job Dispatcher 是一個 iOS 應用程式範例,可用於示範針對 iOS 應用的攻擊以及測試應用程式安全機制。 Job Dispatcher 是一款技術人員可能用來接收和完成任務的應用。在本指南中,我們假設自己是攻擊者,試圖繞過身份驗證檢查,使任何密碼都能被接受。
第一步是透過從上面的 GitHub 連結下載範例應用程序,然後使用 Xcode 建立 IPA 檔案來建立範例應用程式。

找到要修改的目標
本指南將展示如何繞過 Job Dispatcher 應用程式的登入介面。更具體地說,我們將繞過密碼驗證,接受任何密碼。
首先,我們需要一個工具來幫助我們理解編譯後的二進位。 Ghidra 可以將編譯後的應用程式反彙編成人類可讀的彙編程式碼,也可以將其反編譯成類似 C 語言的程式語言。本指南將使用 Ghidra 在二進位檔案中尋找登入介面的相關程式碼段,並分析哪些組譯指令可以修改以繞過登入介面。
請注意,作業調度器中的登入功能並不實際。它使用硬編碼的用戶名和密碼進行驗證。雖然這種登入方式不切實際,但許多函數都遵循這種設計,即根據已知的約束條件檢查開放式輸入。本指南的目的是學習如何繞過函數檢查,因為函數檢查的效果是可見的,所以本指南會使用這種函數。
威脅行為者不會擁有應用程式的原始程式碼,但我們還是快速看一下,以便了解我們正在處理什麼並簡化我們的步驟。

透過逆向工程二進位檔案來尋找目標可能非常耗時,尤其是在應用程式經過混淆處理的情況下。在本例中,目標函數應該位於字串「tech」和「secret」附近,因此讓我們在編譯後的二進位中搜尋這些字串。在許多應用程式中,逆向工程師可以使用錯誤訊息或日誌字串來尋找他們感興趣的程式碼片段。此外,還有一個字串表示“無效的使用者名稱或密碼”,攻擊者可能會使用這個字串來尋找相關的程式碼片段。由於 Swift 處理 alert 呼叫的方式,因此「無效的使用者名稱或密碼」字串更適合用於動態分析技術,而不是我們將要使用的靜態分析方法。
逆向工程作業調度員
現在,讓我們在 Ghidra 中開啟 Job Dispatcher 二進位 Mach-O 檔案。您需要建立一個新的非共用 Ghidra 專案。進入程式碼瀏覽器介面後,我們可以匯入 Job Dispatcher 檔案並使用所有預設分析選項。此過程需要幾分鐘。

這裡需要說明的是,我們沒有提供預編譯的應用程式。當您使用不同的 Xcode 版本、建置設置,或可能對原始程式碼進行修改來建置應用程式時,位址、暫存器甚至彙編程式碼本身的值都可能不同。您可能需要調整所使用的位址和暫存器才能繼續進行操作。
我們知道想要尋找的程式碼位於字串“tech”和“secret”附近。讓我們搜尋這些字串。為此,請使用選單選項“搜尋”->“查找字串…”
典型的攻擊者可能會開始猜測一些可能感興趣的字串,直到找到值得調查的內容。我們這裡就不做猜測了,直接搜尋字串「secret」。


點擊字串會將程式碼瀏覽器跳到該字串所在的位置。找到相關代碼需要幾個步驟。現在,讓我們沿著字串的引用來找出程式碼。

看起來「tech」和「secret」這兩個字在二進位檔案的常數字串部分相鄰儲存。現在,請根據提供的交叉引用 (XREF) 找到另一個資料位置。

這些常數字串被封裝在 CFString 物件中,我們可以在這裡看到。下面,我們可以繼續追蹤 CFString 物件的交叉引用,看看程式碼中哪些地方使用了這些字串。
這看起來可能就是我們要找的程式碼。在精簡後的二進位檔案中,內部函數的函數名稱並不存在。 Ghidra 貼心地將這個函數命名為 FUN_10004000,以指示位址 10004000 處的函數。我們需要仔細閱讀這段反組譯和反編譯程式碼,看看它是否與之前更簡單的原始碼相符。彙編程式碼可能比較難讀,所以首先,分析右側的反編譯程式碼。其中有一個函數接受兩個參數,然後呼叫 FUN_10001e2ec 來進行一些比較。接下來(如下圖),我們將檢查這個輔助函數,看看它的作用。
這是一個字串比較函數。這正是我們所需要的。這些函數在 Ghidra 中的實作方式與原始碼略有不同。您可以查看 GitHub 上的原始程式碼,以便更好地了解逆向工程過程中會移除哪些資訊。
根據文件如果字串匹配,則傳回 YES,否則傳回 NO。我們希望它始終返回 YES,以允許使用任何密碼。
這是相關的彙編程式碼部分。 “password”字串透過暫存器x2引用。然後,我們呼叫“isEqualToString”函數。依照ARM64v8的呼叫約定,函數呼叫的回傳值會儲存在暫存器x0中。我們可以看到,字串比較的回傳值在字串比較函數呼叫之後的下一行程式碼中被處理。這行程式碼是“mov x20, x0”,它將x0暫存器中的值複製到x20暫存器。我們可以輕鬆修改這條MOV彙編指令,使其始終將「YES」寫入x20暫存器,而不管提供的密碼是什麼。
為此,我們需要替換二進位檔案中的這一行彙編程式碼:
MOV x20, x0
用十六進位表示為“f4 03 00 aa”。
這段組譯程式碼使用了一個表示「是」的常數值,完全忽略了字串比較的結果:
MOV x20,#01
我們可以使用線上 ARM64v8 彙編到二進位轉換器來確定 Mov x20, #01 由十六進位值表示:
34 00 80 D2
Ghidra 的數據顯示,這條組裝線存放在以下位置:
0x100004040
在這種情況下,0x10000000 是鏡像檔案進入 TEXT 段的偏移量,二進位指令就儲存在該段中。應用程式載入器使用此偏移量,但磁碟上檔案內容的位址從 0x0 開始。

因此,我們要替換的二進位指令在作業調度程式二進位檔案中的偏移量位於 0x4040 處。現在我們知道需要修改什麼以及需要在文件的哪個位置進行修改。
讓我們開始駭客攻擊吧!
雖然我們可以手動用十六進位編輯器開啟二進位檔案並取代字節,但這不太方便。這裡有一個便捷的 Python 腳本,它可以解壓縮文件,修改一行彙編程式碼,然後將修改後的二進位檔案重新壓縮。您可能需要修改路徑以符合您選擇的目錄。
1 from zipfile import ZipFile 2 import os 3 import shutil 4 5 def hack_and_repack(payloadDir, hackedDir, inputIpa, movOffset, storeTrue): 6 7 # 解壓縮 IPA 檔案以取得目標二進位檔案 8Ipas's ' zObject.extractall(path=payloadDir) 10 11 target = os.path.join(payloadDir, "Payload", "Job Dispatcher.app", "Job Dispatcher") 12 13 # 實際的 hackzorz 部分 14 with open(target, "r+b; 16 targetFile.write(storeTrue) 17 18 # 重新壓縮並重新產生 IPA 檔案 19 hackedIpa = os.path.join(hackedDir, "Job Dispatcher.ipa") 20 shutil.make_archive(os.path.join(hackedpatir, "Defir), "Duta), "Dip.join(hackydir, "D.S. os.rename(os.path.join(hackedDir, "Job Dispatcher.ipa.zip"), hackedIpa) 22 23 hack_and_repack("payload", "hacked_dir", "JobDispatcher/Job Dispatcher.ipa", int(b"4040" b'\x34\x00\x80\xD2')
使用以下命令執行此腳本: python3 hacking_script.py
腳本完成後,需要新增一個新的IPA檔案。這個IPA檔案需要修改,新增新的MOV彙編指令,這樣就能接受任何密碼。我們也可以透過將修改後的二進位檔案重新載入到Ghidra中,或使用XXD進行快速檢查,來驗證它是否被正確修改。
% xxd -s 0x4034 -c 4 -g 1 -l 16 Payload/Job\ Dispatcher.app/Job\ Dispatcher 00004034: 02 09 46 f9 ..F. 00004038: e0 03 13 46 f9 ..F. 00004038: e0 03 13 0. 0004:009 00004040: 34 00 80 d2 4...
我們可以看到,新的移動指令已插入到位址 0x4040。
要運行和測試修改後的 iOS 應用程序,我們必須正確地重新簽署或將其側載到我們的 iOS 裝置上。這在以下文件中有詳細描述: 本系列的第一篇文章運行應用程序,使用用戶名“tech”進行測試,密碼框中可以輸入任何內容;所有密碼都應該被接受,然後進入下一畫面。
外賣
未受保護的應用程式會將關鍵業務邏輯暴露給潛在威脅,從而增加業務風險,使威脅行為者能夠未經授權修改應用程式的二進位程式碼,並可能繞過關鍵的安全功能,例如許可檢查、身份驗證檢查或其他關鍵功能。
對於遊戲而言,攻擊者通常會創建破解版或無DRM保護的遊戲版本,然後將這些破解版提供給其他使用者。如果攻擊者能夠修改二進位文件,他們還可以將加密劫持或惡意軟體植入應用程序,然後嘗試將破解後的應用程式分發給毫不知情的最終用戶。 Digital.ai 可以降低這些風險,使應用程式的攻擊變得極其困難且耗時,以至於即使是意志堅定的攻擊者也會選擇其他更容易下手的目標。本系列的下一部分將討論如何防禦 iOS 二進位檔案篡改。
如果您已經在使用我們的產品,不妨嘗試保護 Job Dispatcher,使其能夠偵測到身分驗證功能的修改,並在使用者嘗試登入之前登出應用程式。如果您嘗試這樣做,我建議您停用混淆功能,否則您可能會發現幾乎不可能成功。
請查看我們的頁面 有關我們如何阻止二進制修改的更多資訊。