1、網(wǎng)絡(luò)請(qǐng)求——裸奔的數(shù)據(jù)
無(wú)論是網(wǎng)頁(yè)還是APP,都不可避免與后臺(tái)服務(wù)進(jìn)行訪(fǎng)問(wèn),可能從服務(wù)器獲取數(shù)據(jù)或者提交數(shù)據(jù)到服務(wù)器,這時(shí)就需要客戶(hù)端發(fā)起網(wǎng)絡(luò)請(qǐng)求。由于http協(xié)議簡(jiǎn)單、靈活和無(wú)狀態(tài)等特點(diǎn),目前大部分應(yīng)用都是采用的http協(xié)議進(jìn)行的網(wǎng)絡(luò)請(qǐng)求。一個(gè)常見(jiàn)的網(wǎng)絡(luò)請(qǐng)求如下圖:

1.1 無(wú)處不在的安全隱患
因?yàn)閔ttp協(xié)議是明文傳輸?shù)?,所以上面的用?hù)名和密碼也是明文在網(wǎng)絡(luò)中傳輸?shù)?,在傳輸過(guò)程中的任何一個(gè)環(huán)節(jié),攻擊者都可以直接看到明文數(shù)據(jù)。當(dāng)然現(xiàn)在很多系統(tǒng)都不傳輸和保存明文賬號(hào)密碼,通常會(huì)采取MD5值傳輸和存儲(chǔ),之前比較出名的CSDN數(shù)據(jù)庫(kù)泄漏,就是因?yàn)槊艽a是明文保存,黑客可以方便的拿去撞庫(kù),加重了事件的嚴(yán)重性。近幾年MD5破解能力提高,例如黑客看到庫(kù)中一個(gè)密碼數(shù)量比較多,就可以嘗試去爆破,加上也可以直接用密碼的MD5值去撞庫(kù),所以現(xiàn)在通常生成MD5值時(shí)都需要加鹽,例如MD5(name+pwd)作為密碼存儲(chǔ),同樣的密碼生成的值是不一樣的,在一定程度上提高了安全性。
攻擊不一定需要用戶(hù)名密碼,或許可以直接打token和uid的主意。通過(guò)上圖可以看到,通過(guò)上圖可以看到,一旦用戶(hù)登錄后,服務(wù)器就通過(guò)token來(lái)標(biāo)識(shí)身份。如果這個(gè)token被黑客劫持了,他就可以冒充你的身份進(jìn)行攻擊,如果token機(jī)制設(shè)計(jì)不合理,攻擊者甚至可以直接暴力去撞token。大部分網(wǎng)站的機(jī)制也類(lèi)似,服務(wù)器通過(guò)一個(gè)sessionId標(biāo)識(shí)用戶(hù),攻擊者一旦拿到這個(gè)sessionId,就可以去冒充一個(gè)合法用戶(hù)。
當(dāng)然,雖說(shuō)這些數(shù)據(jù)明文傳輸,但是如果你不是網(wǎng)管、網(wǎng)絡(luò)運(yùn)營(yíng)商,想拿到這些數(shù)據(jù)也不是那么容易,要不然也不會(huì)有那么人在公共場(chǎng)合開(kāi)放WIFI去釣魚(yú)了。即使抓不到別人的數(shù)據(jù),也并不意味著什么也做不了,想想看我們能做什么?抓不到別人的數(shù)據(jù),可以抓自己的數(shù)據(jù),分析服務(wù)器接口,尋找設(shè)計(jì)漏洞做突破口。下面是一些應(yīng)用場(chǎng)景:
- 微信投票刷票。微信中充斥著各種投票活動(dòng),什么萌娃大賽、最美警察、舞蹈之星?;径际且粋€(gè)鏈接甩過(guò)來(lái),打開(kāi)先提示獲取你的公開(kāi)信息(昵稱(chēng)、頭像等),確認(rèn)后通常是一個(gè)90年代風(fēng)格粗糙的網(wǎng)頁(yè),找到對(duì)應(yīng)編號(hào)的參賽者后,勾選提交。做這些操作前,設(shè)置好你的代理服務(wù)器,看看投票時(shí)發(fā)送的請(qǐng)求參數(shù),多半情況下你會(huì)發(fā)現(xiàn)一些問(wèn)題,用postman驗(yàn)證你的想法,然后差不多花半個(gè)小時(shí),就能寫(xiě)一個(gè)刷票工具。這時(shí)你可以思考下,怎么設(shè)計(jì)才能讓投票程序更健壯。
- 微博xss事件。微博API本身是開(kāi)放的,通過(guò)xss漏洞,注入調(diào)用關(guān)注、轉(zhuǎn)發(fā)、私信API的js腳本。
- 微信、點(diǎn)評(píng)、微博等機(jī)器人。在很多行業(yè),大眾點(diǎn)評(píng)網(wǎng)站中商戶(hù)的好評(píng)差評(píng),對(duì)商戶(hù)的生意和口碑影響很大,于是出現(xiàn)了很多水軍刷好評(píng)和惡意詆毀對(duì)手的事件,人肉養(yǎng)號(hào)和刷評(píng)論很顯然成本比較高,加上活躍度越高的用戶(hù)級(jí)別越高,級(jí)別越高的用戶(hù)評(píng)論時(shí)對(duì)商戶(hù)打分的權(quán)重也越高,所以當(dāng)時(shí)有很多養(yǎng)機(jī)器人小號(hào)做不法勾當(dāng),直到后面公司投入很大資源成立專(zhuān)門(mén)的誠(chéng)信團(tuán)隊(duì)這種現(xiàn)象才好轉(zhuǎn)。微信公眾號(hào)也有同樣問(wèn)題,一個(gè)名人公眾號(hào)發(fā)篇文章才幾百的閱讀量,這樣多沒(méi)面子啊,花點(diǎn)錢(qián)找水軍刷刷量吧,印象中微信針對(duì)這個(gè)事也從政策和技術(shù)上整頓過(guò)好幾次了。微博就不多說(shuō)了,我甚至懷疑官方的態(tài)度,水清則無(wú)魚(yú)嘛。甚至連蘋(píng)果APP Store都不能幸免,不過(guò)只能人肉和眾包的形式。
1.2 使用https是否就萬(wàn)事大吉
https分單向認(rèn)證和雙向認(rèn)證,大部分的應(yīng)用場(chǎng)景是c/s模式,這時(shí)通常都是采用的單向認(rèn)證的方式,也就是說(shuō)可以保證客戶(hù)端拿到的數(shù)據(jù)是后臺(tái)發(fā)送的。這時(shí)想攻擊確實(shí)很難了,除非你能忽悠別人安裝并信任你的證書(shū),實(shí)際上也并不是做不到,很多人蹭wifi時(shí)或者在網(wǎng)上下載一些資源,系統(tǒng)提示要信任什么東西,看都不看就點(diǎn)確定。這些暫時(shí)不提,上面提到的那些攻擊,都依賴(lài)于對(duì)后臺(tái)接口的分析和調(diào)用,對(duì)于這類(lèi)攻擊者來(lái)說(shuō),你使用http和https是沒(méi)有區(qū)別的。
使用抓包工具時(shí),給目標(biāo)設(shè)備安裝并信任裝包工具的自簽名證書(shū),這時(shí)候就可以分析https請(qǐng)求了。下面是正常抓https請(qǐng)求的包和配置過(guò)證書(shū)后的抓包


