Android應(yīng)用安全隱患現(xiàn)狀--資源文件加密/安全防護(hù)進(jìn)化史
前言
? ??有安全數(shù)據(jù)顯示,2014全年,Android用戶感染惡意程序3.19億人次,平均每天惡意程序感染量達(dá)到了87.5萬人次。同時(shí),Android應(yīng)用被破解和盜版等事件也層出不窮。很明顯,Android平臺已經(jīng)成為惡意程序和破解者攻擊的眾矢之的,于是越來越多的Android開發(fā)者開始意識到應(yīng)用安全的重要性。
一、什么是“打包黨”
? ??他們專門對最熱門或新秀APP下手,先將其破解,然后再以植入木馬、插入廣告、篡改支付鏈接等形式封裝成新的APP,這個(gè)過程也叫做二次打包。更有開發(fā)者爆料,專業(yè)“打包黨”的月收入超過百萬,這簡直是對正版開發(fā)者最赤裸的攻擊和挑釁。
? ??尼瑪!一寸代碼一寸血,一寸光陰一寸金,全白費(fèi)了!
二、“打包黨”一般都做些什么
植入木馬,惡意扣費(fèi)
? ??“打包黨”謀取暴利的形式多樣,如在APP中植入木馬程序,用戶下載后,通過惡意扣費(fèi)、竊取用戶賬號和密碼等方式來獲取利益。為了蒙蔽用戶和節(jié)約成本,二次打包的APP通常和正版基本沒有差異,用戶在毫不知情的情況下使用后,一旦遭遇經(jīng)濟(jì)損失,最終開發(fā)者就要為此背黑鍋,還會(huì)使正版APP的品牌形象受損。
植入廣告,賺取廣告費(fèi)
? ??當(dāng)一個(gè)團(tuán)隊(duì)辛辛苦苦開發(fā)的APP,有了幾十萬、上百萬的用戶時(shí),可能已經(jīng)成為了“打包黨”捕獵的對象。他們會(huì)在二次打包的過程中以植入或替換廣告的形式來賺取廣告收入,廣告有按展示次數(shù)、點(diǎn)擊次數(shù)、安裝激活量等不同的計(jì)費(fèi)形式。以展示次數(shù)為例,為了謀取更多利益,二次打包的APP會(huì)頻繁的對用戶進(jìn)行廣告提醒,給用戶造成騷擾,體驗(yàn)感極差,但“打包黨”并不care,他們只關(guān)心怎樣盡可能多的賺到錢。
? ??可以想象,一邊是團(tuán)隊(duì)拼命的開發(fā)和推廣,另一邊則坐收漁翁之利,不勞而獲。APP越火爆,給“打包黨”帶來的利益就越多,完全淪為了“打包黨”賺錢的工具。
直接截取開發(fā)者的財(cái)路
? ??除了游戲和軟件類APP,隨著移動(dòng)支付類應(yīng)用的火熱,“打包黨”還瞄準(zhǔn)了支付類APP。“打包黨”破解正版APP后,再修改App的付費(fèi)鏈接參數(shù),用戶支付的費(fèi)用直接進(jìn)入“打包黨”的口袋,完全切斷了開發(fā)者的財(cái)路。
? ??辛辛苦苦一整年,轉(zhuǎn)眼回到解放前!
三、安卓apk的文件結(jié)構(gòu)
? ??AndroidManifest.xml:Android主配置文件,編譯過程中由文本格式轉(zhuǎn)化為二進(jìn)制AXML文件格式。
? ??Classes.dex:java代碼編譯后產(chǎn)生的一種類似字節(jié)碼的文件。
? ??res:資源文件,其中的.xml文件在編譯過程中由文本格式轉(zhuǎn)化為二進(jìn)制AXML文件格式。
? ??META-INF:簽名文件。
? ??lib: native代碼編譯后的so。
? ??其他文件夾:由開發(fā)者自己添加的文件
? ??Android apk的核心邏輯主要存在于classes.dex中,通常破解者在進(jìn)行破解和二次打包時(shí),會(huì)對classes.dex和AndroidManifest.xml文件進(jìn)行操作,所以對這兩個(gè)文件進(jìn)行保護(hù)尤為重要。
四、apk二次打包的四個(gè)步驟
? ??1.反編譯
? ??反編譯java:classes.dex反編譯成中間文件(smali、jar)。
? ??反編譯布局文件:Axml文件反編譯成xml文件。
? ??2.修改
? ??修改smali文件。
? ??修改xml文件。
? ??3.重新編譯
? ??修改后的smali編譯成classes.dex。
? ??修改后的xml編譯成Axml。
? ??4.重簽名
? ??一款山寨版APP由此誕生!
五、Android APP 防破解進(jìn)化史 原始社會(huì)時(shí)期——代碼混淆
? ??最早的應(yīng)用保護(hù)當(dāng)屬代碼混淆,谷歌官方發(fā)布的sdk中就包含ProGuard這種混淆工具?;煜ぞ邥?huì)把你用java語言編寫的代碼的類名、變量名混淆為自己定義的格式,這樣可以增加破解者在破解時(shí)閱讀難度。但代碼混淆只是簡單的改變類名或者變量的名,只要能找dex,反編譯為smali或者java,花些時(shí)間還是可以輕松破解的。如果說不用混淆工具我們破解一個(gè)apk需要2兩天,那么用了這個(gè)工具,破解者可能需要4天,只是時(shí)間成本增加了。
奴隸社會(huì)時(shí)期——自我校驗(yàn)
? ??經(jīng)過漫長的混淆時(shí)期,開發(fā)者發(fā)現(xiàn)他們的應(yīng)用還是照常被破解。于是新的保護(hù)方式又出現(xiàn)了——自我校驗(yàn)。
簡單說,自我校驗(yàn)就是在程序中加一些對自己應(yīng)用的完整性校驗(yàn),可以借助簽名、或計(jì)算自己應(yīng)用dex的md5值等等來完成。有些開發(fā)者直接把校驗(yàn)功能加入到dex中,有些則是通過http協(xié)議請求相關(guān)服務(wù)來得到校驗(yàn)。有了這種校驗(yàn),應(yīng)用在被二次打包的時(shí)候會(huì)無法運(yùn)行。
? ??那這種方法的弊端是什么?舉一個(gè)有意思的例子。在懸崖的拐彎處都會(huì)有一個(gè)路標(biāo),用來正確指示方向。但如果有人故意搞破壞,把路標(biāo)指示方向弄反,那開車的人被誤導(dǎo)后,順著錯(cuò)誤的方向行駛,就會(huì)發(fā)生不幸的悲劇。
? ??這個(gè)例子的意思是,計(jì)算機(jī)在執(zhí)行指令的時(shí)候也是按照預(yù)先定義好的邏輯(開發(fā)者寫的)去執(zhí)行,然而如果破解者對開發(fā)者校驗(yàn)的地方近進(jìn)行了修改,那么計(jì)算機(jī)也會(huì)按照新的邏輯執(zhí)行,這種保護(hù)措施風(fēng)險(xiǎn)很大,所以也就逐漸沒落了。
封建社會(huì)時(shí)期——dex文件變形
? ??經(jīng)歷了兩個(gè)時(shí)代,開發(fā)者也逐漸提高了保護(hù)技能。于是很多做java出身的開發(fā)者,在經(jīng)過無數(shù)日夜的努力下?lián)u身一變成為了c、c++專家。越來越多的邏輯被寫入到c層,并且所有的校驗(yàn)也被移到c層,混淆也同樣存在。同時(shí),開發(fā)者開始對dex文件AndroidManifest文件做變形處理,這樣做的好處是既能保證應(yīng)用能正常運(yùn)行,也能使一些反編譯工具如apktool在反編譯時(shí)奔潰。但對dex文件和manifest文件的變形同樣有它的弱點(diǎn)?;臼烂嫔系膁ex變形都可以通過baksmali來得到smali,這樣破解者就可繼續(xù)分析。而manifset文件格式官方有明確的規(guī)范,破解者按照規(guī)范去解析,遇到不正確字節(jié)可以推敲,最終還是可以將其還原。
資本主義社會(huì)時(shí)期
? ??這是一個(gè)移動(dòng)互聯(lián)網(wǎng)高速發(fā)展的時(shí)期,但盜版和二次打包等問題也日益凸顯,在這個(gè)開放的時(shí)期,為了滿足開發(fā)者保護(hù)應(yīng)用的迫切需要,相繼出現(xiàn)了一些基于Android APP加固的第三方產(chǎn)品,通常他們的基本做法有:
? ??1.Dex保護(hù)
? ??(1)隱藏dex文件
? ??既然dex文件中包含了核心邏輯,那么把dex隱藏,再通過另外的方式加載起來,是不是就能達(dá)到保護(hù)dex的目的了呢?于是這成為一些第三方加固產(chǎn)品保護(hù)應(yīng)用的方式。他們通過加密甚至壓縮(早期是不存在壓縮的,只是單純的加密)方式把dex轉(zhuǎn)換為另外一個(gè)文件。而被加固后的apk里面的dex則是那些第三方加固產(chǎn)品用來啟動(dòng)和加載隱藏dex的入口,也就是殼。
? ??(2)對dex文件進(jìn)行變形
? ??這里所說的變形,不同于封建社會(huì)時(shí)期提到的變形。這種辦法不隱藏dex,而是讓dex保留在外面,但是當(dāng)破解者去分析這個(gè)dex的時(shí)候,會(huì)發(fā)現(xiàn)dex里面的內(nèi)容是不完整的。
? ??(3)對dex結(jié)構(gòu)進(jìn)行變形
? ??一些第三方加固產(chǎn)品開始嘗試這種方式,他們的保護(hù)方案中可能抽取了DexCode中的部分,然后對字節(jié)碼指令添加nop,或者連ClassDataItem和DexCode一同抽取,或者對上面提到的三個(gè)部分都做處理。抽取完之后,還要做修正、修復(fù)等工作,總之很煩鎖。因?yàn)閐ex運(yùn)行時(shí)有很多關(guān)于dex的校驗(yàn),即使校驗(yàn)通過還有一些偏移問題。
? ??Dex都被抽取修改后為什么還能運(yùn)行呢?那是因?yàn)樵谶\(yùn)行之前或者運(yùn)行之中對這個(gè)內(nèi)存中的dex做修正。修正工作也很復(fù)雜,一般選擇在運(yùn)行之前做修正,這樣可以減少很大的工作量,甚至可能還需要借助hook來幫忙。
? ??2.So保護(hù)
? ??(1)修改Elf頭、節(jié)表
? ??我們知道so其實(shí)是一個(gè)ELF文件,ELF文件有著自己的格式。有些第三方加固保護(hù)是對so文件進(jìn)行保護(hù),他們的做法是稍微修改一下ELF頭或者節(jié)表信息,因?yàn)檫@并不會(huì)影響程序的正常運(yùn)行。圖3和圖4是對ELF文件頭中的節(jié)頭表信息做了修改后,再用010 Editor打開,顯示的異常界面:
? ??接著我們用ida打開該ELF文件,發(fā)現(xiàn)該文件根本無法打開(一直卡在那里),如圖5和圖6所示:
? ??其次,還有修改程序頭表這種保護(hù)方式,如圖7 所示,對PT_NOTE段做了一些修改。在該段的屬性值中填充了一些無效的數(shù)字,導(dǎo)致逆向工具無法正常解析。由于系統(tǒng)并不會(huì)對PT_NOTE段進(jìn)行分析,防御逆向工具的同時(shí)保證了該文件能被系統(tǒng)正常加載。
圖7
? ??(2)選擇開源加殼工具
? ??最常用的當(dāng)屬UPX殼,因?yàn)樗С謅rm架構(gòu)的ELF加固。在加殼之后再對原文件做一些處理,這樣對破解者的分析工作又增加了一些難度。
? ??(3)進(jìn)程防調(diào)試、或增加調(diào)試難度
? ??有時(shí)候靜態(tài)分析是非常局限的,這個(gè)時(shí)候動(dòng)態(tài)分析的好處就體現(xiàn)出來了,然而動(dòng)態(tài)分析的核心就是調(diào)試,而調(diào)試一個(gè)進(jìn)程首先要ptrace這個(gè)進(jìn)程,如果能有效的防止進(jìn)程被ptrace,就能有效的防止動(dòng)態(tài)調(diào)試。當(dāng)然還有其他反調(diào)試技術(shù),或者增加調(diào)試難度等等。
社會(huì)主義時(shí)期
? ??這個(gè)時(shí)期,技術(shù)的發(fā)展與普及讓人人都是開發(fā)者成為可能。而破解者的破解技術(shù)和手段也在隨之變化。單一的應(yīng)用保護(hù)措施已經(jīng)無法有效的應(yīng)對破解者的攻擊,所以還需要從多重維度和深度對應(yīng)用進(jìn)行加固保護(hù)。
? ??在上面的資本主義時(shí)期提到的幾種保護(hù)措施中,遺留了很多問題,比如:
? ??1.隱藏dex遺留的問題
? ??首先dex是被完整隱藏起來的,一旦破解者得到了dex,就等于破解完成了一半。如果破解了加殼原理,就可以輕易做出脫殼機(jī)。另外就是實(shí)現(xiàn)自定義rom,這種方式可謂最為簡單,只需要在相關(guān)的點(diǎn)加一些代碼,然后編譯一個(gè)自己的rom,這樣在虛擬機(jī)中就可以順利的脫殼了。還有就是利用Inject原理將目標(biāo)進(jìn)程注入,代碼進(jìn)行hook系統(tǒng)函數(shù)來達(dá)到脫殼的目的。
? ??2.Dex結(jié)構(gòu)變形帶來的弊端
? ??隨著安卓5.0的發(fā)布,Art步入我們的視野。Art可以直接將dex編譯為本地指令運(yùn)行。
? ??可是它編譯時(shí)需要完整的dex,這怎么辦?或許有些第三方加固產(chǎn)品選擇了根本不編譯,當(dāng)然開發(fā)者和用戶不知道,因?yàn)樗憩F(xiàn)出來的是程序可以正確運(yùn)行,但是系統(tǒng)在Art模式下運(yùn)行的更快這種優(yōu)勢就永遠(yuǎn)得不到體現(xiàn)了。
? ??所以Dex結(jié)構(gòu)變形遺留的問題很明顯,即兼容性和Art模式下的編譯問題。
? ??3.ELF簡單修改遺留問題
? ??對應(yīng)修改ELF頭和節(jié)頭表信息的技巧很容易被識破和修復(fù),所以只能防住初級破解者。
? ??4.UPX方面的劣勢
? ??雖然upx是最為so加殼的首選,但是upx代碼邏輯復(fù)雜,很難達(dá)到定制,特別是讓它同時(shí)支持多種架構(gòu)。