標籤:

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

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

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

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

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

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

萬物互聯,代碼安全先行

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

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

軟體代碼是科技公司最寶貴的財富之一,代碼安全是我們每位IT從業者都可能會遇到的問題,也是很有必要去解決的問題。代碼加密能帶來如下好處:第一,防止核心演算法被重構,保護軟體資產;第二,提升策略安全的強度;第三,加大破解難度,延長破解時間,為運營爭取更多的有利窗口期;第四,提高破解成本,將逆向菜鳥拒之門外。

物聯網時代已經來臨

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

晶元體系多

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

運行內存小

不像PC或者手機動不動就是幾個G的內存容量,物聯網設備的運行內存容量相較PC或手機要小得多的,它們的內存可能只有少得可憐的幾十幾百K。

運行環境複雜

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

傳統黑盒代碼加密及局限

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

黑盒代碼加密的應用

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

黑盒代碼加密的局限

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

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

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

LLVM-IR的抽象結構

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

LLVM-IR的潛能

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

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

初級防護 - 混淆編譯器

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

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

高級防護 - 塊調度編譯器

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

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

旗艦防護 - KiwiVM代碼虛擬化

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

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

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

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

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

結語

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

幾維安全已經在LLVM編譯器代碼安全方面有了完整的產品布局,所有的安全編譯器產品都支持iOS、Android、IoT三大平台。

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


推薦閱讀:

「譯」Liftoff:全新的 WebAssembly 編譯器
編譯器與解釋器的區別和工作原理
如何選擇IR filter
5分鐘入門CTS-嘗鮮中文版TypeScript
windows下安裝,配置gcc編譯器

TAG:編譯器 | LLVM | CTO |