1. 程式人生 > >【技術分享】幾維安全CTO劉柏江:IoT時代LLVM編譯器防護的藝術

【技術分享】幾維安全CTO劉柏江:IoT時代LLVM編譯器防護的藝術

「隨著物聯網時代的開啟,需要解決的安全問題會愈來愈多,而程式碼安全是其他安全方案的底層支撐。面對晶片架構繁多,執行環境複雜的嵌入式物聯網裝置,傳統的程式碼安全方案都將會失效,LLVM編譯器為我們帶來了終極程式碼安全解決方案。」

日前,幾維安全CTO劉柏江在2018 ISC網際網路安全大會“網路安全技術創新及應用論壇”上發表了題為《IoT時代LLVM編譯器防護的藝術》的主題演講。

幾維安全CTO.1.jpg

劉柏江,幾維安全CTO,聯合創始人,KiwiVM的締造者

移動網際網路、萬物網際網路,歸根結底都是硬體組成,軟體驅動。軟體程式碼承載著我們生活的方方面面,利用App打車、購物、支付、聊天等無一不是通過程式碼來實現具體的服務功能。然而由於黑灰產的存在,裸奔的程式碼將會給我們的生活帶來各種糟糕的體驗和危險。尤其是隨著物聯網時代的開啟,需要解決的安全問題會愈來愈多,而程式碼安全是其他安全方案的底層支撐。面對晶片架構繁多,執行環境複雜的嵌入式物聯網裝置,傳統的程式碼安全方案都將會失效,LLVM編譯器為我們帶來了終極程式碼安全解決方案。架構無關、函式粒度、強度可調,堪稱程式碼安全防護的藝術,也是今天要分享的實操性非常強的技術。

萬物互聯,程式碼安全先行

安全圈的同仁們最近幾年都提到一個觀點:萬物互聯,安全先行。但這裡的安全是一個寬泛的概念,它可能是指裝置的物理安全,防止丟失或者被盜;也可能指晶片以及作業系統安全,防止底層漏洞被惡意利用;還可能指物聯網裝置承載的業務安全,防止使用者隱私資料洩漏。

程式碼安全.jpg

這些安全我稱之為策略安全,它們是通過設計完備的規則以及良好的程式碼實現來達到保護的目的。但是這類安全問題我們絕大多數人是遇不到的,它們屬於Intel、ARM、Apple、Google這類晶片和作業系統巨頭公司的考慮範疇。

軟體程式碼是科技公司最寶貴的財富之一,程式碼安全是我們每位IT從業者都可能會遇到的問題,也是很有必要去解決的問題。

程式碼加密能帶來如下好處:第一,防止核心演算法被重構,保護軟體資產;第二,提升策略安全的強度;第三,加大破解難度,延長破解時間,為運營爭取更多的有利視窗期;第四,提高破解成本,將逆向菜鳥拒之門外。

物聯網時代已經來臨

從2007年iPhone的誕生到現在,移動網際網路已趨於成熟,萬物網際網路也已打響軍備競賽,比如Google的Android Things、阿里的AliOS Things,他們都在為新一輪的物聯網平臺佈局。可以預見,未來我們身邊將有數不清的與生活息息相關的智慧終端裝置。作為對策略安全的一個強力補充,程式碼安全也將會繼續為整個生態安全貢獻力量。

晶片體系多

在PC時代,三大主流的桌面作業系統均跑在x86體系下面。而到了移動網際網路時代,我們主要面對的晶片體系是arm,但是arm有thumb、arm、arm64三種不同的指令集,這已經開始有點讓咱們這些做安全和逆向的人感到心力交瘁了。然而到了物聯網時代,鑑於成本、使用場景、效能要求等因素,物聯網裝置所使用的微處理器晶片體系可能會多到讓人難以置信,足以讓安全開發者們癲狂。

執行記憶體小

不像PC或者手機動不動就是幾個G的記憶體容量,物聯網裝置的執行記憶體容量相較PC或手機要小得多的,它們的記憶體可能只有少得可憐的幾十幾百K。

執行環境複雜

物聯網作業系統執行的環境有如下特點:第一,跑在種類繁多的晶片架構上;第二,執行在記憶體一般偏小的環境;第三,受限於功耗硬體效能低下。這些特性給我們做程式碼安全提出了不小的挑戰。在引入我們新型的程式碼加密方案之前,我們先看看歷史方案的做法以及缺陷。

執行環境複雜.jpg

傳統黑盒程式碼加密及侷限