1.3 使用簽名和加密數(shù)據(jù)
上面可以看到,https并不能阻擋攻擊者分析請(qǐng)求接口并發(fā)起攻擊,為了增加攻擊者分析請(qǐng)求的難度,通??梢圆捎脙煞N方式:
- 使用簽名。即給你的請(qǐng)求參數(shù)添加一個(gè)簽名,后臺(tái)服務(wù)接收到請(qǐng)求時(shí),先驗(yàn)證簽名,簽名不正確的話(huà),則不予處理。簽名規(guī)則五花八門(mén),大致策略就是根據(jù)請(qǐng)求參數(shù)做一些運(yùn)算最后生成一個(gè)唯一的字符串當(dāng)做sign,微信支付的簽名大家可以做一個(gè)參考:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3
- 數(shù)據(jù)加密。post到服務(wù)器和從服務(wù)器返回的數(shù)據(jù)都做加密,這樣的話(huà)即使攻擊者拿到你的數(shù)據(jù),他不知道你的加密算法就無(wú)能為力了。
上面說(shuō)的兩種方式可以同時(shí)使用,但是大家還需要考慮一個(gè)問(wèn)題:如何防止攻擊者獲取到你的簽名生成規(guī)則和加密算法,例如你加密使用的AES算法,你的秘鑰放在哪里呢?
2、反編譯,讓你的代碼沒(méi)有秘密
這里主要指Android項(xiàng)目。大家知道,很多應(yīng)用尤其是單機(jī)版游戲類(lèi),都只有iOS版本,沒(méi)有Android版本。一些聯(lián)網(wǎng)游戲,有Android版本用戶(hù)數(shù)據(jù)和iOS用戶(hù)數(shù)據(jù)也是隔離的。這些現(xiàn)象的原因,一方面是Android應(yīng)用分發(fā)的混亂,另一方面,就是比較低的反編譯和二次打包發(fā)布的門(mén)檻。
2.1 項(xiàng)目結(jié)構(gòu)
Android項(xiàng)目早期沒(méi)有自己?jiǎn)为?dú)的IDE工具,是使用Eclipse加ADT插件進(jìn)行開(kāi)發(fā),項(xiàng)目結(jié)構(gòu)跟其他Java項(xiàng)目一致,即一個(gè)workspace表示一個(gè)工程,里面一個(gè)一個(gè)的project表示子項(xiàng)目。后面google推出了基于IntelliJ IDEA的Android Studio,項(xiàng)目結(jié)構(gòu)也順其自然的變成了Project+moduled形式。雖然目錄層級(jí)有所變化,但是整體結(jié)構(gòu)變化不大。
我們可以看下圖,是一個(gè)典型Android項(xiàng)目,PermissionGrantor是項(xiàng)目名稱(chēng),里面有兩個(gè)子項(xiàng)目,分別是app和grantor,兩個(gè)子項(xiàng)目圖標(biāo)看起來(lái)不一樣,是因?yàn)樗麄円粋€(gè)是應(yīng)用項(xiàng)目,即編譯后可以生成一個(gè)可以在Android設(shè)備上運(yùn)行的應(yīng)用,另外一個(gè)是庫(kù)項(xiàng)目,可以生成一個(gè)被其他項(xiàng)目引用的aar庫(kù)。
我們看一下app項(xiàng)目即應(yīng)用項(xiàng)目,紅框標(biāo)注的是幾個(gè)比較重要的目錄,libs是用來(lái)放項(xiàng)目依賴(lài)庫(kù)的,java目錄是項(xiàng)目的代碼,res則是存放資源,包括圖片、布局、字符串等

