掌握應用加固:深入剖析混淆技術

混淆視聽與你

應用安全性 現在,安全防護已是眾所周知的事實。每個人都知道它的重要性,攻擊者也知道如何繞過基本的安全防護;發布未經保護的應用程式是絕對不可取的。所有強大的安全防護都包含兩個部分:靜態分析防禦和動態攻擊偵測。靜態分析是一種強大的工具,它能讓攻擊者深入了解應用程式的特定實作細節。它會暴露應用程式中最脆弱的部分,從而加速攻擊或竊取寶貴的商業智慧財產權。原始碼以及數據, 困惑 這是任何靜態分析保護的重要組成部分。以下是一些可以轉換程式碼和資料以減緩惡意攻擊者速度的方法。他們工作量越大,攻擊就越困難。 safe我們的世界可以如此。

保護您的隱私

應用程式在發布前都應該進行某種形式的混淆處理,但並非所有混淆方法都一樣有效。任何強大的混淆方法都離不開兩個關鍵要素:私有智慧財產權和隨機化。目前可用的開源混淆器對攻擊者和應用程式開發者來說都同樣有用。這些開源混淆器提供的保護等級不足以可靠地保護企業級應用程式。真正有效的混淆需要將原始碼轉換成人類無法閱讀、自動化攻擊工具也無法逆向破解的形式。公開可用的混淆技術本身就像是破解它們的羅塞塔石碑。使用客製化的、非公開的混淆技術,可以阻止蒂米·特納(Timmy Turner)利用他的生成式人工智慧「仙女」(Generative AI Fairies)來逆向破解應用程式的混淆。將這些私有演算法與固有的隨機性結合,可以確保任何人,包括LLM(邏輯邏輯管理工具),都無法破解其本質。

偽隨機數產生器反擊戰

攻擊者可以透過比較同一應用程式的不同版本來獲取大量資訊。因此,應用程式版本之間的混淆方式必須有所不同。大多數偽隨機化引擎都使用種子來強制可預測性,同時保持其固有的隨機性,混淆也不例外。簡單地增加或減少種子值就會顯著影響應用於輸入應用程式的混淆效果。這在需要時提供了可復現性,但也迫使攻擊者在新版本發布後逆向工程時重新開始。這就像攻擊者鏟了一半車道上的雪,喝了杯熱可可休息一下,回來發現又積滿了雪。強大的安全策略旨在避免浪費時間。 逆向工程師 時間,以及不斷變化的環境,是消磨時間的最佳方式之一。

混淆 混淆 混淆

從概念上講,混淆與最佳化是相反的。就像編譯器通常會進行多次最佳化一樣,我們也會進行多次混淆。這意味著我們會對剛剛新增的混淆層再進行一次混淆。最終的結果就是程式碼極難閱讀。

圖 1:多次混淆處理顯著降低了 Ghidra 等工具解析程式控制流程的有效性。

像是簡單的 `add` 或 `mov` 指令這樣的東西,很快就會變成五十條甚至幾百條指令。如果能正確地混淆 `adrp add` 指令對,就能徹底削弱自動化工具(例如 Ghidra 或 IDA)解析程式控制流的能力。看似微不足道的混淆就能讓攻擊者幾乎不可能找到 `acceptUserCredentials` 函數呼叫的起始點、結束點或中間部分。數百種疊加且變化多樣的混淆,會讓潛在的攻擊者連程式碼是如何成功運作的都搞不清楚。

敲敲它,扭轉它,配置它

並非應用程式中的每個方法或函數呼叫都對資料敏感,有些方法或函數呼叫對效能要求極高。雖然對整個應用程式統一應用混淆仍然比什麼都不做要好得多,但這種策略會對運行時效能產生顯著影響。讓安全工程師能夠對敏感呼叫進行高度混淆,同時對效能密集型呼叫進行輕度混淆,是提供世界一流安全防護工具的關鍵所在。任何注入到應用程式中的動態保護(Guards)都需要與底層原始程式碼同等程度的混淆。對這些主動保護應用相同的高安全性混淆技術,有助於確保它們受到保護並持續運行,同時減緩攻擊者識別和移除它們的速度。可配置性對於任何以安全為中心的組織都至關重要,安全防護工具需要與公司的發展方向同步更新。如前所述,不同的混淆方式各不相同。以下是任何可靠的混淆引擎都會提供的一些概念,以及它們如何阻止未經授權的流量。

計算控制流

