Android 資源混淆的方案及注意事項(xiàng)
原理
Android的資源類型是很多的,比如說(shuō)drawable,string,layout等,aapt在打包時(shí),會(huì)將這些資源的名稱,id和位置打包進(jìn)一個(gè)resources.arsc包。 通過(guò)AndroidStudio可以查看resouces.arsc文件的內(nèi)容。
AndResGuard大致上做的就是修改資源的名稱和路徑,修改為a b c這種簡(jiǎn)短的名稱。
注意事項(xiàng)
如果你的資源,存在使用插件化的方式加載的,即:使用名稱去找id,再用id去加載資源,由于資源的名稱已經(jīng)修改過(guò)了,所以會(huì)無(wú)法找到id。這種情況不能混淆??蚣苤刑峁┝颂砑影酌麊蔚姆椒?。 但是三方sdk中隱藏的插件化方式有點(diǎn)防不勝防。官方提供了常見(jiàn)的sdk白名單
使用方法
我使用的是gradle集成的方式
1.添加gradle配置
2.設(shè)置白名單,我設(shè)置了除了layout以外所有的資源不進(jìn)行混淆,因?yàn)槲业男枨笫菓?yīng)付安全監(jiān)測(cè),并且我們的項(xiàng)目中存在圖片插件加載,為了降低后期維護(hù)成本,就不進(jìn)行混淆了。
3.執(zhí)行命令:resguardRelease 與assemble類似
具體可以參考github
一些細(xì)節(jié)
- mappingFile要不要加?我選擇不加,加了之后,會(huì)keep住資源的路徑,如果對(duì)增量包大小有要求的,可以加。不加的話,包體積可以進(jìn)一步減小,并在一定程度上提高反編譯的難度。
- mergeDuplicationedRes要不要加?我是加的。是否會(huì)造成什么問(wèn)題?應(yīng)該是不會(huì)的。因?yàn)榭蚣鼙举|(zhì)上修改的是圖片的指向的路徑,圖片的名稱和id都沒(méi)有修改,所以不管是正常引用和插件化加載都是沒(méi)問(wèn)題的。
附:美團(tuán)的資源混淆方案
Android查找資源的流程
在Android系統(tǒng)中,每一個(gè)應(yīng)用程序一般都會(huì)配置很多資源,用來(lái)適配不同密度、大小和方向的屏幕,以及適配不同的國(guó)家、地區(qū)和語(yǔ)言等等。這些資源是在應(yīng)用程序運(yùn)行時(shí)自動(dòng)根據(jù)設(shè)備的當(dāng)前配置信息進(jìn)行適配的。這也就是說(shuō),給定一個(gè)相同的資源ID,在不同的設(shè)備配置之下,查找到的可能是不同的資源。
這個(gè)查找過(guò)程對(duì)應(yīng)用程序來(lái)說(shuō),是完全透明的,這個(gè)過(guò)程主要是靠Android資源管理框架來(lái)完成的,而Android資源管理框架實(shí)際是由AssetManager和Resources兩個(gè)類來(lái)實(shí)現(xiàn)的。其中,Resources類可以根據(jù)ID來(lái)查找資源,而AssetManager類根據(jù)文件名來(lái)查找資源。事實(shí)上,如果一個(gè)資源ID對(duì)應(yīng)的是一個(gè)文件,那么Resources類是先根據(jù)ID來(lái)找到資源文件名稱,然后再將該文件名稱交給AssetManager類來(lái)打開(kāi)對(duì)應(yīng)的文件的。
基本流程如下圖:
通過(guò)上圖我們可以看到Resources是通過(guò)resources.arsc把Resource的ID轉(zhuǎn)化成資源文件的名稱,然后交由AssetManager來(lái)加載的。
而Resources.arsc這個(gè)文件是存放在APK包中的,他是由AAPT工具在打包過(guò)程中生成的,他本身是一個(gè)資源的索引表,里面維護(hù)者資源ID、Name、Path或者Value的對(duì)應(yīng)關(guān)系,AssetManager通過(guò)這個(gè)索引表,就可以通過(guò)資源的ID找到這個(gè)資源對(duì)應(yīng)的文件或者數(shù)據(jù)。
AAPT
AAPT是Android Asset Packaging Tool的縮寫,它存放在SDK的tools/目錄下,AAPT的功能很強(qiáng)大,可以通過(guò)它查看查看、創(chuàng)建、更新壓縮文件(如 .zip文件,.jar文件, .apk文件), 它也可以把資源編譯為二進(jìn)制文件,并生成resources.arsc, AAPT這個(gè)工具在APK打包過(guò)程中起到了非常重要作用,在打包過(guò)程中使用AAPT對(duì)APK中用到的資源進(jìn)行打包,這里不對(duì)AAPT這個(gè)工具做過(guò)多的討論,只看一下AAPT這個(gè)工具在打包過(guò)程中起到的作用,下圖是AAPT打包的流程:
AAPT這個(gè)工具在打包過(guò)程中主要做了下列工作:
- 把”assets”和”res/raw”目錄下的所有資源進(jìn)行打包(會(huì)根據(jù)不同的文件后綴選擇壓縮或不壓縮),而”res/”目錄下的其他資源進(jìn)行編譯或者其他處理(具體處理方式視文件后綴不同而不同,例如:”.xml”會(huì)編譯成二進(jìn)制文件,”.png”文件會(huì)進(jìn)行優(yōu)化等等)后才進(jìn)行打包;
- 會(huì)對(duì)除了assets資源之外所有的資源賦予一個(gè)資源ID常量,并且會(huì)生成一個(gè)資源索引表resources.arsc;
- 編譯AndroidManifest.xml成二進(jìn)制的XML文件;
- 把上面3個(gè)步驟中生成結(jié)果保存在一個(gè)*.ap_文件,并把各個(gè)資源ID常量定義在一個(gè)R.java中;
資源混淆
我們知道在系統(tǒng)的Proguard中,對(duì)APK中資源文件名使用簡(jiǎn)短無(wú)意義名稱進(jìn)行替換,給破解者制造困難,從而做到資源的相對(duì)安全。通過(guò)閱讀AAPT編譯資源的代碼,我們發(fā)現(xiàn)修改AAPT在處理資源文件相關(guān)的源碼是能夠做到資源文件名的替換,下面是Resource.cpp中makeFileResources()的修改的代碼片段:
static status_t makeFileResources(Bundle* bundle, const sp<AaptAssets>& assets, ResourceTable* table, const sp<ResourceTypeSet>& set, const char* resType) { String8 type8(resType); String16 type16(resType); bool hasErrors = false; ResourceDirIterator it(set, String8(resType)); ssize_t res; while ((res=it.next()) == NO_ERROR) { if (bundle->getVerbose()) { printf(" (new resource id %s from %s)\n", it.getBaseName().string(), it.getFile()->getPrintableSource().string()); } String16 baseName(it.getBaseName()); const char16_t* str = baseName.string(); const char16_t* const end = str + baseName.size(); while (str < end) { if (!((*str >= 'a' && *str <= 'z') || (*str >= '0' && *str <= '9') || *str == '_' || *str == '.')) { fprintf(stderr, "%s: Invalid file name: must contain only [a-z0-9_.]\n", it.getPath().string()); hasErrors = true; } str++; } String8 resPath = it.getPath(); resPath.convertToResPath(); String8 obfuscationName; String8 obfuscationPath = getObfuscationName(resPath, obfuscationName); table->addEntry(SourcePos(it.getPath(), 0), String16(assets->getPackage()), type16, baseName, // String16(obfuscationName), String16(obfuscationPath), // resPath NULL, &it.getParams()); assets->addResource(it.getLeafName(), obfuscationPath/*resPath*/, it.getFile(), type8); } return hasErrors ? UNKNOWN_ERROR : NO_ERROR; }
上述代碼是在ResourceTable和Assets中添加資源文件時(shí), 對(duì)資源文件名稱進(jìn)行修改,這就能夠做到資源文件名稱的替換,這樣通過(guò)使用修改過(guò)的AAPT編譯資源并進(jìn)行打包,從而達(dá)到保護(hù)資源的目的。
以上就是Android 資源混淆的使用及注意事項(xiàng)的詳細(xì)內(nèi)容,更多關(guān)于Android 資源混淆的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android studio 下JNI編程實(shí)例并生成so庫(kù)的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android studio 下JNI編程實(shí)例并生成so庫(kù),需要的朋友可以參考下2017-09-09Android 沉浸式改變小米魅族狀態(tài)欄顏色的實(shí)例代碼
這篇文章主要介紹了Android 沉浸式改變小米魅族狀態(tài)欄顏色的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02詳解Android使用CoordinatorLayout+AppBarLayout+CollapsingToolbarL
這篇文章主要為大家詳細(xì)介紹了Android使用CoordinatorLayout+AppBarLayout+CollapsingToolbarLayou實(shí)現(xiàn)手指滑動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05Kotlin?協(xié)程的取消機(jī)制詳細(xì)解讀
這篇文章主要為大家介紹了Kotlin?協(xié)程的取消機(jī)制詳細(xì)解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Android利用Intent.ACTION_SEND進(jìn)行分享
這篇文章主要介紹了Android利用Intent.ACTION_SEND進(jìn)行分享,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05Android自定義ProgressBar實(shí)現(xiàn)漂亮的進(jìn)度提示框
這篇文章主要為大家詳細(xì)介紹了Android自定義ProgressBar實(shí)現(xiàn)漂亮的進(jìn)度提示框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06Android實(shí)現(xiàn)短信驗(yàn)證碼輸入框
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)短信驗(yàn)證碼輸入框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11自己實(shí)現(xiàn)Android View布局流程
這篇文章主要介紹了自己實(shí)現(xiàn)Android View布局流程,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-03-03Android學(xué)習(xí)教程之圓形Menu菜單制作方法(1)
這篇文章主要為大家詳細(xì)介紹了Android學(xué)習(xí)教程之圓形Menu菜單操作代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Flutter中跨組件數(shù)據(jù)傳遞的方法總結(jié)
Flutter中的數(shù)據(jù)傳遞一般包括:父->子,子->父,父->父,也就是說(shuō)嵌套時(shí)的傳遞以及跨頁(yè)面的傳遞,本文整理了三種我們通常使用的方法,需要的可以參考一下2023-06-06