最下面的AndroidManifest.xml可以理解成項(xiàng)目的配置文件,操作系統(tǒng)加載一個(gè)應(yīng)用,從哪里開(kāi)始執(zhí)行、每個(gè)頁(yè)面調(diào)用那個(gè)類(lèi)和都有哪些服務(wù)哪些權(quán)限,都需要在這里配置。從這里可以透露一個(gè)很重要的信息,就是應(yīng)用的入口和各個(gè)模塊甚至是服務(wù)的類(lèi),都可以從這里看到,而且是必須要配置到這里并且這個(gè)文件是要附帶到發(fā)布APK里面的。

2.2 編譯與反編譯
2.2.1 混淆
項(xiàng)目編譯正式包時(shí),默認(rèn)是開(kāi)啟混淆的,即類(lèi)名方法名會(huì)被混淆成a,b,c,d的樣子,增加破解著的難度。Android采用的Proguard的開(kāi)源方案,只能對(duì)java類(lèi)進(jìn)行混淆。上面的分析中我們知道,程序的啟動(dòng)類(lèi)(Application)和業(yè)務(wù)類(lèi)(Activity)都需要注冊(cè)到AndroidManifest.xml中,而混淆只能對(duì)java類(lèi)進(jìn)行混淆,并不支持xml這種配置文件,所以Android默認(rèn)對(duì)于Application、Activity、Service、UI相關(guān)的類(lèi)都是不混淆的,而一些通過(guò)字符串反射生成類(lèi)的地方也不能混淆(網(wǎng)絡(luò)數(shù)據(jù)轉(zhuǎn)為本地java對(duì)象),而jni調(diào)用方法也不能混淆。下圖是QQ閱讀反編譯后的一個(gè)Activity和數(shù)據(jù)對(duì)象。
通過(guò)上面分析,我們發(fā)現(xiàn)雖然Android引入了混淆技術(shù),但是由于當(dāng)前混淆方案的缺陷和Android系統(tǒng)框架中大量使用反射技術(shù),使得很多重要的類(lèi)不能混淆,這極大的降低了反編譯后閱讀源碼的成本。1.3中提到的使用簽名和加密算法,這時(shí)你會(huì)發(fā)現(xiàn),被破解也不是特別的難,為了增加破解難度,我們可以把算法放到native代碼中,即用C/C++實(shí)現(xiàn)算法,通過(guò)jni調(diào)用。