攻擊者只需查看應用程式中的函數呼叫流程,就能取得大量應用程式資訊。為了因應這種情況,我們的混淆技術採用了一種名為「運算控制流」(Computed Control Flow,簡稱CCF)的技術。 CCF可以阻止反編譯器將函數呼叫和標籤參考與應用程式的主入口點關聯起來。它是任何世界級安全防護的關鍵組成部分。當反編譯器分析二進位檔案時,通常很容易看出一個函數是如何呼叫另一個函數的。例如,像 `b.eq 0x10055bc42` 和 `bl 0x100abcdef` 這樣的指令。反編譯器能夠準確地知道這些虛擬記憶體位置的內容。對於前兩條指令,它們要不是函數內部的標籤,就是函數呼叫本身。任何優秀的反編譯器都會產生一張錯綜複雜的函數呼叫網路圖,清楚展現出應用程式的執行路徑。將此方法與其他基本技巧結合起來,例如查看彙編程式碼中「登入成功」訊息的使用位置,攻擊者就能輕鬆識別出可利用的程式碼。計算控制流是指在明顯的控制流呼叫之前註入的一組數學運算。這些數學運算會阻止反編譯器知道跳到的確切相對虛擬位址,從而破壞其產生控制流程圖的能力。

圖 2:計算控制流程(右)阻止反編譯器知道跳到的確切相對虛擬位址,從而破壞其產生工作控制流程圖(左)的能力。

控制流扁平化

計算控制流程 (CFF) 對反編譯器來說已經是個噩夢;如果​​我們讓它變得更糟,那就太可惜了。另一種擾亂邏輯控制流的策略叫做控制流扁平化 (CFF)。我們有多種形式的 CFF,但最近新增的一種(名為 Nexus)為這項關鍵的混淆技術注入了新的活力。我們都曾在 `main` 函數中編寫過國際象棋程序,但用一個自引用的 switch 語句編寫整個生產級應用程式又如何呢? Nexus 正是如此,同時也能優先考慮運行時效能。關於 CFF、它的重要性以及它的工作原理,網路上有很多資料。這種混淆技術給攻擊者帶來的困難怎麼強調都不為過,任何應用程式都應該在測試環境中使用它。

C hopup

任何不銹鋼刀具套裝都少不了一把配套的不銹鋼剪刀,Chopup 也以類似的方式完善了控制流混淆技術。二進位檔案格式通常採用高密度壓縮以節省磁碟空間。這意味著大多數相關的函數呼叫都彼此非常接近。因此,反彙編後的二進位檔案往往會將相關的函數分組在一起,並且幾乎總是將函數作為二進位檔案中一個連續的區塊。這太容易被讀取了,而且非常令人惱火。 Chopup 改變了這一點。二進位檔案本身並沒有技術限制要求函數呼叫在記憶體中必須連續,一把好剪刀(加上一些柔性膠水)可以讓二進位檔案保持預期運行,但迫使攻擊者必須遍歷二進位檔案的每個角落才能找到邏輯控制流程。

圖 3:Chopup 迫使攻擊者跳到二進位檔案的每個角落,以尋找邏輯控制流程。

mgDaea 和修復

混淆程式碼流程本身是至關重要的保護層,而混淆底層應用程式資料同樣必要。 “損壞”和“修復”就像靜態分析保護機制中的“混亂邪惡”和“守序善良”,幾乎總是相輔相成。損壞一段數據,甚至在某些情況下損壞一段程式碼,然後在讀取或運行之前將其修復,實際上會使靜態分析變得不可能。 「損壞」操作會將指定的資料變成看似垃圾記憶體。當相同的資料被呼叫「修復」時,它會被恢復到原始狀態,很多時候是在使用之前。之後,該資料在超出作用域後可以再次被“損壞”,直到下次呼叫函數時才會被使用。 API 金鑰在二進位檔案中最初可能是“1#&at0d$*nd@@z”,但請放心,它會在使用之前被修復。

符號重新命名

即使進行了原始碼混淆和資料混淆,編譯後的二進位檔案中仍然會殘留一些原始碼符號名稱。例如,像「acceptContinuousPayment」這樣的函數名的符號資訊很容易直接指向該函數的實作。一旦找到這些符號,修改彙編程式碼並免費存取高級功能就易如反掌。全面的符號重命名可以隱藏這些殘留訊息,讓攻擊者無從下手。移除受保護二進位檔案中所有指向敏感功能的線索,可以迫使攻擊者徹底放棄靜態分析。

圖 4:全面的符號重新命名隱藏了剩餘的痕跡,不給攻擊者留下任何可利用的東西。

以上僅列舉了一些強大的混淆實踐和方法,絕非全部。如果應用程式在實際環境中未加保護,任何人都能完全看到其獨特的智慧財產權,攻擊者也能輕易窺探其業務邏輯。隨著生成式人工智慧和原始碼輔助工具的快速普及,編寫程式碼變得無比容易,逆向工程也變得更加便利。在這種快節奏的環境中,組織層面致力於實施強大的安全解決方案是唯一可行的前進方向。不要讓開發人員的辛勤成果付諸東流。

 

閱讀IDC關於重要性的觀點 混淆和防篡改 作為你的一部分 DevSecOps 實踐。

你可能還喜歡