APP加殼原理及常用脫殼方法介紹
前言
目前針對(duì)移動(dòng)應(yīng)用市場上安卓APP被破解、反編譯、盜版叢生的現(xiàn)象,很多APP開發(fā)人員已經(jīng)意識(shí)到保護(hù)APP的重要性。而對(duì)于移動(dòng)應(yīng)用APP加密保護(hù)的問題,如何對(duì)DEX文件加密尤為重要。對(duì)APP進(jìn)行加殼能有效地遏制APP被反編譯破解的行為。
1 加殼
1.1 什么是加殼
加殼是在二進(jìn)制的程序中植入一段代碼,在運(yùn)行的時(shí)候優(yōu)先取得程序的控制權(quán),做一些額外的工作。大多數(shù)病毒就是基于此原理。是應(yīng)用加固的一種手法對(duì)原始二進(jìn)制原文進(jìn)行加密/隱藏/混淆。
1.2 加殼作用
加殼的程序可以有效阻止對(duì)程序的反匯編分析,以達(dá)到它不可告人的目的。這種技術(shù)也常用來保護(hù)軟件版權(quán),防止被軟件破解。
1.3 加殼原理
市面上主要的加殼原理:將原Dex文件加密,加密后的Dex文件和殼Dex文件一起重新打包,產(chǎn)生新的Dex文件。安卓虛擬機(jī)加載的時(shí)候,會(huì)從殼Dex文件的ProxyApplication類開始,執(zhí)行attachBaseContext方法和onCreate方法。而殼Dex文件會(huì)在這兩個(gè)方法里面實(shí)現(xiàn)原Dex文件的還原和加載,讓虛擬機(jī)順利啟動(dòng)APP。
在這個(gè)過程中,牽扯到三個(gè)角色:
1、加殼程序:加密源程序?yàn)榻鈿?shù)據(jù)、組裝解殼程序和解殼數(shù)據(jù)
2、解殼程序:解密解殼數(shù)據(jù),并運(yùn)行時(shí)通過DexClassLoader動(dòng)態(tài)加載
3、源程序:需要加殼處理的被保護(hù)代碼
1.4 加殼后的利與弊
1.5 如何辨別是否加殼
2 脫殼
2.1 脫殼原理
跟java類似,安卓的class都是由Classloader的loadClass方法加載的。跟java不同的是,每一個(gè)class對(duì)象都會(huì)有對(duì)應(yīng)的dex對(duì)象屬性跟相應(yīng)的dex文件關(guān)聯(lián)起來。利用xposed,將loadClass方法劫持住,每當(dāng)loadClass方法調(diào)用完成后,用xposed執(zhí)行后置方法。獲取方法加載的class對(duì)象,然后調(diào)用getDex方法。拿到對(duì)應(yīng)的dex文件引用,最后將dex文件序列成byte數(shù)據(jù),寫到自定義保存文件里面去。就能拿到脫殼后的dex文件。
2.2 常用脫殼軟件
這里列舉三個(gè)常用的脫殼軟件:
一、反射大師 (需要搭建xposed環(huán)境)
二、DumpDex (需要搭建xposed環(huán)境且在真機(jī)下運(yùn)行)
三、FRIDA-DEXDump(需要搭建frida環(huán)境)
2.2.1 反射大師
2.3.1 Dex2Java
2、該目錄下執(zhí)行Dex2Java.py
并傳入jadx的絕對(duì)路徑,我這里為C:\Users\admin\Desktop\jadx\bin\jadx
Dex2Java.py C:\Users\admin\Desktop\jadx\bin\jadx
3、執(zhí)行完畢后,相同目錄下將會(huì)得到一個(gè)sources文件夾,該文件夾能直接用IDE工具打開查看其java代碼
2.3.2 Dex2Smali
準(zhǔn)備工作
1、apktool
apktool用于將apk文件反編譯為項(xiàng)目文件,下載地址:https://www.pcsoft.com.cn/soft/57847.html
2、baksmali.jar文件
basksmali.jar文件用于將dex文件轉(zhuǎn)為smali代碼,下載地址:https://bitbucket.org/JesusFreke/smali/downloads/
3、Dex2Smali腳本
該腳本用于將dex文件轉(zhuǎn)為smali代碼
自編寫如下:
Dex2Smali.py
import os, sys
if __name__ == "__main__":
if len(sys.argv) < 2 :
print("start error!start need 2 arguments!")
sys.exit()
path = os.path.split(__file__)[0] + '\\'
files= os.listdir(path)
for file in files:
if file.find(".dex") > 0:
prefix = file.split('.')[0]
print(prefix)
sh = 'java -jar ' + sys.argv[1] + ' disassemble -o smali_' + ('' if 'classes'==prefix else prefix) + ' ' + file
print(sh)
os.system(sh)
3、執(zhí)行完畢后得到多個(gè)classes文件