2.2.2 編譯
項(xiàng)目編譯成apk文件,主要分為以下幾部分:
xml 編譯為二進(jìn)制文件。xml中所有字符串都會(huì)被放到一個(gè)資源池中,原來(lái)使用字符串的地方會(huì)被替換成資源的地址。所以xml編譯為二進(jìn)制不僅可以減少占用的空間,而且可以提高加載速度。
生成resource.arsc資源索引表
java生成dex文件

2.2.3 簽名
APP編譯成apk包后,必須對(duì)包進(jìn)行簽名才能在手機(jī)上安裝。我們分析簽名后的包會(huì)發(fā)現(xiàn)里面多了MANIFEST.MF、CERT.SF和CERT.RSA三個(gè)文件。我們直接用文本編輯器打開(kāi)MANIFEST.MF如下圖:

可以看到這個(gè)文件里面存儲(chǔ)了每一個(gè)資源的SHA1摘要的base64值,這里就可以解釋你直接替換了apk包里面的某個(gè)資源為什么apk無(wú)法安裝,因?yàn)槌绦蛟诎惭b時(shí)驗(yàn)證資源的摘要跟MANIFEST.MF中的不一致,可以判斷出這個(gè)包被人動(dòng)了手腳。
我們繼續(xù)用文本編輯器打開(kāi)CERT.SF,如下圖:

我們會(huì)發(fā)現(xiàn)除了最上面多了一個(gè)SHA1-Digest-Manifest值,下面的文件跟第一個(gè)文件沒(méi)區(qū)別,我們可以測(cè)試得知,這個(gè)值就是第一個(gè)文件MANIFEST.MF的SHA1摘要的base64值。(目前最新實(shí)現(xiàn)與原來(lái)已有些不同,可以參考這篇文章和這篇文章 所以上面提到的,替換APK資源文件后,如果你同時(shí)更新MANIFEST.MF中對(duì)應(yīng)的值也不行,因?yàn)榇藭r(shí)通不過(guò)CERT.SF的驗(yàn)證。那么我同時(shí)修改CERT.SF中的值呢?我們可以繼續(xù)看第三個(gè)文件CERT.RSA,我們發(fā)現(xiàn)用文本編輯器打開(kāi),它是二進(jìn)制文件,可以通過(guò)下面的命令打開(kāi)此文件:
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text
打開(kāi)后的內(nèi)容為:

