導讀:在移動安全中,客戶端層的安全性非常重要,因為移動應用通常在客戶端裝置上執行,並處理敏感的使用者資料。通過強化您的應用程式,您可以有效地防禦逆向工程和惡意攻擊,並保護應用程式的機密資訊和智財權。 加固通過混淆、加密保護、反除錯等方式為應用提供強大的安全層,使攻擊者更難破解和修改應用。
1. iOS加固方案
目前主流的加固方案有三種:
原始碼加固:直接基於原始碼工程混淆,這種模式一般只能在開發者環境中部署加固工具,需要一些額外的環境配置。
Bitcode 加固:因為 BitCode 本質上是 IPA 編譯過程的中間部分,其加固原理與原始碼沒有太大區別,主要區別在於對接模式,通過用 BitCode 上傳包,可以在加固廠商處進行加固過程,降低對接和環境部署的成本。
無源加固:基於IPA包的加固,由於作用於二進位檔案,功能控制不如原始碼靈活,但訪問成本低。
在新的 Xcode 15 發布後,BitCode 生成開關已被正式移除。
因此,iOS 客戶端強化最終可能只有兩個選項:原始碼強化和無原始碼。 由於原始碼加固方案是開源的,原則上有參考依據,這裡就不多說了,下面簡單介紹一下原始碼加固的一些原理。
2. iOS無原始碼加固
任何平台的原始碼強化都無法解殼檔案格式,iOS 也不例外。 與Android下的ELF檔案一樣,iOS的可執行檔案是一種猛男格式檔案。 從程式載入和操作的角度來看,男子氣概和精靈有以下相似之處和不同之處。
相似之處:兩者都使用段來描述記憶體載入範圍和許可權,並使用段來更詳細地劃分 ** 和資料。
兩者都包含符號表和字串表,用於記錄函式和變數資訊。
兩者都有重新定位的概念。
區別:iOS 部分的含義更明確,尤其是 OBJC 和 SWIFT 相關資訊。
iOS 支援延遲載入。
iOS 對符號進行了更嚴格的分類和排序。
iOS 中的 Load Command 更類似於 ELF 中 dynamic 和 PHDR 的組合,是對程式結構和依賴關係的描述。
要了解平台程式是如何強化的,首先需要了解載入和執行程式的過程。
負荷。 載入過程包括記憶體對映、記憶體修復和初始化過程。
從檔案內容來看,男子氣概包含三大資料結構。
Macho Header:包含 mach-o 檔案的基本資訊,如檔案型別、CPU 型別、載入命令數等。
load 命令:每個 load 命令都包含乙個標頭和資料。 標頭包含載入命令的型別、大小和其他相關資訊。
segment:用於描述mach-o檔案中的segment、data segment和loader所需的資料資訊。
通過解析命令結構,可以讀取與load命令關聯的所有資料,並且資料必須在上述資料範圍內。 整個男子氣概檔案大小等於上述三個資料大小的總和。
在程式的編譯過程中有一些約定,一些自實現的變數或函式的呼叫使用了相對位址,可以簡單理解為與程式載入的第乙個位址的偏移量,而不是實際位址。 但是,當程式載入到記憶體中時,第乙個位址通常是隨機的,並且這些位址需要在執行之前進行修復,這個過程稱為變基。
在程式開發過程中,如果使用動態庫中的函式或變數,生成的二進位產品會識別出這些需要匯入的函式或變數,並將函式位址保留在位址區(得到的表)中。 動態鏈結的過程是將函式位址或變數值固定在這些位置,這個過程稱為繫結。
程式載入過程很容易理解,可以分為以下三個過程。
根據分段設定的位址分配資料儲存和許可權。
根據 rebase 中的規則,對編譯生成的相對位址進行修復並轉換為真實位址。
根據 bind 中的規則,固定編譯所依賴的其他函式和變數的位址,以保證程式可以正常呼叫。
由於 iOS 版本的迭代,rebase 和 bind 的描述以及資料的儲存方式因版本而異。
在 iOS 14 下,您可以通過解析 lc dyld info 或僅解析 lc dyld info 來變基和繫結操作。
rebase 和 bind 操作都是根據 ios 自定義的一組操作碼進行解析的,可以參考 dyld 原始碼了解操作碼的處理過程。
變基通過一系列操作碼執行特定操作,其結果是確保在載入應用和隨機化記憶體基址時可以固定與程式關聯的內部位址。
bind 使用一組不同的編碼,bind 程序用於繫結符號,例如當程式使用其他庫中的變數函式時,需要將位址資訊寫入程式記憶體中,以保證這些函式和變數的正常訪問和使用。
iOS 14 及以上版本相容 14 以下的格式,但提供了新格式(修復鏈)以完成動態鏈結。 編譯應用程式時,如果選擇僅支援 iOS 14 或更高版本,則 Macho 檔案中不再有 LC Dyld Info 或 LC Dyld Info Only,並且 Dyld Chained Fixups 和 Dyld Exports Trie 將替換為 Dyld Chained Fixups 和 Dyld Exports Trie。
Dyld 鏈式修復對應於舊版本的 bind 和 rebase,其中刪除了惰性繫結機制,但 bind 和弱繫結之間仍然存在區別。
Dyld Exports Trie 對應於舊版本的匯出符號。
dyld 鏈式修復的資料圖如下:
上面的 iOS 重新定義了一組重新定位資料的方法,Fixup Chains 有兩個關鍵功能:
初始化匯入表,該表是乙個包含符號資訊和 lib 資訊的鍊表或陣列,指向符號的 **,其陣列索引與繫結資料相關聯。
引導 dyld 在 segment 資料中找到 dyld 鏈式的起始位置,計算出資料中真正需要修復的位址,通常在 got 表或者一些引用的區域性變數中。
在資料部分,初始化方法與以前的版本不同。
在舊格式中,您可以指定哪些位址需要變基,哪些位址需要繫結。 在真正要修復的位址中,預設值可能是 0 或相對位址。
新版格式 fixupchains 只獲取資料的第乙個位址,需要通過 chainedfixuppointerondisk 的結構以鍊表的形式對資料進行解析,並根據結構型別進行相應的修復操作。
新版本的 macho 增加了格式的複雜性,但在大量重定位的程式中,資料量可以減少很少。
執行。 執行過程涉及一些預設情況下在程式中執行的介面。 在這裡,我們更多地關注 main 函式在啟動之前的行為。
在類和類擴充套件中載入和註冊方法。
呼叫 objc 的 +load 函式。
在 mod init func 中執行函式,包括但不限於以下規則中宣告的函式。
宣告為屬性(建構函式)的 C 函式)。
已在全域性變數中初始化的物件。
執行 main 函式。
關注啟動過程的目的是在做加固時,在合適的時間初始化加固相關的功能,比如在負載中初始化,或者插入init進行初始化。 您需要確保初始化時間在加固函式生效之前。
場景和效果。
在確認了程式的載入和執行過程後,我們可以對程式進行資料加密、混淆轉換、功能對抗等操作,以達到所需的保護效果。 二進位密碼混淆幾乎總是基於彙編和檔案處理,這比原始碼更難,但如果處理得當,其分析難度並不比原始碼加固差,相反,由於彙編和檔案處理的靈活性,修改特徵會更容易。
以下是保護作用之一:
從效果上看,不像普通的混淆,表面有一層抽取,而真正的**次級混淆,不僅無法分析函式體,甚至連引數型別都無法正常解析。
三、結語
在本文中,我們詳細介紹了一些 iOS 應用程式強化的工作原理。 希望能幫助一些需要了解強化的朋友了解一些原理知識。 在當今的數字時代,應用程式安全至關重要。 為了保障使用者資料和業務的安全,我們不斷完善iOS加固產品,為開發者提供全面的應用防護解決方案。
如果您對我們的加固產品感興趣或想了解更多資訊,請訪問網易盾**。 我們很樂意為您提供定製的解決方案,以滿足您的安全需求。