Android程序打完包之后是一個(gè)apk程序,可以安裝到Android手機(jī)上。我們反編譯其實(shí)也就是對(duì)這個(gè)APK文件進(jìn)行反編譯。Android的反編譯主要又分為兩個(gè)部分,一個(gè)是對(duì)代碼的反編譯,一個(gè)是對(duì)資源的反編譯,我們馬上來(lái)逐個(gè)學(xué)習(xí)一下。
一、反編譯
本人自己寫(xiě)了一個(gè)程序來(lái)進(jìn)行反編譯,畢竟反編譯別人的程序不是特別好的事情。這里我的代碼很簡(jiǎn)單就是一個(gè)按鈕點(diǎn)擊彈出一個(gè)Toast來(lái)提示“反編譯例子”。
這是我們的APP例子:Android反編譯.apk

下面讓我們用此APP為例來(lái)開(kāi)始學(xué)習(xí)!
1、我們需要先準(zhǔn)備Android反編譯的三個(gè)工具
- apkTool? 谷歌提供的 APK 編譯工具,可以反編譯和回編譯。[apkTool下載地址]
- dex2jar:將 dex 文件轉(zhuǎn)換成 jar 包。?[dex2jar下載地址]
- jd-gui:用來(lái)查看 jar 包里面的代碼的一種工具。? [jd-gui下載地址]
2、對(duì)資源進(jìn)行反編譯
1. 這里我們需要用到apkTool

2. 接下來(lái)的工作就很簡(jiǎn)單了,我們將Android反編譯.apk拷貝到和這兩個(gè)文件同樣的目錄當(dāng)中,然后cmd也進(jìn)入到這個(gè)目錄下,并在cmd中執(zhí)行如下命令:
apktool d Android反編譯.apk
其中d是decode的意思,表示我們要對(duì)Android反編譯.apk這個(gè)文件進(jìn)行解碼。那除了這個(gè)基本用法之外,我們還可以再加上一些附加參數(shù)來(lái)控制decode的更多行為:
-f 如果目標(biāo)文件夾已存在,則強(qiáng)制刪除現(xiàn)有文件夾(默認(rèn)如果目標(biāo)文件夾已存在,則解碼失敗)。
-o 指定解碼目標(biāo)文件夾的名稱(chēng)(默認(rèn)使用APK文件的名字來(lái)命名目標(biāo)文件夾)。
-s 不反編譯dex文件,也就是說(shuō)classes.dex文件會(huì)被保留(默認(rèn)會(huì)將dex文件解碼成smali文件)。
-r 不反編譯資源文件,也就是說(shuō)resources.arsc文件會(huì)被保留(默認(rèn)會(huì)將resources.arsc解碼成具體的資源文件)。
常用用法就這么多了,那么上述命令的執(zhí)行結(jié)果如下圖所示(下圖為成功案例):

3、對(duì)代碼進(jìn)行反編譯
1. 這里我們用到dex2jar工具
解壓dex2jar壓縮包后,如下圖

這里面我們用到的是d2j-dex2jar.bat文件。
2. 我們先對(duì)Android反編譯.apk進(jìn)行更改為Android反編譯.zip我們更改apk為zip就行,然后用解壓軟件打開(kāi)。解壓之后你會(huì)發(fā)現(xiàn)里面有一個(gè)classes.dex文件,如下圖所示:

這個(gè)classes.dex文件就是存放所有java代碼的地方了,我們將它拷貝到dex2jar解壓后的目錄下。
3. 在cmd中也進(jìn)入到同樣的目錄,然后執(zhí)行:( dex2jar ? 為文件夾名稱(chēng),一般cmd要到此文件夾下 。 ?d2j-dex2jar 與classes.dex ?為文件夾內(nèi)部的文件?。。。?/p>
d2j-dex2jar classes.dex
那么上述命令的執(zhí)行結(jié)果如下圖所示(下圖為成功案例):

這樣我們的目錄下就會(huì)多出兩個(gè)文件

可以看到,classes-dex2jar.jar這個(gè)文件就是我們借助工具之后成功轉(zhuǎn)換出來(lái)的jar文件了。但是對(duì)于我們而言,jar文件也不是可讀的,因此這里還需要再借助一下jd-gui這個(gè)工具來(lái)將jar文件轉(zhuǎn)換成java代碼。
4. 下面我們就要用到我們的第三個(gè)工具了 jd-gui
直接運(yùn)行jd-gui.exe打開(kāi)classes-dex2jar.jar后就可以了。結(jié)果如下圖所示:

OK,由此可見(jiàn),我們的代碼反編譯工作已經(jīng)成功了,MainActivity中的代碼非常清晰,基本已經(jīng)做到了90%以上的還原工作。但是如果想要做到100%的代碼還原還是非常有難度的,因?yàn)橄駍etContentView()方法傳入的參數(shù),其實(shí)就是一個(gè)資源的id值而已,那么這里反編譯也就只能將相應(yīng)的id值進(jìn)行還原,而無(wú)法變成像R.layout.activity_main這樣直觀的代碼展示。