Android APP 防破解進化史

http://tech.it168.com/a2014/0425/1616/000001616976.shtml 
Android平臺以其免費和開源的特性使其佔據了移動領域大半壁江山,越來越的人投身到移動應用開發中,但本文恐怕要先給Android應用開發者潑盆冷水,據360發佈的《2014年中國手機安全狀況報告》顯示,2014全年,360互聯網安全中心累計監測到Android用戶感染惡意程序3.19億人次,平均每天惡意程序感染量達到了87.5萬人次。同時,Android應用被破解和盜版等事件也層出不窮。

  很明顯,Android平臺已經成爲惡意程序和破解者攻擊的衆矢之的,於是越來越多的Android開發者開始意識到應用安全的重要性。如何捍衛自己苦心開發的應用安全,開發者們都使用過哪些保護手段, 360加固保(http://jiagu.360.cn/)技術工程師爲大家一一分析。

  原始社會時期——代碼混淆

  最早的應用保護當屬代碼混淆,谷歌官方發佈的sdk中就包含ProGuard這種混淆工具。混淆工具會把你用java語言編寫的代碼的類名、變量名混淆爲自己定義的格式,這樣可以增加破解者在破解時閱讀難度。

  圖1是用ProGuard混淆過的dex文件截圖,從圖中可以看到,左側的類名大多都變成了a、b等這樣自定義字母的形式。在未混淆前,破解者可以根據一個類名叫做HttpGet的文件,大致猜測出它是做http get相關的。而混淆後,變成了a等自定義類名,破解者無法猜測它的含義,增加了閱讀難度。

  

  圖1

  但代碼混淆只是簡單的改變類名或者變量的名,只要能找dex,反編譯爲smali或者java,花些時間還是可以輕鬆破解的。如果說不用混淆工具我們破解一個apk需要2兩天,那麼用了這個工具,破解者可能需要4天,只是時間成本增加了。

  奴隸社會時期——自我校驗

  經過漫長的混淆時期,開發者發現他們的應用還是照常被破解。於是新的保護方式又出現了——自我校驗。

  簡單說,自我校驗就是在程序中加一些對自己應用的完整性校驗,可以藉助簽名、或計算自己應用dex的md5值等等來完成。有些開發者直接把校驗功能加入到dex中,有些則是通過http協議請求相關服務來得到校驗。有了這種校驗,應用在被二次打包的時候會無法運行。

  那這種方法的弊端是什麼?舉一個有意思的例子。在懸崖的拐彎處都會有一個路標,用來正確指示方向。但如果有人故意搞破壞,把路標指示方向弄反,那開車的人被誤導後,順着錯誤的方向行駛,就會發生不幸的悲劇。

  這個例子的意思是,計算機在執行指令的時候也是按照預先定義好的邏輯(開發者寫的)去執行,然而如果破解者對開發者校驗的地方近進行了修改,那麼計算機也會按照新的邏輯執行,這種保護措施風險很大,所以也就逐漸沒落了。

  封建社會時期——dex文件變形

  經歷了兩個時代,開發者也逐漸提高了保護技能。於是很多做java出身的開發者,在經過無數日夜的努力下搖身一變成爲了c、c++專家。越來越多的邏輯被寫入到c層,並且所有的校驗也被移到c層,混淆也同樣存在。同時,開發者開始對dex文件AndroidManifest文件做變形處理,這樣做的好處是既能保證應用能正常運行,也能使一些反編譯工具如apktool在反編譯時奔潰。由圖2可見, apktool在反編譯時完全失去了作用。

  

  圖2

  但對dex文件和manifest文件的變形同樣有它的弱點。基本世面上的dex變形都可以通過baksmali來得到smali,這樣破解者就可繼續分析。而manifset文件格式官方有明確的規範,破解者按照規範去解析,遇到不正確字節可以推敲,最終還是可以將其還原。

  資本主義社會時期

  這是一個移動互聯網高速發展的時期,但盜版和二次打包等問題也日益凸顯,在這個開放的時期,爲了滿足開發者保護應用的迫切需要,相繼出現了一些基於Android APP加固的第三方產品,通常他們的基本做法有:

  1. Dex保護

  (1) 隱藏dex文件

  既然dex文件中包含了核心邏輯,那麼把dex隱藏,再通過另外的方式加載起來,是不是就能達到保護dex的目的了呢?於是這成爲一些第三方加固產品保護應用的方式。

  他們通過加密甚至壓縮(早期是不存在壓縮的,只是單純的加密)方式把dex轉換爲另外一個文件。而被加固後的apk裏面的dex則是那些第三方加固產品用來啓動和加載隱藏dex的入口,也就是殼。

  (2) 對dex文件進行變形

  這裏所說的變形,不同於封建社會時期提到的變形。這種辦法不隱藏dex,而是讓dex保留在外面,但是當破解者去分析這個dex的時候,會發現dex裏面的內容是不完整的。

  (3) 對dex結構進行變形

  此類方法是比較複雜的,瞭解dex結構的人應該很清楚,dex結構中包含DexClassDef、ClassDataItem、DexCode,這些是dalvik虛擬機運行一個dex必不可少的部分,特別是DexCode,DexCode包含了虛擬機運行的字節碼指令。

  部分第三方加固產品開始嘗試這種方式,他們的保護方案中可能抽取了DexCode中的部分,然後對字節碼指令添加nop,或者連ClassDataItem和DexCode一同抽取,或者對上面提到的三個部分都做處理。抽取完之後,還要做修正、修復等工作,總之很煩鎖。因爲dex運行時有很多關於dex的校驗,即使校驗通過還有一些偏移問題。

  Dex都被抽取修改後爲什麼還能運行呢?那是因爲在運行之前或者運行之中對這個內存中的dex做修正。修正工作也很複雜,一般選擇在運行之前做修正,這樣可以減少很大的工作量,甚至可能還需要藉助hook來幫忙。

  2. So保護

  (1) 修改Elf頭、節表

  我們知道so其實是一個ELF文件,ELF文件有着自己的格式。有些第三方加固保護是對so文件進行保護,他們的做法是稍微修改一下ELF頭或者節表信息,因爲這並不會影響程序的正常運行。

  圖3和圖4是對ELF文件頭中的節頭表信息做了修改後,再用010 Editor打開,顯示的異常界面:

  

  圖3

  

  圖4

  接着我們用ida打開該ELF文件,發現該文件根本無法打開(一直卡在那裏),如圖5和圖6所示:

  

  圖5

  

  圖6

  其次,還有修改程序頭表這種保護方式,如圖7 所示,對PT_NOTE段做了一些修改。在該段的屬性值中填充了一些無效的數字,導致逆向工具無法正常解析。由於系統並不會對PT_NOTE段進行分析,防禦逆向工具的同時保證了該文件能被系統正常加載。

  

  圖7

  (2) 選擇開源加殼工具

  最常用的當屬UPX殼,因爲它支持arm架構的ELF加固。在加殼之後再對原文件做一些處理,這樣對破解者的分析工作又增加了一些難度。

  (3) 進程防調試、或增加調試難度

  有時候靜態分析是非常侷限的,這個時候動態分析的好處就體現出來了,然而動態分析的核心就是調試,而調試一個進程首先要ptrace這個進程,如果能有效的防止進程被ptrace,就能有效的防止動態調試。當然還有其他反調試技術,或者增加調試難度等等。

  社會主義時期

  這個時期,技術的發展與普及讓人人都是開發者成爲可能。而破解者的破解技術和手段也在隨之變化。單一的應用保護措施已經無法有效的應對破解者的攻擊,所以還需要從多重維度和深度對應用進行加固保護。

  在上面的資本主義時期提到的幾種保護措施中,遺留了很多問題,比如:

  (1) 隱藏dex遺留的問題

  首先dex是被完整隱藏起來的,一旦破解者得到了dex,就等於破解完成了一半。如果破解了加殼原理,就可以輕易做出脫殼機。

  另外就是實現自定義rom,這種方式可謂最爲簡單,只需要在相關的點加一些代碼,然後編譯一個自己的rom,這樣在虛擬機中就可以順利的脫殼了。

  還有就是利用Inject原理將目標進程注入,代碼進行hook系統函數來達到脫殼的目的。

  (2) Dex結構變形帶來的弊端

  隨着安卓5.0的發佈,Art步入我們的視野。Art可以直接將dex編譯爲本地指令運行。

  可是它編譯時需要完整的dex,這怎麼辦?或許有些第三方加固產品選擇了根本不編譯,當然開發者和用戶不知道,因爲它表現出來的是程序可以正確運行,但是系統在Art模式下運行的更快這種優勢就永遠得不到體現了。

  所以Dex結構變形遺留的問題很明顯,即兼容性和Art模式下的編譯問題。

  (3) ELF簡單修改遺留問題

  對應修改ELF頭和節頭表信息的技巧很容易被識破和修復,所以只能防住初級破解者。

  (4) UPX方面的劣勢

  雖然upx是最爲so加殼的首選,但是upx代碼邏輯複雜,很難達到定製,特別是讓它同時支持多種架構。

  基於上述原因一些第三方加固產品只是簡單的利用upx加殼,並修改一些數據。不過很容易被有upx經驗的人識破並脫殼。

  安全防護當然不是絕對的,但既然能發現這些遺留問題和弊端,就一定能找到相應的解決方案。據360加固保(http://jiagu.360.cn/)技術工程師介紹,一款能防得住破解者攻擊、兼容性好、能體現系統各優勢的加固產品就是值得開發者選擇的好產品。



準備編譯環境:http://my.oschina.net/u/2424583/blog/509634

?
1
2
3
4
1、zlib-1.2.8.tar.gz
2、ucl-1.03.tar.gz
3、lzma443.tar.bz2
4、upx-hg-d9e7cb4b5485.tar.gz  https://www.pysol.org:4443/hg/upx.hg

編譯UPX設置環境變量:

?
1
2
3
4
5
export UPX_UCLDIR=/usr/local/android/upx/ucl-1.03
export UPX_ZLIBDIR=/usr/local/android/upx/zlib-1.2.8
export UPX_LZMADIR=/usr/local/android/upx/lzma
export UPX_LZMA_VERSION=0x443
export UPX_DIR=/usr/local/android/upx/upx-hg-d9e7cb4b5485

提示幾點:

1、upx使用上面給的鏈接下載,這個版本修復了加固SO後無法在手機上運行的錯誤

2、編譯時提示找不到libz庫,需要在UPXDIR/src/MakeFile中添加

?
1
2
INCLUDES += -I$(UPX_ZLIBDIR)
LIBS += $(addprefix -L,$(dir $(wildcard $(UPX_ZLIBDIR)/libz$(libext))))

最後在UPX根目錄使用make all編譯,編譯完成後會在src目錄下生成upx.out

準備JNI環境

使用編譯好的Upx.out將jni生成的.so文件加固後放入APK中即可在手機上運行起來。

加固語法:

?
1
2
3
$./upx.out -f -o libjin_upx.so libjni.so
.....
packed 1 file.

杯具的Android版UPX移植筆記


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章