App加固中的程式碼混淆功能,讓逆向工程師很頭疼

iOS皮皮豬呀發表於2023-11-16

App加固中的程式碼混淆功能,讓逆向工程師很頭疼

“我想離開浪浪山。”

在數次嘗試破解某個App 時,某個逆向工程師無奈感慨道。

image.png

逆向工程師顧名思義就是把一個個完整的軟體逆推,還原成一段段程式碼,方便破解。

比如給他們一個手機App、電腦程式,用不了多久,他們就能逆推出程式的執行邏輯,找到其中的關鍵程式碼,篡改、破解、發現漏洞。

這其中最好的例子就是盜版軟體。開發者們累死累活才寫好的程式,分分鐘就被人逆向破解,植入廣告和木馬,重新打包成盜版。

但逆向工程師並非是反面形象,亦有好壞之分,正義的逆向者只是做安全研究,而那些非正義的逆向者卻拿著這項技能四處幹壞事牟利。

因此,二者的對立也尤為明顯,一方為了防破解使出渾身解數,一方為了破解絞盡腦汁。

今天,我們就來講講關於讓非正義的逆向工程師們頭疼的程式碼混淆。

程式碼混淆究竟是什麼?

關於程式碼混淆,百度百科給出的解釋是:程式碼混淆(Obfuscation)是將電腦程式的原始程式碼或機器程式碼,轉換成功能上等價,但是難於被人閱讀和理解的行為。混淆後的程式碼,會將原先有明確含義的類名、欄位、函式等轉為無意義的單詞,這樣對於計算機來說,執行邏輯還是正常的,但是當人們去分析混淆後的程式碼時,會加大閱讀和理解的難度,以此來加強程式碼的保護。

1677216717933100.png

什麼意思呢?

我們可以簡單理解為程式碼開發者是想給破解者(逆向工程師)製造一個假象,從而讓他們從其他角度去嘗試破解,但破解之後發現方向是錯的,便又需要重新找角度破解,增加破解難度,也給開發者們充分時間來對抗破解。

舉個例子。

你想去超市買水果,但又不想讓人知道,於是你先去買了衛生紙回來,又去了健身房,然後又去超市買了可樂,最後才去超市買了水果。

這樣一來,別人對你的行動目的就不是明確的,需要多次猜測推理才能知道你的目的。程式碼混淆的邏輯便是如此,程式碼開發者們為了隱藏目的,會在程式碼里加入各種多餘的垃圾指令和程式碼,把原來的邏輯拆分成各種怪癖語法,從而達到防破解的目的。

如何做程式碼混淆?

講到這裡,你一定也好奇,程式碼混淆究竟是怎麼做的?

對此,頂象移動安全總監Bob解釋道:程式碼混淆主要有以下幾方面工作:

1、程式碼中的包含各種元素,比如變數、函式、類的名字,這些名字有實際意義,直白的告訴破解者這個程式碼的功能用途.如果能改成無意義的名字,使得破解者閱讀時無法根據名字猜測其功能用途;

2、良好的程式碼有著直白的程式碼邏輯,破解者閱讀時可以輕易的反推出功能用途.如果將它們變為功能上等價、但是更難理解的形式,比如將迴圈改為遞迴、精簡中間變數等,破解者需要付出更高的代價才能明白其功能用途;

3、對於一些解釋型的程式碼,比如JavaScript,通常以原始碼的形式釋出,程式碼有良好的格式並且包含註釋直接描述了程式碼的功能用途.如果能打亂程式碼的格式,刪除原始碼註釋,刪除空格,將多行程式碼擠到一行程式碼等,破解者將難以從原始碼中獲取有效資訊;

對程式碼的閱讀通常需要藉助一些逆向工具,比如IDA,JADX,JDGUI.如果能用某種方式讓這些逆向工具失效,可以逼迫破解者使用效率地下的手工分析, 進而干擾反編譯的工作。

一般而言,程式碼混淆的常見手段分為以下幾種:

1、名稱混淆

將有意義的類,欄位、方法名稱更改為無意義的字串。生成的新名稱越短,位元組程式碼越小。在名稱混淆的位元組程式碼中,包,類,欄位和方法名稱已重新命名,並且難以恢復原始名稱。