首先,我們科普兩個簡單的概念。黑盒程式碼加密處理的物件是最終的軟體執行體,它們都是以二進位制的方式存在,比如Windows的exe、Android的so以及dex;白盒程式碼加密處理的物件是原始碼,它們都是以文字的方式存在,需要用對應的編譯器才能轉換成二進位制,比如C/C++/Objective-C/Swift原始檔。

黑盒程式碼加密.jpg

黑盒程式碼加密的應用

黑盒程式碼加密的典型應用有四種場景。第一種是加殼,一般是對執行體壓縮或加密,然後執行的時候動態解密,比如適用於Windows、Linux、Android的UPX殼。第二種是加花指令,比如x86架構下面利用指令的可變長特性增加誤導反彙編程式的垃圾指令。第三種是加虛擬機器,這種是直接把對應的指令集轉換成自定義的指令集,比如Windows平臺非常著名的VMProtect,它就是把x86指令集轉碼為私有的指令集格式。第四種是劫持執行時,比如Android平臺的Dex加固就屬於這一類。

黑盒程式碼加密的應用.jpg

黑盒程式碼加密的侷限

從黑盒程式碼加密的實現原理來看,它們針對的作業系統以及晶片架構都是特定於一個很小的集合,這樣帶來一些很明顯的限制和缺陷,一個是可移植性差,另一個是相容性差。可移植性差主要體現在以下兩點:一是很難對多端且同源的程式碼做一致性的保護;二是晶片架構不相容、記憶體需求顯著增加,很難適應新的像IoT這樣的平臺。相容性差主要體現在黑盒方案往往需要干預正常的App執行時(專業的叫法稱之為Hook技術)。但是對於像Android這類高碎片化的平臺,干預執行時意味著很難把方案做到完備;而對於像iOS這類完全封閉的平臺,干預執行時意味著方案沒法工作,因為蘋果基於安全的考慮不允許很多底層的操作比如動態分配程式碼記憶體。

黑盒程式碼加密的侷限.jpg

新型程式碼加密方案 - LLVM編譯器

下面我們看看怎樣利用LLVM來重新定義程式碼安全的實現思路。LLVM是模組化、可複用的編譯器工具鏈集合,它提供了非常完整的API操作介面,可以自定義整個編譯過程。它的編譯流程可以抽象為原始檔通過編譯器前端生成架構無關的IR(IR是中間表示的英文縮寫), 然後被編譯器後端生成架構相關的目標檔案。從這個抽象的編譯流程我們可以看到,架構無關的IR給了我們設計程式碼安全方案的機會。

新型程式碼加密方案.jpg

LLVM-IR的抽象結構

IR的抽象結構如下圖所示,去除一些資料和描述資訊,IR由函式構成,函式由基本塊構成,基本塊由IR指令構成。LLVM提供了完整的IR指令操作API,讓我們可以對IR模組做修改,這是我們基於LLVM編譯器做程式碼安全的基礎和核心,也是我們能克服黑盒方案缺陷的關鍵。

LLVM-IR的抽象結構.jpg

LLVM-IR的潛能

基於LLVM-IR做程式碼安全能帶來的好處眾多且方案的設計思路靈活,它能完美的處理移動網際網路和物聯網作業系統環境下的程式碼安全問題。第一,在架構無關的IR級別做防護,可以適應任意晶片架構;第二,能做到以函式為單位進行防護,可以適應低記憶體執行環境;第三,可以根據不同的需求,定製化實現不同級別的安全防護。

基於LLVM編譯器的程式碼安全方案

初級防護 - 混淆編譯器

Obfuscator-LLVM,這是2013年開源的一個混淆編譯器,也是我們國產安全編譯器的鼻祖。很多友商的安全編譯器都是從這個專案衍生而來。它能實現程式碼膨脹、塊亂序等功能。

初級防護-混淆編譯器.jpg

這是兩張彙編程式碼反編譯流程圖 ,圖中的白色部分代表著一個最小單位的指令塊。左邊是正常的流程圖,右邊是混淆之後的流程圖。從流程圖中我們可以看到,混淆之後把程式碼量增大了,執行邏輯也做了轉換。從逆向分析的角度看,程式碼量的增加在一定程度提高了逆向的難度。但由於這個方案比較初級,因此強度不是很高,現在也已經有了針對混淆的自動化反混淆指令碼。

高階防護 - 塊排程編譯器

