引言:
在安卓開發中,打包發布是開發的最后一個環節,apk是整個項目的源碼和資源的結合體;對于懂點反編譯原理的人可以輕松編譯出apk的源碼資源,并且可以修改資源代碼、重新打包編譯,輕輕松松變成自己的apk或者修改其中一部分竊取用戶信息。
代碼被反編譯對于apk的開發者和使用者而言十分苦惱。apk加固、防止反編譯此時顯得尤為重要。雖然有好多給apk加固的第三方,可能并不需要自己做apk加固,但是了解apk加固原理還是很有必要的。本文主要向大家介紹apk加固原理和簡單實現。
目錄:
一、apk常見加固方式
二、apk加固原理
三、apk加固實現
四、apk該方式加固后缺陷
一、apk常見加固方式
(1)代碼層級加密--代碼混淆
代碼混淆是一種常用的加密方式。本質是把工程中原來的有具體含義的類名、變量名、方法名,修改成讓人看不懂的名字。常見的代碼混淆工具proguard(有興趣的可以自己看一下該工具:http://t.cn/ELjgHdi)。該加密方式只是對工程提供了最小的保護,并不是說不能逆向破解;只是說難度增加,需要耐心。
(2) Dex文件加密
dex是Android工程中的代碼資源文件,通過dex可以反編譯出java代碼。dex的加殼是常見的加密方式。通過對dex文件加密拼接加殼,可以有效的對工程代碼進行保護。apk工程在安裝成功后,app啟動時會有dex解密的過程,然后重新加載解密后的dex文件。
第二種加密方式也就是本文要為大家分享的加密方式。基本原理是在jni層, 使用DexClassLoader動態加載技術完成對加密classex.dex的動態加載,dex文件可以附屬在assert或raw目錄。
二、apk加固原理
(1)apk文件結構
解壓一個apk包,可以看到如下目錄結構:
assets:存放工程資源(圖片、本地html等)文件的目錄
Lib:存放ndk編譯出來的so文件(so:C/C++編譯出的文件)
META-INF:
該目錄下存放的是簽名信息,用來保證apk包的完整性和系統的安全性:
CERT.RSA:保存著該應用程序的證書和授權信息
CERT.SF:保存著SHA-1信息資源列表
MANIFEST.MF:清單信息
res:存放資源(布局xml、布局xml引用圖片等)文件的目錄
AndroidManifest.xml:清單文件,它描述了應用的名字、版本、權限、注冊的服務等信息
classes.dex:java源碼編譯經過編譯后生成的dalvik字節碼文件,主要在Dalvik虛擬機上運行的主要代碼部分
resources.arsc:編譯后的二進制資源文件
META-INF文件主要是跟簽名有關的文件,保證了apk的完整性和安全性。apk每次重新簽名需要刪除該文件夾。
需要大家主要關注的是classes.dex文件:因為apk加固主要是對dex文件進行的加密。
(2)Dex文件結構

Java源文件生成Dex文件的映射關系
dex文件可以理解為由java文件編譯生產的,直觀表現就是dex文件可以編譯出java源碼;
dex文件的作用是記錄整個工程(通常是一個Android工程)的所有類文件的信息;
dex文件是從class文件演變而來的,class文件存在冗余信息,dex文件則去掉了冗余,并且整合了整個工程的類信息。

Dex文件結構
文件頭header包含了dex文件的信息,也是大家需要關注的部分。因為下面的操作中會有dex文件的修改操作,而判斷是否是正確的dex文件是由header部分決定的。
下面看一下header部分的信息:
struct DexFile {
DexHeader header;
DexStringId StringIds[StringIdsSize];
DexTypeId TypeIds[typeIdsSize];
DexProtoId ProtoIds[protoIdsSize];
DexFieldId FieldIds[fieldIdsSize];
DexMethodId MethodIds[methodIdsSize];
DexClassDef Data[];
DexLink LinkData;
}
Dex文件header部分結構體信息
Header部分有需要注意的三個字段:checksum字段、signature字段、filesize字段。
checksum字段: checksum是校驗碼字段,校驗dex數據的完整性
signature字段: signature是SHA-1簽名字段,dex數據完整性校驗
signature字段:保存classes.dex文件總長度
之所以關注這三個字段,是因為后面會有對dex的重新拼接。dex拼接后要修改這三個字段,字段修改正確后才可以保證dex的正確加載。