2、程式碼縮減

刪除程式碼中對執行無用的註釋,空格,換行,回車,除錯資訊,行號等,可以減小程式碼體積同時降低程式碼中有效的資訊量.

3、控制流混淆

用於if, switch, while,for等關鍵字,對程式碼進行細微的修改,模糊控制流,而不改變程式碼在執行時的行為。通常情況下,選擇和迴圈等邏輯構造會被更改,因此它們不再具有直接等效的原始碼。流模糊的位元組碼通常強制反編譯器將一系列標籤和非法的go to語句插入到它們生成的原始碼中。

4、資料流混淆

對一些通用的計算,將其替換為等價的形式.比如a=b+c替換為a=b+1+c-1.

5、花指令

在正常的指令序列中新增一些指令,對執行時無害,但是會觸發逆向工具的Bug,造成逆向工具崩潰,無法反彙編,無法反編譯,功能異常等.

此外,還有異常混淆、字串加密混淆、引用混淆等。

對於Java來說,常用的混淆工具如下:

1、Ipa Guard

Ipa Guard是一個免費的 ,Ipa Guard是一款功能強大的ipa混淆工具,不需要ios app原始碼,直接對ipa檔案進行混淆加密。可對IOS ipa 檔案的程式碼,程式碼庫,資原始檔等進行混淆保護。 可以根據設定對函式名、變數名、類名等關鍵程式碼進行重新命名和混淆處理,降低程式碼的可讀性,增加ipa破解反編譯難度。可以對圖片,資源,配置等進行修改名稱,修改md5。只要是ipa都可以,不限制OC,Swift,Flutter,React Native,H5類app。

2、yGuard

yGuard是一款免費的Java混淆器(非開源),它有Java和.NET兩個版本。yGuard 完全免費,基於 Ant 任務執行,提供高可配置的混淆規則。

3、allatori

第二代Java混淆器。所謂第二代混淆器,不僅僅能進行欄位混淆,還能實現流混淆。

程式碼混淆不等於加密

那麼,混淆等同於加密嗎?

答案當然是否定的。

加密顧名思義就是要在我們想要隱藏的東西上上鎖,可以是一道鎖,也可以是多道鎖,而混淆則不同,在進行混淆處理時,資訊將保持原樣,只是以一種模糊的格式呈現出來,因為我們將其複雜性提高到不可能(或幾乎不可能)被理解或解析的程度。

相對於加密而言,則進一步證明了程式碼混淆在防破解方面的高明之處。我們都知道,加密的東西必須解密才能使用,就像一把鎖和一堆鑰匙,總有一把鑰匙可以成功開啟鎖,讓你看到其中的邏輯,但程式碼混淆不同,雖然沒有加密,但程式碼開發者們卻讓逆向工程師們一遍遍在破解的迷宮裡來回轉圈,干擾破解。

這就會導致兩種情況:一種是逆向工程師死磕到底,一種是放棄破解轉而去破解更容易破解的App,從而達到保護App 的效果。

當然,程式碼混淆並不能真正防止逆向工程,只能增加難度,對於安全性要求很高的場景,僅使用程式碼混淆並不能保證原始程式碼的安全。

並且,對於程式碼混淆而言被混淆的程式碼難於理解,因此除錯以及除錯也變得困難起來。開發人員通常需要保留原始的未混淆的程式碼用於除錯。對於支援反射的語言,程式碼混淆有可能與反射發生衝突。

 App 加固非一時之功

正如前文所說,程式碼混淆並不能真正防止逆向工程,總有撥開雲霧的一天,僅使用程式碼混淆並不能保證原始程式碼的安全,也不能完成保證App 加固不被破解,此時就需要多方出手,為App 的防破解環境加築更多城牆。

比如字串加密、控制流平坦化、指令替換、符號混淆、混淆多樣化、不透明謂詞、防動態除錯、防動態注入、HOOK檢測、程式碼段檢驗、完整性校驗等等多種技術手段。

對於App 加固而言,這從來都不是一件簡單的事情,一方有難,八法支援才是保護App 不被破解的良方。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70032199/viewspace-2995656/,如需轉載,請註明出處,否則將追究法律責任。

相關文章