王慶豐,梁浩,王亞文,謝根琳,何本偉
基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞構(gòu)造方法
王慶豐,梁浩,王亞文,謝根琳,何本偉
(信息工程大學(xué)信息技術(shù)研究所,河南 鄭州 450001)
隨著軟件功能的日趨復(fù)雜和網(wǎng)絡(luò)攻擊技術(shù)的不斷演進(jìn),軟件盜版、軟件破解、數(shù)據(jù)泄露、軟件惡意修改等惡意行為呈上升趨勢,軟件安全問題逐漸成為行業(yè)領(lǐng)域普遍關(guān)注的焦點(diǎn)和研究方向。代碼混淆是一種典型的對抗逆向工程的軟件保護(hù)技術(shù),它能夠在保持程序原有功能不變的條件下加大攻擊者對程序進(jìn)行分析和理解的難度,被廣泛應(yīng)用和深入研究?,F(xiàn)有的代碼混淆技術(shù)大多由于追求混淆效果而普遍存在性能損耗偏高、隱蔽性差等問題。控制結(jié)構(gòu)混淆是代碼混淆技術(shù)中應(yīng)用較廣泛的一種,它通過擾亂程序的控制流從而提高代碼逆向工程難度,不透明謂詞混淆是其一大分支。為了彌補(bǔ)現(xiàn)有代碼混淆技術(shù)的缺陷,提出了基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞構(gòu)造方法,利用計(jì)算機(jī)浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算過程中伴隨的精度損失現(xiàn)象使特定條件下產(chǎn)生與常理相悖的運(yùn)算結(jié)果,通過選擇若干個(gè)小數(shù)進(jìn)行強(qiáng)制類型轉(zhuǎn)換、加法運(yùn)算和乘法運(yùn)算,基于其運(yùn)算結(jié)果統(tǒng)計(jì)可以構(gòu)造一系列不透明謂詞,實(shí)現(xiàn)代碼混淆功能。相較于傳統(tǒng)的不透明謂詞,該構(gòu)造方法具有隱蔽性高、通用性好、可逆性、開銷低等優(yōu)點(diǎn)。實(shí)驗(yàn)驗(yàn)證表明,該方法在大幅降低攻擊者對軟件進(jìn)行逆向工程等工作速度的同時(shí),對于符號執(zhí)行等動(dòng)態(tài)分析技術(shù)具有良好的抵御性能。
代碼混淆;虛假控制流;不透明謂詞;浮點(diǎn)數(shù)運(yùn)算
隨著信息技術(shù)的發(fā)展,軟件的應(yīng)用領(lǐng)域越來越廣泛、功能越來越豐富、復(fù)雜性越來越高、市場規(guī)模越來越大。軟件行業(yè)規(guī)模的擴(kuò)大不可避免地引入更多的軟件缺陷,根據(jù)奇安信發(fā)布的《2022中國軟件供應(yīng)鏈安全分析報(bào)告》[1],每1 000行代碼就有超過6個(gè)安全缺陷。與此同時(shí),信息技術(shù)的發(fā)展讓更多的人接觸到計(jì)算機(jī)與網(wǎng)絡(luò)技術(shù),這間接導(dǎo)致發(fā)起攻擊的門檻降低。軟件帶來便利的同時(shí),人們的工作與生活、社會的正常運(yùn)轉(zhuǎn)等對軟件的依賴程度越來越高,相應(yīng)地,攻擊者造成的軟件安全問題所產(chǎn)生的危害越來越大。以軟件盜版為例,全球范圍內(nèi)未經(jīng)授權(quán)軟件約占個(gè)人計(jì)算機(jī)軟件的37%,其總價(jià)值超過460億美元[2]。
對軟件的攻擊催生出眾多軟件保護(hù)技術(shù),根據(jù)實(shí)現(xiàn)方式的不同可以分為基于硬件的保護(hù)技術(shù)和基于軟件的保護(hù)技術(shù)[3],基于軟件的保護(hù)技術(shù)主要有軟件水印、篡改防護(hù)、數(shù)據(jù)銷毀、代碼混淆。其中,代碼混淆是一種典型的對抗逆向工程的軟件保護(hù)技術(shù),它可以通過重寫代碼中的部分邏輯或者修改標(biāo)識符名稱等實(shí)現(xiàn),在保持程序原有功能不變的條件下對其進(jìn)行修改,加大攻擊者對程序進(jìn)行分析和理解的難度[4],已被廣泛應(yīng)用。圍繞代碼混淆的研究主要集中在控制結(jié)構(gòu)混淆,許多研究成果處于理論階段,相關(guān)的新技術(shù)往往忽視了實(shí)用性、通用性以及性能損耗而導(dǎo)致難以推廣。
針對已有的基于不透明謂詞的代碼混淆技術(shù)面臨構(gòu)造復(fù)雜、性能損失較大、不能抵抗符號執(zhí)行代碼分析技術(shù)等問題,本文提出基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞構(gòu)造方法,主要貢獻(xiàn)如下。
1) 提出一種通過浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞構(gòu)造方法。
2) 以浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算為理論基礎(chǔ)構(gòu)造不透明謂詞,以此為基礎(chǔ)完成虛假控制流實(shí)驗(yàn),并從強(qiáng)度、耐受性、開銷、隱蔽性、通用性、可逆性,以及能否抵抗符號攻擊7個(gè)方面進(jìn)行評估。
二進(jìn)制代碼是一種重要的計(jì)算機(jī)軟件存在形式,也是非常普遍的軟件分發(fā)形式。攻擊者發(fā)起攻擊在很大程度上依賴于對軟件有充分的理解和分析,這要求攻擊者必須對二進(jìn)制代碼進(jìn)行逆向工程。Collberg等[5]闡述了代碼混淆的概念,他們對代碼混淆技術(shù)進(jìn)行了系統(tǒng)性的總結(jié)分類,并通過強(qiáng)度、耐受性和開銷3個(gè)方面對代碼混淆質(zhì)量進(jìn)行評估。
根據(jù)處理目標(biāo)的不同,代碼混淆可以分為源代碼混淆、中間代碼混淆、字節(jié)碼混淆、二進(jìn)制代碼混淆等。根據(jù)代碼混淆原理的不同,代碼混淆可以分為外形混淆、控制結(jié)構(gòu)混淆、數(shù)據(jù)混淆、預(yù)防混淆等。其中,控制結(jié)構(gòu)混淆是代碼混淆技術(shù)中應(yīng)用最廣泛的一種,其目的是使攻擊者難以理解程序的控制流。常見的控制結(jié)構(gòu)混淆技術(shù)包括虛假控制流[6]、控制流扁平化[7]、代碼虛擬化[8-12]、不透明謂詞[13-14]等。
不透明謂詞是指在混淆時(shí)插入一些條件控制語句,其中,由軟件開發(fā)者控制的條件表達(dá)式邏輯上恒真或者恒假,然而攻擊者難以判斷條件表達(dá)式的值。例如,對于任意整數(shù),條件表達(dá)式“(+1)%2==0”恒成立,但是攻擊者無法枚舉取值范圍內(nèi)的每一個(gè)值,無法簡單得出該條件表達(dá)式恒成立的結(jié)論。不透明謂詞可以與多項(xiàng)控制結(jié)構(gòu)混淆技術(shù)結(jié)合,在控制結(jié)構(gòu)混淆中占有重要地位。不透明謂詞的質(zhì)量直接決定了控制結(jié)構(gòu)混淆的實(shí)際效果。
常用的不透明謂詞往往基于簡單的代理定理和邏輯規(guī)則,如“(+1)%2==0”恒成立,其構(gòu)造簡單,運(yùn)行開銷低,因此被廣泛應(yīng)用。然而,這類簡單的不透明謂詞有助于抵抗靜態(tài)分析,但對于越來越多的反混淆手段卻束手無策。因此,出現(xiàn)了更多的不透明謂詞構(gòu)造方法,大致可以分為基于困難問題的不透明謂詞、基于密碼學(xué)的不透明謂詞和基于復(fù)雜代數(shù)運(yùn)算的不透明謂詞。
Collberg等[13]提出基于別名分析問題以及并發(fā)分析問題的不透明謂詞。其中,基于別名分析問題的不透明謂詞首先構(gòu)造一個(gè)復(fù)雜的動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu),再構(gòu)造一些指針指向這個(gè)數(shù)據(jù)結(jié)構(gòu)中的元素,然后向程序代碼中插入代碼來編輯這個(gè)數(shù)據(jù)結(jié)構(gòu)。在編輯時(shí)需要維護(hù)一些不變的性質(zhì),這些性質(zhì)即不透明謂詞的本質(zhì)。后者原理與前者類似,區(qū)別在于編輯數(shù)據(jù)結(jié)構(gòu)的代碼位于并發(fā)執(zhí)行的線程中。Moser等[15]提出基于3SAT(3-satisfiability)問題的不透明謂詞構(gòu)造方法,該方法通過將程序中的個(gè)布爾變量構(gòu)造成一個(gè)困難問題,從而構(gòu)造出一個(gè)值恒定的表達(dá)式作為不透明謂詞,假設(shè)攻擊者必須先解決3SAT問題才能反混淆不透明謂詞,則其反混淆難度為解決NP困難問題的難度。但是Sheridan等[4]指出Moser等的方法所依賴的假設(shè)并不成立,攻擊者可以基于啟發(fā)式檢測策略來識別并反混淆此類不透明謂詞。Tiella等[16]基于NP困難問題中的分團(tuán)問題實(shí)現(xiàn)構(gòu)造不透明謂詞,此類不透明謂詞破解難度依賴于問題規(guī)模,而構(gòu)造大規(guī)模問題將導(dǎo)致性能損耗嚴(yán)重,實(shí)用性差。此外,當(dāng)NP問題不是最壞情況時(shí),計(jì)算復(fù)雜度會降低,相應(yīng)的安全性也會降低。
Sharif等[17]提出一種基于密碼學(xué)哈希函數(shù)的不透明謂詞構(gòu)造方法,把程序中常量與變量之間的相等判斷轉(zhuǎn)換為經(jīng)過哈希函數(shù)之后常量與變量的比較,并與對稱加密算法聯(lián)合起來,實(shí)現(xiàn)了高強(qiáng)度的密碼隱藏,該方法安全性高,但開銷較大,且通用性較差。Zhu等[18]提出基于余數(shù)系統(tǒng)的同態(tài)性來混淆代碼中的整數(shù)運(yùn)算。這兩種方法安全性較高,但同樣不具備通用性。
Arboit等[19]提出利用二次剩余構(gòu)造不透明謂詞簇,該方法沒有考慮到不透明謂詞的彈性,且密碼安全性較差。袁征等[14]基于同余方程生成不透明謂詞,同二次剩余構(gòu)造方法一樣,這種不透明謂詞容易受到符號執(zhí)行攻擊,且運(yùn)算構(gòu)造復(fù)雜。Wang等[20]提出基于考拉茲猜想的不透明謂詞構(gòu)造方法,利用符號執(zhí)行容易引起路徑爆炸的缺陷,降低符號執(zhí)行反混淆的效率,該方法同樣靈活性差,容易受到特征匹配攻擊。付蒙[21]提出基于置換函數(shù)的單射性的不透明謂詞構(gòu)造方法,通過使用比特向量上的置換函數(shù),再結(jié)合函數(shù)復(fù)合的性質(zhì),可以構(gòu)造關(guān)于置換函數(shù)單射性的恒等式,即不透明謂詞,該方法構(gòu)造簡單,運(yùn)行高效,可以作為備選的不透明謂詞構(gòu)造方法。
符號執(zhí)行[22]是一種軟件分析技術(shù),也是較為流行的研究方向,在軟件測試等領(lǐng)域具有較好的應(yīng)用場景。Ming等[23]提出符號執(zhí)行與邏輯推理結(jié)合來反混淆,采用不透明謂詞的代碼混淆后的二進(jìn)制程序。該方案通過動(dòng)態(tài)二進(jìn)制插樁平臺獲取程序執(zhí)行時(shí)的匯編指令并用符號執(zhí)行框架對其進(jìn)行分析,對程序中的每個(gè)謂詞進(jìn)行反向切片,生成執(zhí)行到謂詞所在路徑的約束條件,最終通過約束求解和邏輯推理即可正確識別不透明謂詞。針對只含有簡單路徑約束的不透明謂詞,該方法能實(shí)現(xiàn)零誤報(bào)率的不透明謂詞檢測,且運(yùn)行效率高。Yadegari等[24]提出基于污點(diǎn)分析和符號執(zhí)行的反混淆技術(shù)。Bardin等[25]提出有限后向動(dòng)態(tài)符號執(zhí)行來反混淆不透明謂詞混淆。以上基于符號執(zhí)行的代碼反混淆受限于約束求解器,無法應(yīng)對含有復(fù)雜路徑約束的代碼混淆。隨著以符號執(zhí)行的動(dòng)態(tài)分析技術(shù)應(yīng)用于代碼反混淆,能抵抗符號執(zhí)行攻擊的代碼混淆技術(shù)研究逐漸增多。例如,Banescu等[26]提出抵抗符號執(zhí)行攻擊的代碼混淆方法能夠?qū)⒎枅?zhí)行攻擊的速度降低4個(gè)數(shù)量級,但這種方法只能用于混淆循環(huán)語句,實(shí)用性較低。
綜上,基于困難問題的不透明謂詞往往混淆程序高、隱蔽性好,但是構(gòu)造復(fù)雜、開銷較大、難以與原生代碼融合?;诿艽a學(xué)的不透明謂詞安全性較高,但不具備通用性?;趶?fù)雜代數(shù)運(yùn)算的不透明謂詞往往靈活性較差,容易受到軟件動(dòng)態(tài)分析技術(shù)攻擊以及特征匹配攻擊。
常用的數(shù)字包括整數(shù)和分?jǐn)?shù),兩者的集合稱為有理數(shù)。其中整數(shù)可以看作分母為1的分?jǐn)?shù),因此可以說有理數(shù)由分?jǐn)?shù)組成。有理數(shù)既可以用分?jǐn)?shù)表示,又可以用小數(shù)表示,其中小數(shù)分為有限小數(shù)和無線循環(huán)小數(shù)。任意分?jǐn)?shù)一定可以轉(zhuǎn)換為有限小數(shù)或無線循環(huán)小數(shù),反之亦然[27]。全體有理數(shù)的集合為有理數(shù)集,它是無限集合。將有理數(shù)按照大小進(jìn)行排序后,任意兩個(gè)有理數(shù)之間必然存在其他有理數(shù),即有理數(shù)具有稠密性。借助數(shù)軸來理解這一概念,數(shù)軸上任意兩個(gè)點(diǎn)相連形成一個(gè)線段,無論這條線段有多短,在其上一定能找到一個(gè)新的有理數(shù)。
浮點(diǎn)類型是編程語言中一種基本數(shù)據(jù)類型,高級語言中浮點(diǎn)類型的存儲方式源自1985年出現(xiàn)的IEEE-754標(biāo)準(zhǔn)。根據(jù)該標(biāo)準(zhǔn),一個(gè)二進(jìn)制浮點(diǎn)數(shù)由符號位、指數(shù)位以及尾數(shù)部分組成。
高級編程語言在設(shè)計(jì)基本數(shù)據(jù)類型時(shí)往往需要平衡取值范圍和所占用的存儲空間。在C語言中,float數(shù)據(jù)類型在內(nèi)存中的存儲共占用4 byte,其中指數(shù)位占用8 bit,尾數(shù)部分占用23 bit。double數(shù)據(jù)類型在內(nèi)存中的存儲共占用8 byte,其中指數(shù)部分占用11 bit,尾數(shù)部分占用52 bit。因此float數(shù)據(jù)類型理論上最多能表達(dá)232個(gè)數(shù)字,而double數(shù)據(jù)類型理論上最多能表達(dá)264個(gè)數(shù)字,即無論是float還是double數(shù)據(jù)類型都只能表示有限個(gè)數(shù)字,且精度是有限的。float和double數(shù)據(jù)類型有限的精度導(dǎo)致其在運(yùn)算過程中可能出現(xiàn)嚴(yán)重的錯(cuò)誤。
float和double數(shù)據(jù)類型表示數(shù)據(jù)的范圍是有限的,而有理數(shù)是無限集合,每一個(gè)float或double類型變量都對應(yīng)無數(shù)個(gè)有理數(shù),它們的分布范圍可以表示為(?e1,+e2),其中e1和e2都是非常小的值。任意兩個(gè)不等的(?e1,+e2)范圍內(nèi)的變量1和2使用float數(shù)據(jù)類型表達(dá)后是相等的。如果其中一個(gè)數(shù)字位于邊界附近,那么一點(diǎn)小小的擾動(dòng)就可能導(dǎo)致其落在(?e1,+e2)范圍外。以十進(jìn)制小數(shù)舉例,假設(shè)一個(gè)數(shù)據(jù)類型只有2個(gè)有效的小數(shù)位,所有在[1.665,1.674)范圍內(nèi)的數(shù)字經(jīng)過四舍五入都等于1.67,但是0.001的變量就可以讓1.674四舍五入變成1.68。
浮點(diǎn)數(shù)運(yùn)算出現(xiàn)精度損失主要有兩個(gè)原因:①強(qiáng)制類型轉(zhuǎn)換,double類型變量轉(zhuǎn)float類型會損失精度;②浮點(diǎn)數(shù)數(shù)學(xué)運(yùn)算,如0.1加0.6得到的實(shí)際計(jì)算結(jié)果不等于0.7(不完全相等)。由于浮點(diǎn)數(shù)表示一個(gè)范圍內(nèi)的有理數(shù),所以出現(xiàn)精度損失并不意味著計(jì)算結(jié)果一定出現(xiàn)錯(cuò)誤。只有經(jīng)過計(jì)算才可以確定某個(gè)或某幾個(gè)浮點(diǎn)數(shù)經(jīng)過類型轉(zhuǎn)換或運(yùn)算后的計(jì)算結(jié)果是否與邏輯上的計(jì)算結(jié)果相等。因此,可以將浮點(diǎn)數(shù)的類型轉(zhuǎn)換或運(yùn)算作為一種不透明謂詞引入代碼混淆。接下來用兩個(gè)例子說明。
如圖1所示,定義double類型變量double1并給double1賦值0.1,然后定義float類型變量float1,隨后將變量double1賦值給變量float1,最后將float1賦值給double類型變量double2。此時(shí)的變量double1和double2的值在邏輯上是相等的,而且輸出到控制臺的結(jié)果都是0.10000。然而以二進(jìn)制格式打印的double1結(jié)果是0, 01111111011, 100110011001100110011001100110 0110011001100110011010,以二進(jìn)制格式打印的double2結(jié)果是0, 01111111011, 10011001100110 01100110100000000000000000000000000000,所以變量double1的值小于變量double2。通過仔細(xì)觀察整個(gè)過程,可以發(fā)現(xiàn)在將double1賦值給float1時(shí)發(fā)生了尾數(shù)截?cái)嗖⑦M(jìn)1,因此在這個(gè)過程中浮點(diǎn)數(shù)的值變大。
圖1 浮點(diǎn)數(shù)類型轉(zhuǎn)換精度損失示意
Figure 1 Illustration of the loss of precision in floating-point type conversion
圖2 浮點(diǎn)數(shù)加法計(jì)算結(jié)果偏差示意
Figure 2 Illustration of the deviation of the result of floating-point addition calculation
如圖2和圖3所示,定義3個(gè)float類型變量float1、float2、float3,并分別給它們賦值0.1、0.6、0.7。再定義一個(gè)float類型變量float_sum,并將float1和float2相加的結(jié)果賦值給它。此時(shí)的float_sum和float3邏輯上是相等的,而且輸出到控制臺的結(jié)果都是0.70000。然而,以二進(jìn)制格式打印的float_sum結(jié)果是0, 01111110, 01100110011001100110100,其計(jì)算過程如圖2所示,0.1的尾數(shù)計(jì)算時(shí)需要移位4次,0.6和0.7的尾數(shù)計(jì)算時(shí)需要移位1位,因此移位相差3位,尾數(shù)截?cái)鄷r(shí)發(fā)生了進(jìn)1,如圖3所示。以二進(jìn)制格式打印的float3結(jié)果是0, 01111110, 01100110011001100110011,所以float_sum的值大于float3。
圖3 浮點(diǎn)數(shù)加法計(jì)算結(jié)果偏差原理示意
Figure 3 Illustration of the principle of deviation of the result of floating-point addition calculation
根據(jù)上述計(jì)算過程中觀察到的現(xiàn)象,可以對若干浮點(diǎn)數(shù)對進(jìn)行加法和乘法運(yùn)算,并統(tǒng)計(jì)其結(jié)果用作后續(xù)浮點(diǎn)數(shù)運(yùn)算。如表1和表2所示,分別是0.1到0.9這9個(gè)數(shù)字進(jìn)行加法和乘法運(yùn)算后實(shí)際結(jié)果和邏輯結(jié)果比較。例如,表1中0.1對應(yīng)的行和0.6對應(yīng)的列(第一行第六列的)“>”符號表示在計(jì)算機(jī)浮點(diǎn)數(shù)運(yùn)算中,0.1+0.6的計(jì)算結(jié)果大于其理論值0.7。
表1 浮點(diǎn)數(shù)加法運(yùn)算結(jié)果示例
表2 浮點(diǎn)數(shù)乘法運(yùn)算結(jié)果示例
在驗(yàn)證浮點(diǎn)數(shù)類型轉(zhuǎn)換與運(yùn)算構(gòu)造不透明謂詞構(gòu)造可行后,可以通過算法使其工程化。首先構(gòu)造浮點(diǎn)數(shù)加法運(yùn)算、乘法運(yùn)算的浮點(diǎn)數(shù)對,這些浮點(diǎn)數(shù)對滿足計(jì)算結(jié)果與邏輯值不等。此外,需要收集滿足浮點(diǎn)數(shù)類型轉(zhuǎn)換后精度損失明顯的浮點(diǎn)數(shù)。在完成準(zhǔn)備工作后,即可開始不透明謂詞混淆。首先收集可以進(jìn)行不透明謂詞混淆的點(diǎn),然后決定采用哪一種浮點(diǎn)數(shù)混淆方式,并進(jìn)行混淆。具體代碼混淆原理如圖4所示的虛假控制流示意,每一個(gè)順序執(zhí)行的基本塊都可以作為不透明謂詞混淆的點(diǎn),在它前面插入一個(gè)if語句,浮點(diǎn)數(shù)類型轉(zhuǎn)換與運(yùn)算不透明謂詞作為if語句的判斷條件,使原順序執(zhí)行的基本塊作為條件為真的跳轉(zhuǎn)分支,再構(gòu)造一個(gè)虛假的基本塊作為條件恒假的跳轉(zhuǎn)分支。經(jīng)過虛假控制流處理后的基本塊控制流結(jié)構(gòu)明顯比原基本塊復(fù)雜,這將極大增加對代碼進(jìn)行逆向分析的難度。
圖4 虛假控制流示意
Figure 4 Illustration of bogus control flow
基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞混淆算法如算法1所示。
算法1 基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞混淆算法
輸入 待混淆的LLVM中間代碼target_code
輸出 混淆后的LLVM中間代碼result_code
開始
1) Add_Array={<1,2>, <3,4>, ...}; // 構(gòu)造浮點(diǎn)數(shù)加法參數(shù)
2) Multi_Array={<1,2>, <3,4>, ...}; // 構(gòu)造浮點(diǎn)數(shù)乘法參數(shù)
3) Cast_Array={1,2,3,4, ...}; // 構(gòu)造浮點(diǎn)數(shù)類型轉(zhuǎn)換參數(shù)
4) ...
5) EntryPoint_Array=Get_EP(target_code); // 找出所有的不透明謂詞插入點(diǎn)
6) for each entrypoint in Entrypoint // 遍歷所有的插入點(diǎn)
7) if Execute_Insert(rand_number) // 根據(jù)概率決定是否執(zhí)行插入
8) if Select_Add() // 選擇浮點(diǎn)數(shù)加法作為不透明謂詞
9) Execute_Add(Add _Array);
10) else if Select _Multi() // 選擇浮點(diǎn)數(shù)乘法作為不透明謂詞
11) Execute_Multi(Multi _Array);
12) else // 選擇浮點(diǎn)數(shù)類型轉(zhuǎn)換作為不透明謂詞
13) Execute_Cast(Cast _Array);
14) end if
15) end if
16) end for each
17) end
本節(jié)對提出的基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞構(gòu)造方法進(jìn)行實(shí)驗(yàn)和評估。實(shí)驗(yàn)圍繞6個(gè)基準(zhǔn)測試程序進(jìn)行基準(zhǔn)測試,對每一個(gè)基準(zhǔn)測試程序源代碼,將其源代碼編譯成4個(gè)版本的可執(zhí)行文件?;鶞?zhǔn)測試包括程序執(zhí)行時(shí)間、程序大小、程序相似度比較。完成基準(zhǔn)測試后,根據(jù)基準(zhǔn)測試結(jié)果從安全性、高效性、隱蔽性、通用性4個(gè)方面對提出的基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞構(gòu)造方法進(jìn)行評估。
在實(shí)驗(yàn)展開之前,需要完成實(shí)驗(yàn)準(zhǔn)備工作,包括實(shí)驗(yàn)環(huán)境構(gòu)建和基準(zhǔn)測試程序修改。實(shí)驗(yàn)環(huán)境包括程序編譯執(zhí)行環(huán)境和程序相似度比較環(huán)境,兩個(gè)環(huán)境均通過虛擬機(jī)實(shí)現(xiàn)。程序編譯執(zhí)行環(huán)境安裝ubuntu20.04操作系統(tǒng),為其分配4 GB內(nèi)存和20 GB磁盤。最后在該環(huán)境中安裝LLVM12.0.1,用它編譯基準(zhǔn)測試程序。LLVM項(xiàng)目是模塊化、可重用編譯器和工具鏈技術(shù)的集合。開發(fā)人員可以借助LLVM將C++代碼編譯成LLVM中間代碼,并在中間代碼的基礎(chǔ)上進(jìn)行代碼優(yōu)化,最后生成二進(jìn)制文件。程序相似度比較環(huán)境安裝Windows10操作系統(tǒng),為其分配4 GB內(nèi)存和60 GB磁盤,最后在該環(huán)境中安裝IDA pro7.5和BinDiff5.0用于測量程序相似度?;鶞?zhǔn)測試程序的源代碼默認(rèn)采用gcc進(jìn)行編譯,因此需要給它們重新編寫采用LLVM編譯的Makefile來生成實(shí)驗(yàn)需要的可執(zhí)行文件。
IDA pro(簡稱IDA)是Hex-Rays公司出品的一款靜態(tài)反編譯軟件,在程序分析過程中發(fā)揮著舉足輕重的作用。IDA pro是交互式的、可編程的、可擴(kuò)展的、多處理器的,支持Windows/Linux/ macOS等平臺文件格式。IDA pro已經(jīng)成為分析惡意代碼的標(biāo)準(zhǔn)和攻擊研究領(lǐng)域的重要工具。BinDiff是一個(gè)二進(jìn)制文件比較工具,可以協(xié)助安全研究人員和工程師快速定位反匯編代碼中的差異和相似之處。BinDiff最早由Zynamics公司開發(fā),該公司2011年被谷歌公司收購,隨后谷歌將BinDiff融入許多內(nèi)部文件分析系統(tǒng)中,利用其二進(jìn)制對比技術(shù)追蹤惡意程序家族。BinDiff還可以用于識別供應(yīng)商提供的修補(bǔ)程序中的漏洞,分析多個(gè)版本相同的二進(jìn)制數(shù)據(jù),鑒別代碼被盜以及專利侵權(quán)的證據(jù)收集等。
基準(zhǔn)測試程序包括bzip2、mcf、gobmk、sjeng、lbm、sphinx3。對于每一個(gè)基準(zhǔn)測試程序源代碼,采用LLVM編譯環(huán)境編譯得到4個(gè)版本的可執(zhí)行文件:原始可執(zhí)行文件、虛假控制流混淆處理后的可執(zhí)行文件、采用浮點(diǎn)數(shù)運(yùn)算作為不透明謂詞的虛假控制流混淆處理后的可執(zhí)行文件、采用浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算作為不透明謂詞的虛假控制流混淆處理后的可執(zhí)行文件。在完成編譯的基礎(chǔ)上,統(tǒng)計(jì)這些程序的文件大小、執(zhí)行時(shí)間,以及兩種虛假控制流程序與原始程序的相似度比較。
3.1.1 基準(zhǔn)測試程序的運(yùn)行時(shí)間
本節(jié)采用time命令測量基準(zhǔn)測試程序運(yùn)行時(shí)間,為了減小誤差,將每一個(gè)可執(zhí)行文件執(zhí)行10次取其平均值作為其運(yùn)行時(shí)間。表3為基準(zhǔn)測試程序的運(yùn)行時(shí)間,其中每一列包含指定基準(zhǔn)測試程序運(yùn)行時(shí)間。4行數(shù)據(jù)分別表示origin、origin+ bcf1、origin+bcf2、origin+bcf3這4個(gè)版本的基準(zhǔn)測試程序數(shù)據(jù),其中origin表示直接編譯基準(zhǔn)測試程序得到的可執(zhí)行文件,origin+bcf1表示采用基準(zhǔn)測試程序經(jīng)過示例虛假控制流混淆處理后的可執(zhí)行文件,origin+bcf2表示基準(zhǔn)測試程序經(jīng)過采用浮點(diǎn)數(shù)運(yùn)算作為不透明謂詞的虛假控制流混淆處理后的可執(zhí)行文件,origin+bcf3表示基準(zhǔn)測試程序經(jīng)過采用浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算作為不透明謂詞的虛假控制流混淆處理后的程序。每一個(gè)版本的基準(zhǔn)測試程序運(yùn)行時(shí)間信息包括real time、user time和sys time,三者分別表示程序?qū)嶋H運(yùn)行時(shí)間、程序用戶態(tài)運(yùn)行時(shí)間、程序系統(tǒng)態(tài)運(yùn)行時(shí)間。通過表3的數(shù)據(jù)可知:用戶態(tài)運(yùn)行時(shí)間加上系統(tǒng)態(tài)運(yùn)行時(shí)間略小于程序?qū)嶋H運(yùn)行時(shí)間;基準(zhǔn)測試程序4個(gè)版本的可執(zhí)行文件的系統(tǒng)態(tài)運(yùn)行時(shí)間基本一致;所有基準(zhǔn)測試程序的4個(gè)可執(zhí)行文件運(yùn)行時(shí)間大小均滿足origin 表3 基準(zhǔn)測試程序運(yùn)行時(shí)間 3.1.2 基準(zhǔn)測試程序的可執(zhí)行文件大小 表4為基準(zhǔn)測試程序的可執(zhí)行文件大小。通過表中數(shù)據(jù)可知,所有基準(zhǔn)測試程序的4個(gè)可執(zhí)行文件大小滿足origin 3.1.3 基準(zhǔn)測試程序文件相似度比較 表5為基準(zhǔn)測試程序的原始可執(zhí)行文件與經(jīng)虛假控制流混淆的可執(zhí)行文件相似度比較。通過表中數(shù)據(jù)可知,除了sphinx3,另外5個(gè)基準(zhǔn)測試程序采用不同的虛假控制流混淆方法處理后的可執(zhí)行文件與原始可執(zhí)行文件相似度基本一致。 對不透明謂詞的混淆一般從強(qiáng)度、耐受性、開銷、隱蔽性、通用性方面進(jìn)行評價(jià),這里再增加一個(gè)指標(biāo):可逆性。此外,近年來符號執(zhí)行技術(shù)開始被用于攻擊不透明謂詞混淆,且具有較好的效果,因此將它也作為一個(gè)評估方法。 強(qiáng)度是指混淆給原始程序增加了多少復(fù)雜度。軟件復(fù)雜度評估有多種方法,McCabe QA是其中一個(gè)比較常用的方法,McCabe復(fù)雜度包括圈復(fù)雜度、基本復(fù)雜度、模塊設(shè)計(jì)復(fù)雜度等。圈復(fù)雜度是評估軟件復(fù)雜度的一個(gè)重要標(biāo)準(zhǔn),可以用于衡量軟件的復(fù)雜度和質(zhì)量。不透明謂詞方法只引入3行代碼,基本上不會改變軟件復(fù)雜度,即對強(qiáng)度基本沒有影響。 耐受性是指變換后的程序?qū)κ褂米詣?dòng)去混淆工具進(jìn)行攻擊的抵抗度。本文方法最大的弱點(diǎn)就是攻擊者可以通過實(shí)際執(zhí)行得到不透明謂詞的真實(shí)值,這是大部分不透明謂詞構(gòu)造方法的固有缺陷。如果將該方法結(jié)合其他代碼混淆方法,能較大程度上避免這一缺陷,同時(shí)只引入非常小的開銷。 開銷是指經(jīng)過混淆變換后的程序相較原來的程序所產(chǎn)生的開銷,如程序執(zhí)行時(shí)間、程序所需存儲空間等。如表3所示,本文方法在運(yùn)行時(shí)間上明顯優(yōu)于LLVM提供的不透明謂詞示例。如表4所示,本文方法在可執(zhí)行文件所需存儲空間方面明顯優(yōu)于LLVM提供的不透明謂詞示例。實(shí)際上,這是因?yàn)楸疚姆椒ū旧懋a(chǎn)生3條指令,而LLVM提供的不透明謂詞示例中間代碼產(chǎn)生17條指令,因此無論是執(zhí)行時(shí)間還是所需存儲空間,本文方法都有較大的優(yōu)勢。 表4 可執(zhí)行文件大小 表5 虛假控制流混淆前后可執(zhí)行文件相似度比較 隱蔽性是指不透明謂詞不具備明顯的特征,可以用于衡量采用不透明謂詞的混淆抵抗攻擊者人工分析和特征匹配分析的能力?,F(xiàn)有的大部分不透明謂詞構(gòu)造技術(shù)往往具備明顯的特征,如基于3SAT問題的不透明謂詞涉及較多的布爾操作,文獻(xiàn)[20]提出的啟發(fā)式檢測策略能有效識別該不透明謂詞構(gòu)造技術(shù)。浮點(diǎn)數(shù)是C/C++、Java、Python、PHP、JavaScript等主流高級編程語言的基本數(shù)據(jù)類型,對其進(jìn)行類型轉(zhuǎn)換或運(yùn)算不需要額外的支持,因此高級編程語言原生支持浮點(diǎn)數(shù)及浮點(diǎn)數(shù)類型轉(zhuǎn)換或運(yùn)算。并且,本文不透明謂詞方法具有非常簡短的代碼,因此具有良好的隱蔽性。 通用性是指不透明謂詞能用于多種編程語言,能運(yùn)行于多種操作系統(tǒng)等。浮點(diǎn)數(shù)是C/C++、Java、Python、PHP、JavaScript等主流高級編程語言的基本數(shù)據(jù)類型,因此無論在任何操作系統(tǒng)上,本文不透明謂詞方法都支持主流的高級編程語言。從程序生成過程的角度來看,本文方法不僅僅可以應(yīng)用于源代碼,還可以應(yīng)用于以LLVM IR為代表的中間代碼以及可執(zhí)行文件。綜上,本文方法具有良好的通用性。 可逆性是指使用軟件所有者能否對經(jīng)過混淆的軟件進(jìn)行反混淆。任何一個(gè)軟件都有缺陷,經(jīng)過混淆后的軟件同樣如此。如果直接對混淆后的軟件進(jìn)行分析,則安全分析人員同樣要面臨軟件逆向等方面的障礙。本文不透明謂詞方法具有可逆性,只要提前構(gòu)造好浮點(diǎn)數(shù)計(jì)算范圍,就可以通過技術(shù)手段快速對混淆后的程序進(jìn)行反混淆。 近年來,基于符號執(zhí)行的程序分析技術(shù)被用于自動(dòng)化反混淆不透明謂詞混淆。與此同時(shí),大部分不透明謂詞,如條件表達(dá)式“(+1)%2== 0”,往往具有固定的值,無法抵抗符號執(zhí)行攻擊。本文的不透明謂詞方法并不具備固定的值,能夠抵抗符號執(zhí)行等軟件動(dòng)態(tài)分析手段。 本文提出一種基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞混淆方法,利用計(jì)算機(jī)進(jìn)行浮點(diǎn)數(shù)運(yùn)算精度有限的原理構(gòu)造不透明謂詞。該方法可以在權(quán)衡軟件安全性要求和軟件性能,在產(chǎn)生較低開銷的情況下增加對軟件的保護(hù);具有可逆性,在特殊情況下可以將混淆后的程序恢復(fù);不僅能抵抗靜態(tài)分析,還能在一定程度上抵抗動(dòng)態(tài)分析,如所提方法生成的不透明謂詞并不具備固定的值,能抵抗符號執(zhí)行攻擊。所提方法的可逆性是優(yōu)點(diǎn),也是容易被破解的缺點(diǎn)。因此后續(xù)需要構(gòu)造不透明謂詞混淆框架,所提方法與眾多不透明謂詞方法組合并在混淆時(shí)隨機(jī)選擇使用,擴(kuò)大不透明謂詞的熵,增大攻擊者破解的枚舉難度。 [1] 奇安信代碼安全實(shí)驗(yàn)室. 2022 中國軟件供應(yīng)鏈安全分析報(bào)告[EB]. Qi An Xin Code Security Lab. 2022 China software supply chain security analysis report[EB]. [2] BSA Global Software Survey. Software management: security imperative, business opportunity[EB]. [3] 張漢寧. 基于精簡指令集的軟件保護(hù)虛擬機(jī)技術(shù)研究[D]. 西安: 西北大學(xué), 2010. ZHANG H N. Research on software protection virtual machine technology based on reduced instruction set[D]. Xi'an: Northwest University, 2010. [4] SHERIDAN B, SHERR M. On manufacturing resilient opaque constructs against static analysis[J]. Springer International Publishing, 2016. [5] COLLBERG C, THOMBORSON C, LOW D. A taxonomy of obfuscating transformations[J]. Technical Report, 1997. [6] 李成揚(yáng), 黃天波, 陳夏潤, 等. LLVM中間語言的控制流混淆方案[J]. 計(jì)算機(jī)工程與應(yīng)用, 2023, (4): 1-8. LI C Y, HUANG T B, CHEN X R, et al. Control flow obfuscation scheme for LLVM intermediate languages[J]. Computer Engineering and Applications, 2023, (4): 1-8. [7] LáSZLó T, KISS A . Obfuscating C++ programs via control flow flattening[R]. 2009. [8] ROLLES R. Unpacking virtualization obfuscators[C]//Proceedings of the 3rd USENIX Conference on Offensive Technologies. 2009. [9] KUANG K, TANG Z, GONG X, et al. Exploiting dynamic scheduling for VM-based code obfuscation[C]//2017 IEEE Trustcom/BigDataSE/I SPA. 2017. [10] 陳耀陽. 基于代碼混淆的軟件保護(hù)技術(shù)研究與實(shí)現(xiàn)[D]. 南京: 南京郵電大學(xué), 2021. CHEN Y Y. Research and implementation of software protection technology based on code obfuscation[D]. Nanjing: Nanjing University of Posts and Telecommunications, 2021. [11] 房鼎益, 張恒, 湯戰(zhàn)勇, 等. 一種抗語義攻擊的虛擬化軟件保護(hù)方法[J]. 工程科學(xué)與技術(shù), 2017, 49(1): 159-168. FANG D Y, ZHANG H, TANG Z Y, et al. DAS-VMP: a virtual machine-based software protection method for defending against semantic attacks[J].Advanced Engineering Sciences, 2017, 49(1): 159-168. [12] 湯戰(zhàn)勇, 李光輝, 房鼎益, 等. 一種具有指令集隨機(jī)化的代碼虛擬化保護(hù)系統(tǒng)[J]. 華中科技大學(xué)學(xué)報(bào)(自然科學(xué)版), 2016, 44(3): 28-33. TANG Z Y, LI G H, FANG D Y, et al. Code virtualized protection system with instruction set randomization[J]. Journal of Huazhong University of Science and Technology(Natural Science Edition), 2016, 44(3): 28-33. [13] COLLBERG C, THOMBORSON C, LOW D. Manufacturing cheap, resilient, and stealthy opaque constructs[C]//Proceedings of the 25th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL ’98). 1998: 184-196. [14] 袁征, 馮雁, 溫巧燕, 等. 構(gòu)造一種新的混淆Java程序的不透明謂詞[J]. 北京郵電大學(xué)學(xué)報(bào), 2007, 30(6): 103-106. YUAN Z, FENG Y, WEN Q Y, et al. Manufacture of a new opaque predicate for java programs[J]. Journal of Beijing University of Posts and Telecom, 2007, 30(6): 103-106. [15] MOSER A, KRUEGEL C, KIRDA E. Limits of static analysis for malware detection[C]//Twenty-Third Annual Computer Security Applications Conference (ACSAC 2007). 2007. [16] TIELLA R, CECCATO M. Automatic generation of opaque constants based on the k-clique problem for resilient data obfuscation[C]//2017 IEEE 24th International Conference on Software Analysis, Evolution and Reengineering (SANER). 2017: 182-192. [17] SHARIF M, LANZI A, GIFFIN J, et al. Impeding malware analysis using conditional code obfuscation[C]//Proceedings of the Network and Distributed System Security Symposium (NDSS 2008). 2008. [18] ZHU W, THOMBORSON C. A provable scheme for homomorphic obfuscations in software security[R]. ACTA Press, 2005. [19] ARBOIT G. A method for watermarking Java programs via opaque predicates[C]//Proc Int Conf Electronic Commerce Research, 2002. [20] WANG Z, MING J, JIA C, et al. Linear obfuscation to combat symbolic execution[C]//European Symposium on Research in Computer Security. 2011. [21] 付蒙. 抵抗符號執(zhí)行的不透明謂詞混淆技術(shù)研究[D]. 西安: 西安電子科技大學(xué), 2019. FU M. Research on opaque predicate-based obfuscations against symbolic execution[D]. Xi’an: Xidian University, 2019. [22] KING J C. Symbolic execution and program testing[J]. Communications of the ACM, 1976, 19(7): 385-394. [23] MING J, XU D, WANG L, et al. LOOP: logic-oriented opaque predicate detection in obfuscated binary code[C]//Proceedings of the 22nd ACM SIGSAC Conference on Computer and Communications Security. 2015: 757-768. [24] YADEGARI B, JOHANNESMEYER B, WHITELY B, et al. A generic approach to automatic deobfuscation of executable code[C]//2015 IEEE Symposium on Security and Privacy. 2015: 674-691. [25] BARDIN S, DAVID R, MARION J Y. Backward-bounded DSE: targeting infeasibility questions on obfuscated codes[C]//2017 IEEE Symposium on Security and Privacy (SP). 2017: 633-651. [26] BANESCU S, COLLBERG C, GANESH V, et al. Code obfuscation against symbolic execution attacks[C]//Proceedings of the 32nd Annual Conference on Computer Security Applications. 2016: 189-200. [27] 王國俊. 有理數(shù)、無理數(shù)與實(shí)數(shù)[J]. 數(shù)學(xué)的實(shí)踐與認(rèn)識, 1998(3): 258-266. WANG G J . Rational, irrational and numbers [J]. Mathematics in Practice and Theory, 1998 (3): 258-266. Constructing method of opaque predicate based ontype conversion and operation of floating point numbers WANG Qingfeng, LIANG Hao, WANG Yawen, XIE Genlin, HE Benwei Information Technology Research Institute, Information Engineering University, Zhengzhou 450001, China With the increasing complexity of software functions and the evolving technologies of network attacks, malicious behaviors such as software piracy, software cracking, data leakage, and malicious software modification are on the rise. As a result, software security has become a focal point in industry research. Code obfuscation is a common software protection technique used to hinder reverse engineering. It aims to make program analyzing and understanding more difficult for attackers while preserving the original program functionality. However, many existing code obfuscation techniques suffer from performance loss and poor concealment in pursuit of obfuscation effectiveness. Control flow obfuscation, particularly opaque predicate obfuscation, is widely used to increase the difficulty of code reverse engineering by disrupting the program’s control flow. A method was proposed to address the limitations of existing code obfuscation techniques. It utilized the phenomenon of precision loss that occurred during type conversion and floating-point number operations in computers. Under certain conditions, this method produced operation results that contradict common sense. By performing forced type conversion, addition, and multiplication with selected decimal numbers, a series of opaque predicates can be constructed based on the statistical analysis of their operation results. This approach achieved code obfuscation with high concealment, good generality, reversibility, and low overhead compared to traditional opaque predicates. Experimental verification demonstrates that this method significantly slows down attackers’ reverse engineering efforts and exhibits good resistance to dynamic analysis techniques such as symbolic execution. code obfuscation, bogus control flow, opaque predicates, floating point operations The National Natural Science Foundation of China (62002383) 王慶豐, 梁浩, 王亞文, 等. 基于浮點(diǎn)數(shù)類型轉(zhuǎn)換和運(yùn)算的不透明謂詞構(gòu)造方法[J]. 網(wǎng)絡(luò)與信息安全學(xué)報(bào), 2023, 9(5): 48-58. TP393 A 10.11959/j.issn.2096?109x.2023068 王慶豐(1995?),男,河南周口人,信息工程大學(xué)助理研究員,主要研究方向?yàn)閿M態(tài)防御和軟件多樣化。 梁浩(1987? ),男,河南鄭州人,信息工程大學(xué)副研究員,主要研究方向?yàn)榫W(wǎng)絡(luò)空間主動(dòng)防御、內(nèi)生安全。 王亞文(1990?),男,河南鄭州人,信息工程大學(xué)助理研究員,主要研究方向?yàn)閿M態(tài)防御和云計(jì)算。 謝根琳(1999? ),男,河北辛集人,信息工程大學(xué)碩士生,主要研究方向?yàn)榫W(wǎng)絡(luò)空間安全和軟件多樣化。 何本偉(1998? ),男,安徽滁州人,信息工程大學(xué)碩士生,主要研究方向?yàn)榫W(wǎng)絡(luò)空間安全和軟件多樣化。 2022?09?05; 2013?01?30 梁浩,lhmailhappy@163.com 國家自然科學(xué)基金(62002383) WANG Q F, LIANG H, WANG Y W, et al. Constructing method of opaque predicate based on type conversion and operation of floating point numbers[J]. Chinese Journal of Network and Information Security, 2023, 9(5): 48-58.3.2 實(shí)驗(yàn)分析與評估
4 結(jié)束語