網(wǎng)上有資料解析這個(gè)結(jié)構(gòu),我們不展開(kāi)分析,只要知道,上面那一坨16進(jìn)制編碼是簽名的公鑰,下面那一坨是簽名,即用你keystore文件中的私鑰對(duì)上面的域和值進(jìn)行加密得到的結(jié)果。程序安裝時(shí)使用上面的公鑰進(jìn)行校驗(yàn),如果你拿不到對(duì)方的私鑰就沒(méi)辦法對(duì)簽名進(jìn)行偽造。這就回答了上面拋出的問(wèn)題,替換apk包中的資源后,同時(shí)修改MANIFEST.MF和CERT.SF也無(wú)法通過(guò)驗(yàn)證。
但是如果我同時(shí)把上面的公鑰也替換了呢?答案是當(dāng)然可以通過(guò)驗(yàn)證啊。因?yàn)槟愕倪@一系列動(dòng)作等同于對(duì)APK重新簽名了,不過(guò)使用的是你自己的私鑰。Android采用的是自簽名的證書(shū),所以如果有人拿到了你的APP,用自己的keystore重新簽名然后發(fā)布,用戶(hù)并不知道他是山寨的還是正版的。這就解釋了為什么很多單機(jī)游戲都不做Android版本的,你辛苦做一個(gè)收費(fèi)的游戲,攻擊者很容易破解在里面加點(diǎn)廣告,然后再二次打包發(fā)布。一些不愿意花錢(qián)買(mǎi)游戲的用戶(hù)只需要忍受下廣告就可以免費(fèi)玩游戲了。通過(guò)這里的分析,我們知道攻擊者很難偽造我們的簽名,所以我們可以在程序中插入簽名檢查的代碼,提高攻擊門(mén)檻。
2.3 反編譯
上面已經(jīng)把APK結(jié)構(gòu)分析的差不多了,反編譯要做的工作就是反匯編.dex和還原xml文件。我們可以使用apktool直接對(duì)一個(gè)apk進(jìn)行反編譯,可以得到還原后的xml文件和.smali文件。這里的smali文件是可以運(yùn)行在android虛擬機(jī)上的匯編語(yǔ)言,讀起來(lái)還是有些晦澀的,如果有讀源碼的需求,可以直接解壓apk包,使用dex2jar工具直接反編譯dex文件,可以得到反編譯后的class文件,即我們能得到反編譯后的java源碼。我們1.3中提到的加密算法和秘鑰,就可以通過(guò)分析反編譯后的源碼去獲取。為了不讓別人獲取類(lèi)似敏感信息,很多人選擇這些信息繼續(xù)向底層放到lib.so中,下面一節(jié)我們會(huì)介紹。
3、NDK與反匯編
3.1 NDK
NDK全稱(chēng)為Native Development Kit,翻譯過(guò)來(lái)叫原生開(kāi)發(fā)工具包,官方解釋是可以在Android中使用C/C++的工具。我沒(méi)找到這里Native的詳細(xì)解釋?zhuān)瑐€(gè)人理解常規(guī)Android程序是運(yùn)行在虛擬機(jī)上面的,而Native指直接運(yùn)行在操作系統(tǒng)上面的程序,可以調(diào)用操作系統(tǒng)的API。一般情況下我們沒(méi)有必要使用NDK,官方也提到了使用native開(kāi)發(fā)會(huì)增加開(kāi)發(fā)過(guò)程的復(fù)雜性。但是對(duì)于一些計(jì)算密集型的應(yīng)用,例如游戲、圖像處理,使用NDK能提高運(yùn)算性能。還有一些情況為了復(fù)用現(xiàn)有庫(kù)或者跨平臺(tái)庫(kù),也會(huì)選擇NDK。上面提到的一些核心算法和秘鑰,大家選擇放到native層,潛意識(shí)中也是默認(rèn)native的破解難度比java高,還有欺負(fù)大部分Android程序員不會(huì)寫(xiě)C/C++代碼:)
我們可以創(chuàng)建一個(gè)新工程,創(chuàng)建時(shí)勾選上"Include C++ support",如下圖:

這時(shí)會(huì)創(chuàng)建一個(gè)支持NDK的默認(rèn)工程,項(xiàng)目里包含從C++代碼中獲取一個(gè)字符串的demo:

我們編譯出apk并反編譯這個(gè)程序如下圖,會(huì)發(fā)現(xiàn)包里面多了一堆libnative-lib.so(其實(shí)只是一個(gè)庫(kù),為了支持不同的CPU架構(gòu)編程出了多個(gè)版本)。