Obfuscator-LLVM給了我們一個好的開頭,同時也是一個重要的啟示。基於LLVM,我們還能做得更多。從逆向分析的角度看,只要函式邏輯是連貫的,那麼我們總是可以做分析,不管你如何膨脹,程式碼就在那裡。所以,切斷函式邏輯,是一個程式碼防護的方向。基於該方向的思考,我們做出了塊排程編譯器,它完美的掐斷了原始函式的邏輯,讓逆向的人沒法分析。

高階防護-塊排程編譯器.jpg

塊排程編譯器的實現原理是這樣的,比如一個函式裡面有三個基本的程式碼塊A、B、C,A執行完成之後會根據不同的條件跳轉到B或者C。正常的執行流程我們通過專業的反編譯程式可以一眼就能看出這三者的邏輯關係,進而分析它的實現原理將變得易如反掌。而塊排程呢,會把A跳轉到B或者C這個跳轉過程加密,這樣出來的效果呢就像右邊的圖一樣,各個基本的關鍵程式碼塊成為了彼此獨立的實體,靜態反編譯工具將沒法做程式碼的連續性分析,這將使得逆向分析無法進行。另外,塊排程還會把函式呼叫加密,那麼我們常用的通過函式呼叫了哪些函式來猜測函式邏輯將變得不可能。因此,塊排程的強度遠遠高於普通的混淆,如果將混淆和塊排程疊加使用,那麼效果將會出奇的好,讓逆向分析的人無比痛苦。

旗艦防護 - KiwiVM程式碼虛擬化

一直以來,在外掛、反外掛最激烈的Windows網路遊戲攻防戰場,虛擬機器防護往往是最後一道防線,也是強度最高的一道防線。高水平的逆向分析者往往需要花費數月甚至數年才能大致搞明白被虛擬機器保護的程式碼,而一般的逆向分析者幾乎沒法展開虛擬機器的分析。因此,虛擬機器是程式碼安全的最高堡壘。

作為國內專業的白盒程式碼安全方案提供商,幾維安全於2016年就基於LLVM研發出了全平臺全架構支援的程式碼虛擬化產品KiwiVM。它小巧精緻,不僅適用於移動網際網路,同時也天生適應物聯網,這是基於LLVM的頂級藝術品。

由於LLVM-IR的平臺無關性,因此KiwiVM也能平臺無關的實現函式級的虛擬化,可以在效能和安全兩方面取得良好的平衡。KiwiVM程式碼虛擬化屬於靜態程式碼加密技術,一旦成功虛擬化,配合虛擬CPU的執行時即可完整的實現原始程式碼的功能,不存在干預執行時的Hook操作,因此相容性可以達到100%。

旗艦防護-KiwiVM程式碼虛擬化.jpg

KiwiVM的中心思想是利用LLVM-IR編碼成自定義虛擬CPU的指令集和元資料,包括指令集資料、重定位資料、函式呼叫簽名資料等。轉換過程是原始碼轉原始碼,比如C/C++/ObjC原始碼通過LLVM前端編譯為BC檔案(IR模組的載體),然後KiwiVM核心演算法把該BC檔案做自定義的編碼生成功能等價的標準C原始碼檔案,最後再編譯為目標平臺需要的二進位制檔案。前面我們提到物聯網裝置的晶片可能會是非常冷門的,甚至其編譯工具鏈都是完全私有定製的,和常規的GCC交叉工具鏈都不一樣。面對這種冷門環境,由於KiwiVM擁有原始碼轉原始碼的能力,所以可以完美的相容它的程式碼安全需求。

KiwiVM程式碼虛擬化.jpg

原始函式被虛擬化之後程式碼邏輯完全變為單一的虛擬機器入口,不管多麼複雜的函式成功虛擬化之後,最終出來都是這樣一個無比“單純”的白板。

結語

至此,我們分享了基於LLVM編譯器做的不同防護級別的三種程式碼安全方案。從下圖我們可以清楚的看出混淆、塊排程、程式碼虛擬化三者之間的區別。

區別.jpg

幾維安全已經在LLVM編譯器程式碼安全方面有了完整的產品佈局,所有的安全編譯器產品都支援iOS、Android、IoT三大平臺。

產品佈局.jpg

其中初級防護產品混淆編譯器能實現程式碼膨脹、亂序執行、字串加密等功能。高階防護產品塊排程編譯器能實現邏輯斷鏈、函式呼叫隱藏、字串加密等功能,並且可以和混淆編譯器疊加使用,強度更高。幾維安全旗艦防護產品程式碼虛擬化編譯器能實現虛擬CPU執行,完全隱藏函式邏輯,讓逆向工程徹底無法進行。