邱子楊,付 雄
(南京郵電大學(xué) 計(jì)算機(jī)學(xué)院,江蘇 南京 210003)
根據(jù)2016年第一季度統(tǒng)計(jì)報(bào)告指出[1],Android設(shè)備所占市場份額為76.4%。但同時(shí)根據(jù)《騰訊移動安全實(shí)驗(yàn)室2016年上半年手機(jī)安全報(bào)告》指出[2],2016年上半年新増安卓惡意應(yīng)用安裝包918萬個,是2014年全年新增惡意應(yīng)用包的9.15倍,感染用戶數(shù)量已經(jīng)超過2億,同比去年增長了42%。安卓用戶群體的高比例以及惡意應(yīng)用軟件的激增使得安卓應(yīng)用軟件的安全防護(hù)技術(shù)日漸重要。
攻擊者一般會通過對安卓應(yīng)用程序進(jìn)行反編譯并篡改代碼再對其進(jìn)行重新打包并且重新簽名來進(jìn)行惡意行為的攻擊。當(dāng)攻擊者攻擊一個安卓應(yīng)用程序文件時(shí),并不會直接反匯編去分析其smali代碼[3],因?yàn)閟mali代碼過于復(fù)雜,難以讀閱,而他們往往會把可執(zhí)行文件apk反編譯成java源碼,然后從java源碼中獲取到關(guān)鍵代碼的位置,然后再去對應(yīng)的smali代碼位置進(jìn)行篡改[4],然后重新打包,重新簽名就可以得到一個被纂改過的安卓應(yīng)用程序。
因此,防止Android應(yīng)用程序逆向分析是非常重要的。在以往的研究中,Enck等列出了Android系統(tǒng)的安全性分析方法[5],分析了Android系統(tǒng)的安全性模型并解釋其復(fù)雜性。Felt和Fahl等[6-7]詳細(xì)說明了Android系統(tǒng)的安全性。Bernhard等[8]開發(fā)了Bauhaus,基于軟件安全技術(shù)和代碼分析技術(shù)的Android系統(tǒng)源代碼分析工具,并通過案例研究從安全認(rèn)證和許可機(jī)制的角度分析了Android系統(tǒng)實(shí)施中的不一致信息。
牛豪飛[9]實(shí)現(xiàn)一套在ART模式下的安卓應(yīng)用保護(hù)方案。通過對Android平臺的體系結(jié)構(gòu)、安全機(jī)制以及常見靜態(tài)和動態(tài)攻擊的分析,提出了動態(tài)和靜態(tài)兩個方向的安卓安全防御方案。尉惠敏[10]提出了一套基于Hook文件的自修改方案,可以應(yīng)對大部分攻擊手段。其加密粒度更小,加密精度更準(zhǔn)確。實(shí)現(xiàn)了So動態(tài)庫中函數(shù)運(yùn)行前解密運(yùn)行后加密,保證任何時(shí)刻So動態(tài)庫都不是完整的明文。是一種針對于Hook攻擊的動態(tài)防御機(jī)制。
對于Java層面的安卓應(yīng)用加固,彭守鎮(zhèn)[11]提出了基于資源文件的加密方式。對反編譯后的dex文件進(jìn)行加密混淆處理,對資源文件進(jìn)行加殼處理,從而預(yù)防apk被反編譯篡改,增強(qiáng)打包難度。呂苗苗[12]提出基于Java的安卓應(yīng)用代碼混淆技術(shù)。通過抽離安卓軟件中的code_item代碼,將其進(jìn)行混淆然后形成混淆代碼索引表,同時(shí)在So中進(jìn)行封裝。最后采取JNI機(jī)制注冊封裝后的代碼,生成特定的執(zhí)行環(huán)境。從而做到對安卓應(yīng)用代碼的混淆加固。
對于smali層面的安卓加固,鄭琪等人[13]通過插入多余的控制流和壓扁控制流對控制流進(jìn)行混淆以對安卓應(yīng)用進(jìn)行防御。并從功能、性能兩個方面做出了評價(jià)。劉方圓等人[14]同樣在smali層面對安卓應(yīng)用加固進(jìn)行研究,其主要是對寄存器的值加以混淆以及通過不透明謂詞對控制流進(jìn)行混淆,并且在強(qiáng)度、彈性、開銷進(jìn)行的技術(shù)評價(jià)。吳林[15]提出了基于Dalvik字節(jié)碼指令的混淆技術(shù),從數(shù)據(jù)流和控制流兩個層面對apk進(jìn)行混淆。
綜合現(xiàn)有的工作,大部分的工作都是針對于Android應(yīng)用程序中源碼級別Java代碼的混淆,對于Android應(yīng)用程序中smali級別的代碼的安全性分析還是比較缺少。對于Java源代碼層面的混淆目前主要是控制流和標(biāo)識符混淆兩個方面,可是大部分情況下廠商并不可能直接提供源碼給安全公司,這樣的話這種保護(hù)就無法發(fā)揮其作用。對于現(xiàn)有的smali層面的研究,主要圍繞數(shù)據(jù)流和邏輯流進(jìn)行混淆[16-18],且混淆方式并不考慮對原來安卓應(yīng)用的額外消耗,且混淆方式單一,缺乏動態(tài)性。
針對上述代碼混淆技術(shù)出現(xiàn)的問題,文中提出了smali代碼的混淆保護(hù)方法,在除去數(shù)據(jù)流和控制流兩個層面之外,又增加了邏輯流層面的混淆,并且對于數(shù)據(jù)流和控制流消耗方面也做了優(yōu)化和把控,其主要貢獻(xiàn)如下:
(1)設(shè)計(jì)實(shí)現(xiàn)smali代碼混淆系統(tǒng),不需要提供源碼,但能對抗攻擊者的攻擊。
(2)針對之前研究的混淆方式,提出新的混淆方式邏輯流混淆用來加強(qiáng)混淆強(qiáng)度。
(3)實(shí)驗(yàn)與評價(jià)。用這種方法保護(hù)后的應(yīng)用程序可以抵抗靜態(tài)分析,并使反編譯后的代碼出錯。同時(shí),還評估了其對時(shí)間和空間性能的影響,以證明該方法的有效性。
文中提出的混淆方式不同于Java策略方向的安全加固,不需要源碼但是完全可以對抗惡意攻擊,通過對Android應(yīng)用程序代碼中間產(chǎn)物smali代碼的混淆,使得攻擊者無法獲取正確的邏輯代碼。
下面簡要介紹該方法的混淆過程(見圖1):
圖1 混淆方法過程
step1:反編譯待保護(hù)的apk文件;
step2:遍歷所有smali文件,通過數(shù)據(jù)流混淆模塊進(jìn)行混淆;
step3:遍歷所有smali文件,通過控制流混淆模塊進(jìn)行混淆;
step4:遍歷所有smali文件,通過邏輯流混淆模塊進(jìn)行混淆;
step5:將編譯后的文件重新打包為apk文件;
在數(shù)據(jù)流混淆模塊中,對數(shù)據(jù)通過加密策略進(jìn)行混淆,為了不影響源程序的性能,且盡量縮短加密過程但對數(shù)據(jù)能起到混淆的作用,所以文中提出了一種基于字典的簡易加密方式。但由于字典加密算法有較大風(fēng)險(xiǎn),字典一旦被破解或盜取就面臨數(shù)據(jù)泄露的風(fēng)險(xiǎn),所以又通過RSA對字典進(jìn)行加密存儲在服務(wù)器端,且字典是由系統(tǒng)隨機(jī)生成的,所以不同Apk的數(shù)據(jù)加密方式是不同的,減少被破解的風(fēng)險(xiǎn)。下面介紹字典的生成和傳輸過程。
step1:生成兩個數(shù)組A,B,其大小為26,且每個數(shù)組依次存放0-25數(shù)字;
step2:打亂A數(shù)組和B數(shù)組的內(nèi)容,即為字典D;
step3:使用混淆系統(tǒng)中的私鑰對A與B進(jìn)行加密存儲,生成加密字典RSA(D);
step4:混淆系統(tǒng)發(fā)送字典RSA(D),給需要加密的apk端,apk端通過公鑰解密得到字典D;
step5:使用字典D進(jìn)行加密。
在上述過程中,小寫字母x對應(yīng)的密文為A[index_x],其中index_x=ascii(x)-0;ascii(x)為x對應(yīng)的ascii的碼值。同樣大寫字母X對應(yīng)的密文為B[index_X],其中index_X=ascii(X)-0;ascii(X)為x對應(yīng)的ascii的碼值。
Collberg等人[19]提出了代碼混淆的概念,提出了代碼混淆的基本定義,給出了第一個代碼混淆算法,將代碼混淆分為外形混淆、控制混淆、數(shù)據(jù)混淆和預(yù)防混淆,通過強(qiáng)度、執(zhí)行代價(jià)、彈性來評估有效性。代碼混淆其實(shí)就是一種代碼功能一致性的轉(zhuǎn)化,會保留與之前代碼一致的有效性,通過某種混淆轉(zhuǎn)換,使得變換后的程序在具有相同功能的前提下更難分析[20]。如果程序和具有一致的可觀測行為,則稱其為混淆轉(zhuǎn)換。
代碼混淆的基本原理如圖2所示,整體上說混淆方式主要有靜態(tài)混淆和動態(tài)混淆兩個方式。靜態(tài)混淆有控制流混淆、數(shù)據(jù)流混淆等,動態(tài)混淆是通過自定義的混淆器來達(dá)到運(yùn)行過程中動態(tài)的進(jìn)行混淆以及解混淆的方法。
2017年,彩云社區(qū)在進(jìn)行居民情況調(diào)查時(shí),了解到楊家的事。李敬益打算啃啃硬骨頭,牽頭調(diào)解試試看。他把楊家七個兄妹都找來,挨個了解了下他們的想法;再把老太太的兩個兄弟請來,“兩個舅舅一來,講了句公道話,‘都是一家人,現(xiàn)在就剩下你們媽媽了,也得考慮考慮她。’”李敬益聽完,心里大概有了數(shù),這一家人的目光總圍著商鋪轉(zhuǎn),如果按著以往的思路往下走,只討論商鋪的歸屬,這矛盾怕是難解。得轉(zhuǎn)換個思路,綜合考慮、綜合盤算。
圖2 smali代碼混淆原理示意圖
smali代碼混淆:
(1)基于字典加密的數(shù)據(jù)流混淆。
在Dalvik虛擬機(jī)中,由于字符串是通過明文形式顯示賦值給寄存器,然后再由具體操作在寄存器內(nèi)取字符串的具體值,這樣就會造成代碼暴露的危險(xiǎn)性。所以可以將字符串進(jìn)行加密處理,對數(shù)據(jù)進(jìn)行混淆,增加代碼閱讀難度,降低破解代碼邏輯風(fēng)險(xiǎn)。
在傳統(tǒng)加密方式中,常用的加密方式為對稱加密和非對稱加密,但其加密方式繁瑣且性能消耗大,但是混淆方法中,對原有程序的影響越小則混淆方法是越有效的,所以文中采用基于字典的加密方式來簡化加解密過程,減少對原有程序的影響。這種加密方式即隨機(jī)生成a-z以及A-Z唯一對應(yīng)的字典密文后進(jìn)行加密。數(shù)據(jù)流混淆過程如算法1所示。
算法1:數(shù)據(jù)流混淆。
輸入:待保護(hù)應(yīng)用反編譯之后的smali文件。
輸出:數(shù)據(jù)流混淆之后是smali文件。
1.設(shè)smali文件集合為F=(f1,f2,…,fn),其中fi表示第i個smali文件。
2.遍歷集合F,逐行讀取fi文件。
3.設(shè)行內(nèi)容為fij,記錄加密位置pm=j(當(dāng)fij滿足正則s*const-strings+(v|p)(d),s+”(.*)”),添加到集合Pi中。
4.設(shè)字典加密算法為D(x),遍歷集合Pi,獲取加密字符串s=D(fipm),替換fipm=s。
5.遍歷集合F,輸出。
6. end
算法1只是對如下指令const-string v0, “InjectLog”進(jìn)行簡單的修改,并且由于加密算法是基于字典進(jìn)行加密,所以并不會修改字符串長度,且解密過程是基于字典式的,所以查詢密鑰對應(yīng)原文的時(shí)間復(fù)雜度為O(1),并不會對系統(tǒng)性能產(chǎn)生很大的消耗,也不會對系統(tǒng)文件大小產(chǎn)生改變,但是能在一定程度上抵抗逆向工具的逆過程,是一種低消耗、高性能的數(shù)據(jù)流混淆方式。
圖3為數(shù)據(jù)流混淆后的結(jié)果。
圖3 數(shù)據(jù)流混淆
可以看出,有意義的字符串全部被更換為了無意義的字符串,這樣就使得攻擊者無法從字面獲取程序的意義從而進(jìn)行邏輯分析,很大程度上增加了邏輯分析的難度。
(2)低消耗控制流混淆。
算法2:控制流混淆。
輸入:待保護(hù)應(yīng)用反編譯之后的smali文件。
輸出:控制流混淆之后是smali文件。
1.設(shè)smali文件集合為F=(f1,f2,…,fn),其中fi表示第i個smali文件。
2.設(shè)存儲方法的集合為Map集合,M=(mi,ci),其中mi表示方法的全限定名稱,ci表示mi被調(diào)用的次數(shù)。
3.遍歷集合F,逐行讀取fi,如果當(dāng)前調(diào)用了方法mi,檢測Map是否存在(mi,ci),如果存在則ci++,否則添加一個新元素(mi,ci)(其中ci=1)到Map中,并且維持方法總量C=C+ci(C初始值為0)。
5.重新遍歷集合F,逐行讀取fi,如果當(dāng)前調(diào)用的方法mi∈P,則執(zhí)行控制流混淆器D(x),混淆結(jié)果s=D(mi),替換fi=s。
6.遍歷集合F,輸出。
7. end
控制流混淆相對于數(shù)據(jù)流混淆來說,是更有效的混淆方式,其原理是在程序的某些地方添加一些常用的控制switch、if等來隱藏原程序中真正的控制流程,從而阻止反編譯攻擊。并且在smali語法中,控制流語法復(fù)雜程度遠(yuǎn)遠(yuǎn)高于Java源代碼,其是通過跳轉(zhuǎn)指令來實(shí)現(xiàn)對代碼的邏輯控制,所以加入一些無效控制流或者修改一些控制流,可以很大程度混淆代碼,降低代碼的可讀性。
文中提出的低消耗控制流多注入的混淆方式,首先確定插入位置,確定插入位置的方式是將方法被調(diào)用次數(shù)作為依據(jù),超過閾值的,將其被調(diào)用的位置確定為待插入位置。
控制流混淆不會對原有命令做修改混淆,而是在原有命令上增加無效控制流,比如常用的if分支,switch分支,這增加了原有程序的復(fù)雜性,給攻擊者分析smali代碼增加了難度。
圖4為控制流混淆的結(jié)果。
圖4 控制流混淆
可以看出,混淆后之前的簡單邏輯被加大了復(fù)雜度,出現(xiàn)了分支,從而干擾攻擊者的邏輯分析,增大了分析難度。
(3)邏輯流混淆。
對數(shù)據(jù)流混淆和控制流混淆來說,如果攻擊者通過數(shù)據(jù)分析獲取加密規(guī)則并且攻擊者對smali語言十分熟悉,這種情況下,數(shù)據(jù)流混淆和控制流混淆會顯得蒼白。
為加大混淆力度,文中提出一種新的混淆方式—邏輯流混淆,邏輯流是指程序的執(zhí)行過程。
由于smali源代碼所有的邏輯必然都是與APP本身執(zhí)行過程有關(guān)的,所以當(dāng)攻擊者進(jìn)行反編譯之后,對smali源代碼,在短時(shí)間內(nèi)很有可能分析出APP執(zhí)行過程從而對APP的安全造成危害。為了提高安全性,文中提出了一種邏輯流混淆的思想,讓攻擊者在短時(shí)間內(nèi)無法分析出APP的邏輯流,或者讓其分析無效的邏輯流。
邏輯流混淆的具體做法是在APP邏輯流某一節(jié)點(diǎn)處添加不影響APP邏輯流和數(shù)據(jù)流的自定義邏輯流,不僅加大APP邏輯流的復(fù)雜程度,也由于無關(guān)邏輯流的加入,使得攻擊者對于APP執(zhí)行過程的分析并不都是有效的,進(jìn)而增加APP的安全性。對于自定義的邏輯流,如果過于復(fù)雜會增加APP對系統(tǒng)的消耗,過于簡單又對混淆加固起不到很大作用,所以選擇合適的自定義邏輯流是尤為重要的??刂屏骰煜^程如算法3所示。
算法3:邏輯流混淆。
輸入:待保護(hù)應(yīng)用反編譯之后的smali文件。
輸出:控制流混淆之后是smali文件。
1.設(shè)smali文件集合為F=(f1,f2,…,fn),其中fi表示第i個smali文件。
2.構(gòu)建邏輯流圖T=(t1,t2,…,tn),其中ti為樹節(jié)點(diǎn),也就是調(diào)用的方法,其中T表示樹的層次遍歷序列,且T是一棵有序樹。
3.選擇邏輯流節(jié)點(diǎn),這里采用隨機(jī)選取的方式,調(diào)用邏輯流混淆器D(x),結(jié)果t=D(ti),替換ti=t。
4.遍歷集合F,輸出。
5. end
圖5為邏輯流混淆的結(jié)果。
圖5 邏輯流混淆
可以看出,之前的邏輯前后不只是單純的一個邏輯的執(zhí)行,而是被加上了多余的邏輯,而這些多余的邏輯是邏輯流混淆模塊自定義的,與程序本身邏輯流無關(guān),也不會影響程序邏輯流的執(zhí)行。這樣的混淆既做到了安全加固,增大攻擊者分析難度,也不會影響源程序的執(zhí)行,且由圖可看出相對數(shù)據(jù)流混淆和控制流混淆,復(fù)雜度更高。
混淆程序Pr'相對于原始程序Pr由于混淆產(chǎn)生的額外開銷,通過執(zhí)行代價(jià)來度量。
執(zhí)行代價(jià)的定義如下:
表1 執(zhí)行代價(jià)度量
彈性用來度量混淆程序的抵抗攻擊程度,是指針對于反混淆程序的攻擊,主要包括反混淆程序運(yùn)行時(shí)的時(shí)間和空間代價(jià)以及攻擊者編寫反混淆程序的代價(jià)。
彈性定義如下:
規(guī)定T是對Pr的一個單項(xiàng)的混淆變化當(dāng)且僅當(dāng)從原始程序Pr除去某些信息后無法通過混淆后的程序Pr'恢復(fù)出Pr。
對于文中提出的smali代碼混淆方法從數(shù)據(jù)流、控制流、邏輯流三個層面進(jìn)行混淆。在數(shù)據(jù)流混淆方面,將constr指定中存儲的字符串進(jìn)行加密存儲,這種方法使得逆向分析獲取的字符串值是錯誤的,實(shí)驗(yàn)結(jié)果如圖3所示。在控制流混淆方面,在關(guān)鍵函數(shù)調(diào)用指令和返回值獲取指令中間插入不透明謂詞,使得攻擊者無法獲得正確的控制流程,逆向工具逆向結(jié)果圖4所示。在此基礎(chǔ)上文中還提出了新的混淆方式,即邏輯流混淆方式,因?yàn)锳PP在逆向之后所有的邏輯流都是和APP本身運(yùn)行有關(guān)的,所以引入邏輯流混淆,才進(jìn)行一些無用邏輯的處理和調(diào)用。逆向工具逆向結(jié)果如圖5所示,當(dāng)攻擊者利用逆向工具去逆向分析時(shí),結(jié)果不僅僅是APP的邏輯流還有加入混淆的邏輯流。
對不同的混淆方式分別進(jìn)行時(shí)間開銷的分析。對于數(shù)據(jù)流層面的混淆只是簡單的加密混淆對時(shí)間開銷必然沒有影響。對于控制流混淆,插入的無效控制流時(shí)間復(fù)雜度都為O(1),并且控制流個數(shù)的插入也是有限的,所以并沒有影響原程序的復(fù)雜度。對于邏輯流混淆,插入的新邏輯流的時(shí)間復(fù)雜度均為O(1),這在可以容忍的范圍之內(nèi)。對于空間開銷來說,由于混淆僅僅是針對關(guān)鍵函數(shù)進(jìn)行指令轉(zhuǎn)換、插入定量的無效控制流、修改控制流,以及插入定量的空間復(fù)雜度為O(1)的邏輯流,因此,smali代碼的混淆方法對于程序空間開銷來說影響較小。
被混淆的程序,在數(shù)據(jù)流層面其字符串的值被加密混淆,在控制流層面進(jìn)行的混淆,如圖4所示,增加了程序的控制流復(fù)雜度;除此之外,對于邏輯流進(jìn)行混淆,如圖5所示,增加了許多無關(guān)程序的邏輯流,加強(qiáng)了程序的復(fù)雜度??梢钥闯鑫闹械拇a混淆方法具有較好的彈性。
如圖1所示,文中設(shè)計(jì)并實(shí)現(xiàn)了一個smali混淆系統(tǒng),能夠有效地抵抗逆向分析。
實(shí)驗(yàn)環(huán)境:Android7.0紅米Note,Idea開發(fā)環(huán)境。測試用例說明如表2所示。
表2 測試用例說明
測試用例:本節(jié)采用四個自主編寫的Android應(yīng)用程序作為測試用例,這四種應(yīng)用程序是具有代表性的,完全可以表明混淆方法的有效性。
文中從兩個方面分析smali混淆系統(tǒng)的性能,一方面是通過應(yīng)用程序保護(hù)方法的有效性來評估應(yīng)用程序保護(hù)方法的質(zhì)量,另一方面通過保護(hù)前后應(yīng)用程序的性能消耗變化評估其質(zhì)量。對于有效性,之前已經(jīng)在強(qiáng)度、開銷、彈性進(jìn)行了分析,接下來對性能消耗變化作根據(jù)四個測試用例的實(shí)驗(yàn)結(jié)果進(jìn)行分析,主要從三個方面分析性能消耗:保護(hù)前后的代碼長度變化,時(shí)間開銷變化和空間開銷變化。
由于移動設(shè)備往往在內(nèi)存和處理器方面是受限的,所以應(yīng)用程序的大小以及APP啟動時(shí)間很重要,這關(guān)乎到用戶體驗(yàn)問題。因此對代碼長度變化以及啟動時(shí)間進(jìn)行定量分析以此來證明smali混淆系統(tǒng)的有效性。
如表3所示,混淆程序相比于原始程序代碼長度并沒有顯著變化,主要原因如下:
表3 代碼長度和開銷
(1)對const-str中的字符串只是加密等長替換,所以對代碼長度不會有影響;
(2)只是簡單的指令替換;
(3)測試用例的代碼長度本身比較小,滿足混淆操作的指令并不多;
(4)邏輯流混淆插入的部分的邏輯,是新增的邏輯,由于新增邏輯本身并不大,所以對代碼長度和內(nèi)存消耗也并不是很大。
為了更直觀地體現(xiàn)混淆操作對應(yīng)用程序的影響并不大,另外比較了應(yīng)用程序混淆前后啟動時(shí)間的變化(見表4)。
表4 啟動時(shí)間變化
4個應(yīng)用程序在第一次啟動時(shí),啟動時(shí)間在混淆前后有明顯的變化,分析原因可能是以下原因造成的:
(1)dex文件類加載器的替換;
(2)混淆方法的查找。但是在第一次啟動之后,可以發(fā)現(xiàn)啟動時(shí)間在混淆前后基本沒有變化。
針對Android應(yīng)用程序容易被反編譯篡改smali源碼并重新打包重新簽名的問題,提出了一種smali代碼混淆的應(yīng)用程序保護(hù)方法,不同于常規(guī)的Android應(yīng)用程序保護(hù),是針對于smali層面做的防護(hù),無需獲得源碼即可進(jìn)行混淆,并且在常規(guī)的數(shù)據(jù)流和控制流層面使用了新的算法。在數(shù)據(jù)流層面采用快速加解密的字典式對其進(jìn)行混淆,在控制流層面,選取特定的位置進(jìn)行混淆,并且控制流的插入會選取輕量級消耗的控制流,從而減少對程序開銷的影響。文中在此基礎(chǔ)上還提出了新的混淆層面邏輯流混淆,相對于數(shù)據(jù)流和控制流來說混淆強(qiáng)度更大,擴(kuò)展性更強(qiáng),這使得對Android應(yīng)用程序的防御有很大的提升。同時(shí)也從強(qiáng)度、開銷、彈性三個方面對smali代碼混淆方法進(jìn)行了分析,也從代碼長度和啟動時(shí)間定量進(jìn)行了分析,實(shí)驗(yàn)結(jié)果表明,smali代碼混淆方法是有效的。
總之,提出的smali代碼混淆對于解決Android安全性被破壞的問題有一定意義,但是對于自定義的邏輯流沒有進(jìn)行很好的選擇,導(dǎo)致開銷上有一定影響。因此下一步工作將針對邏輯流進(jìn)行優(yōu)化,以更好地保護(hù)代碼并且減少消耗。