字符串的生成的實(shí)現(xiàn)放到了這個(gè)so庫(kù)里面,相比較直接在java代碼中生成字符串,破解起來(lái)的確麻煩了些。這個(gè)時(shí)候如果想破解拿到這個(gè)字符串,該怎么辦呢?
一個(gè)簡(jiǎn)單的辦法,直接寫(xiě)java代碼,通過(guò)jni調(diào)用這個(gè)so的方法。這尼瑪就尷尬了,本來(lái)封裝so是為了隱藏?cái)?shù)據(jù),結(jié)果倒好,別人才不管你怎么實(shí)現(xiàn),把你直接拿來(lái)用。為了避免這種尷尬,我們可以在so中判斷當(dāng)前應(yīng)用的簽名,前面分析過(guò),只要?jiǎng)e人拿不到你的keystore就沒(méi)辦法偽造你的簽名。如果沒(méi)辦法直接調(diào)用這個(gè)so,只能想辦法破解才能洞察到里面隱藏的秘密了,下面我們談一下怎么來(lái)破解。
3.2 PE/ELF和反匯編
上面提到了我們需要破解so文件才能獲取里面的信息,在破解之前我們要先理解so文件到底是什么。這里我們我們需要了解一種文件格式,即Windows系統(tǒng)中的PE(Portable Executable)和Linux系統(tǒng)下的ELF(Executable Linkable Format),看全稱(chēng)基本了解這種文件的用途。其實(shí)在Windows系統(tǒng)上我們平時(shí)運(yùn)行的.exe安裝文件和使用共(破)享(解)軟件時(shí)用來(lái)覆蓋的.dll動(dòng)態(tài)鏈接庫(kù)文件,都是PE格式文件。在Linux系統(tǒng)上(我們可以把Android理解為L(zhǎng)inux系統(tǒng))的.o目標(biāo)文件、.a靜態(tài)連接庫(kù)和.so動(dòng)態(tài)連接庫(kù),都屬于ELF文件。如下圖所示,一段C程序編譯生成ELF文件后的結(jié)構(gòu)

當(dāng)然我們直接用文本編輯器打開(kāi)so文件,看到的是如下二進(jìn)制文件:

根據(jù)ELF文件格式的定義,可以把這個(gè)二進(jìn)制文件還原為圖3.4右邊的結(jié)構(gòu)。這些細(xì)節(jié)很復(fù)雜我們也沒(méi)必要去全部弄清楚,我們可以使用一些命令直接查看ELF文件。以圖3.2中的C++代碼生成的so為例,我們輸入:
readelf -a libnative-lib.so
可以看到結(jié)果:

內(nèi)容很長(zhǎng),不了解ELF格式的話(huà)很難看懂(我這里在使用“greadelf”是因?yàn)槭褂玫膍ac系統(tǒng)自己安裝的類(lèi)似工具),我們可以先大概看一下,這里的“節(jié)頭”其實(shí)就是對(duì)應(yīng)的圖3.4中的section,我們可以查看第12個(gè)segment——.rodata:

我們發(fā)現(xiàn)了之前辛苦藏到so中的字符串"Hello from C++"。如果想看代碼實(shí)現(xiàn),可以使用objdump命令,能看到反匯編后的代碼。
現(xiàn)在我們可以理解ELF文件已經(jīng)是機(jī)器指令了,我們?nèi)绻肟匆恍┐a邏輯,要么像機(jī)器一樣讀機(jī)器指令,要么把這些機(jī)器指令反編譯成人類(lèi)方便閱讀的匯編代碼(匯編語(yǔ)言人類(lèi)也很難讀的好吧),這個(gè)過(guò)程我們就是反匯編。
當(dāng)然真正去破解一些so文件時(shí),使用上面的辦法效率太低,這是可以去使用一些專(zhuān)業(yè)的破解工具,里面集成了很多很強(qiáng)大的功能,可以大大提高工作效率,例如使用IDA直接把so打開(kāi),我們可以很方便的定位到j(luò)ni函數(shù):

從這個(gè)例子的分析,我們?yōu)榱嗽黾悠平怆y度,可以動(dòng)態(tài)注冊(cè)jni函數(shù)并且自定義函數(shù)名,避免破解者一眼就找到Java_com_xxx這樣的native函數(shù)。另外一點(diǎn)就是要隱藏在字符串,不可以直接明文寫(xiě)在代碼中,至少做個(gè)拼接吧,或者添加一定的邏輯動(dòng)態(tài)生成。大家可以想一下,還有沒(méi)有其他的辦法增加破解難度?
4、加殼與脫殼
通過(guò)上面的分析我們可以知道,無(wú)論是編譯java代碼生成的dex文件,還是編譯C/C++代碼生成的so文件,反編譯成本都不是特別的高,如果想增加破解難度,還能做什么呢?其實(shí)這個(gè)問(wèn)題一直存在,大家想想從十幾年前的PC時(shí)代,大部分人使用的都是windows,當(dāng)時(shí)大家使用的office、photoshop有幾個(gè)不是破解版的?因?yàn)楫?dāng)時(shí)網(wǎng)絡(luò)不發(fā)達(dá),很多游戲和工具軟件都是本地驗(yàn)證授權(quán)的,再加上法律監(jiān)管空白,軟件破解行業(yè)甚是紅火。
在當(dāng)時(shí)就有了加殼脫殼這個(gè)說(shuō)法,看一些破解軟件的文章時(shí),第一步基本都是脫殼。加殼直觀(guān)理解就是給程序加一層殼,可以用來(lái)對(duì)原程序進(jìn)行資源壓縮、防調(diào)試、防注入、防反編譯,也就是說(shuō)通過(guò)一個(gè)殼把原來(lái)的程序保護(hù)了起來(lái)。我們知道一個(gè)常規(guī)Android程序它的所有代碼都在dex文件中,程序啟動(dòng)時(shí)要先把這個(gè)dex文件載入到內(nèi)存中,所以如果要加殼的話(huà),主要工作就是把原dex文件加密或者隱藏起來(lái),放一個(gè)新的殼dex到apk中,程序啟動(dòng)時(shí)運(yùn)行這個(gè)殼dex,然后這個(gè)殼dex在運(yùn)行時(shí)再加載原dex,用一張圖表示如下:

其實(shí)這時(shí)候我們發(fā)現(xiàn),破解原dex的工作變成了破解殼dex了,最終的原理是一樣的,早期的梆梆、360等公司的加固方案都被人破解,網(wǎng)上能查到破解步驟。當(dāng)然他們的加固方案升級(jí)很快,網(wǎng)上看的破解方案對(duì)于新的加固方案基本已經(jīng)無(wú)效。我們使用騰訊的樂(lè)固加密一個(gè)不包含so庫(kù)的APK后反編譯后可以看到如下:


我們可以看到程序一開(kāi)始就加載了libshella.so庫(kù),這里我們可以推測(cè)我們的原dex被加密為了mix.dex和mixz.dex,dex的動(dòng)態(tài)還原方案的實(shí)現(xiàn)放到了libshell.so庫(kù)中,即dex的加殼方案放到了so實(shí)現(xiàn),再次佐證了大家公認(rèn)so的破解難度比較高。這里我測(cè)試發(fā)現(xiàn)這兩個(gè)so使用IDA反匯編工具已經(jīng)無(wú)法直接打開(kāi)了,很顯然這個(gè)so是加過(guò)殼的。關(guān)于so的脫殼,我也是小白,就不班門(mén)弄斧了,這里樂(lè)固.so V2.8版本的脫殼方案(樂(lè)固目前最新是V2.10),可以證明上面我們的推測(cè)是正確的,大家有興趣可以看一下https://bbs.pediy.com/thread-217556.htm
補(bǔ)充: 這是一年前的文章,當(dāng)時(shí)認(rèn)為加固是比較安全的方案,畢竟逆向so成本非常高,后面發(fā)現(xiàn)使用像xposed框架這樣的hook技術(shù),類(lèi)似于降維打擊,可以繞過(guò)加固技術(shù)輕松獲取到dex文件。目前的樂(lè)固、360等大廠(chǎng)加固都可以繞過(guò),從原理上看,加固技術(shù)對(duì)于這種hook技術(shù)獲取dex也沒(méi)有什么好辦法,作為APP的作者,需要加強(qiáng)hook方面的防御來(lái)提高加固技術(shù)的安全性,后面有時(shí)間的話(huà)我會(huì)寫(xiě)一篇文章介紹這方面的攻防。
參考文章:
http://blog.csdn.net/luoshengyang/article/details/8744683
http://blog.csdn.net/jiangwei0910410003/article/details/50402000
http://www.cnblogs.com/LiuYanYGZ/p/5574602.html
http://www.cnblogs.com/EliteDci/p/5578901.html