前一章順利搭建了反編譯的環(huán)境冰抢,該環(huán)境只是我為了方便使用而搭建的犬金,如果讀者想自己練習(xí)份蝴,除了像我一樣搭建環(huán)境外忆畅,只要有正確的工具和命令坛善,也可以進(jìn)行反編譯-查看源代碼-代碼注入-回編譯-簽名
等一系列操作。
本章使用上一章節(jié)所搭建的環(huán)境和工具邻眷,同時(shí)也使用之前Volley系列的成果作為源文件。工具和源文件可到這里下載剔交,同時(shí)也可參考上一章節(jié)進(jìn)行環(huán)境配置肆饶。
我們的源文件VolleyDemo.apk之所以還是一個(gè)很簡單的應(yīng)用,并未做代碼混淆等處理岖常,是為了接下來以最直觀的方式講解反編譯的一系列流程驯镊。[1]
應(yīng)用反編譯適用于參考別人的UI效果,邏輯實(shí)現(xiàn)等竭鞍,但后續(xù)的代碼注入等方式板惑,只是技術(shù)分享,切記不可用于惡意用途或違法操作偎快,否則造成的一切后果自行負(fù)責(zé)冯乘,與本人無關(guān)。
至于apk文件結(jié)構(gòu)等知識晒夹,這里就不科普了裆馒,反編譯系列重點(diǎn)記錄我自己的處理方式,當(dāng)然丐怯,如果能帶給讀者一定的啟發(fā)更好喷好,哈哈。
查看Java代碼
回顧上一章節(jié)读跷,我們配置環(huán)境時(shí)梗搅,已經(jīng)在/user/local/bin/下創(chuàng)建鏈接。
也就意味著我們可以隨時(shí)隨地直接使用apksign, apktool, dex2jar, jd-gui四個(gè)命令。
接下來需要查看應(yīng)用的java源碼无切,分為兩步:
- 將apk/dex轉(zhuǎn)換為jar包
- 反編譯jar包得到j(luò)ava代碼
接下來執(zhí)行如下命令:
dex2jar VolleyDemo.apk
該操作將輸出結(jié)果:
并且可以看到荡短,在該目錄下生成了一個(gè)新文件VolleyDemo_dex2jar.jar
。
然后使用jd-gui查看jar包代碼:
jd-gui VolleyDemo_dex2jar.jar
彈出如下界面:
我們這里使用jd-gui工具订雾,方法非常簡單肢预,選擇左邊的包路徑,比如com.joyin.volleydemo.app.MyApplication
打開后洼哎,就能看到我們的源代碼烫映,如果讀者是從封裝Volley實(shí)現(xiàn)自動(dòng)化網(wǎng)絡(luò)處理一路過來的,對這部分代碼應(yīng)該會感到很眼熟噩峦。
而原本我們項(xiàng)目中MyApplication.java代碼如下:
package com.joyin.volleydemo.app;
import android.app.Application;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
import com.joyin.volleydemo.utils.parse.xml.ErrorCodeParser;
/**
* Created by joyin on 16-4-3.
*/
public class MyApplication extends Application {
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
mRequestQueue = Volley.newRequestQueue(this);
ErrorCodeParser.init();
}
public static MyApplication getInstance() {
return mInstance;
}
public static RequestQueue getRequestQueue() {
return mInstance.mRequestQueue;
}
}
對比一下jd-gui里面得到的代碼锭沟,對于我們來說,簡直就是一模一樣啊识补。
而且左側(cè)目錄結(jié)構(gòu)可以展開族淮,代碼中有下劃線的地方,點(diǎn)擊可跳轉(zhuǎn)過去凭涂,非常方便祝辣。
至此,各位讀者應(yīng)該已經(jīng)會通過反編譯得到apk的java源碼了切油,但是該代碼只能看不能改蝙斜,而若想修改apk,進(jìn)行代碼注入澎胡,所接觸到的就不是java代碼孕荠,而是smali代碼了。
查看smali代碼
這里推薦兩篇關(guān)于反編譯和smali的文章攻谁,這些文章都寫的非常好稚伍,所以具體細(xì)節(jié)我不過多講解,反編譯系列的重點(diǎn)在于掌握解決思路戚宦。
Android 反編譯 -smali語法
APK反編譯之一:基礎(chǔ)知識
除此之外个曙,還有dalvik opcodes,以及網(wǎng)絡(luò)上很多其他的相關(guān)資源文章阁苞,有興趣的各位請自行搜索困檩。
上一章節(jié)講了反編譯回編譯和簽名的流程,反編譯的命令如下:
apktool d VolleyDemo.apk
生成的目錄結(jié)構(gòu)如下:
其中smali目錄下的各文件即為java代碼編譯后生成的對應(yīng)smali代碼那槽。
VolleyDemo/smali/com/joyin/volleydemo/app/MyApplication.smali
.class public Lcom/joyin/volleydemo/app/MyApplication;
.super Landroid/app/Application;
.source "MyApplication.java"
# static fields
.field private static mInstance:Lcom/joyin/volleydemo/app/MyApplication;
# instance fields
.field private mRequestQueue:Lcom/android/volley/RequestQueue;
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 12
invoke-direct {p0}, Landroid/app/Application;-><init>()V
return-void
.end method
.method public static getInstance()Lcom/joyin/volleydemo/app/MyApplication;
.locals 1
.prologue
.line 27
sget-object v0, Lcom/joyin/volleydemo/app/MyApplication;->mInstance:Lcom/joyin/volleydemo/app/MyApplication;
return-object v0
.end method
.method public static getRequestQueue()Lcom/android/volley/RequestQueue;
.locals 1
.prologue
.line 31
sget-object v0, Lcom/joyin/volleydemo/app/MyApplication;->mInstance:Lcom/joyin/volleydemo/app/MyApplication;
iget-object v0, v0, Lcom/joyin/volleydemo/app/MyApplication;->mRequestQueue:Lcom/android/volley/RequestQueue;
return-object v0
.end method
# virtual methods
.method public onCreate()V
.locals 1
.prologue
.line 20
invoke-super {p0}, Landroid/app/Application;->onCreate()V
.line 21
sput-object p0, Lcom/joyin/volleydemo/app/MyApplication;->mInstance:Lcom/joyin/volleydemo/app/MyApplication;
.line 22
invoke-static {p0}, Lcom/android/volley/toolbox/Volley;->newRequestQueue(Landroid/content/Context;)Lcom/android/volley/RequestQueue;
move-result-object v0
iput-object v0, p0, Lcom/joyin/volleydemo/app/MyApplication;->mRequestQueue:Lcom/android/volley/RequestQueue;
.line 23
invoke-static {}, Lcom/joyin/volleydemo/utils/parse/xml/ErrorCodeParser;->init()V
.line 24
return-void
.end method
smali代碼有點(diǎn)匯編的感覺悼沿,晦澀難懂,但是始終還是有這自己的語法骚灸,所以熟悉后就沒那么難了糟趾,這里建議大家了解一下smali的語法和基本知識,因?yàn)橛械腶pk經(jīng)過處理后,通過jd-gui或者SmaliToJava一類的工具查看不到j(luò)ava代碼义郑,此時(shí)能讀懂smali代碼就很重要了蝶柿。我也不精通于smali代碼,但是個(gè)人感覺改apk(代碼注入)和平時(shí)寫代碼一樣非驮,有思路才是最重要的交汤。
本章到此結(jié)束,下一章將通過代碼注入的方式劫笙,開始修改我們的VolleyDemo.apk芙扎。
-
如果進(jìn)行代碼混淆,反編譯得到的代碼中填大,一些變量戒洼、方法或者類名就變成a、b允华、c等難以辨識的詞匯圈浇。當(dāng)然,市場上絕大部分應(yīng)用都是進(jìn)行過代碼混淆的靴寂,我在此也強(qiáng)烈建議大家上線的時(shí)候一定要記得混淆磷蜀,不然自己的業(yè)務(wù)以及敏感數(shù)據(jù)很容易被暴露出來,在商業(yè)項(xiàng)目中是比較危險(xiǎn)的百炬。然而僅僅對代碼進(jìn)行混淆蠕搜,對于熟練反編譯技能的人來說,只是降低代碼可讀性收壕,并未從本質(zhì)上解決安全性問題,此時(shí)可以選擇應(yīng)用加固等方式轨蛤。應(yīng)用加固參考文章:《Android中的Apk的加固(加殼)原理解析和實(shí)現(xiàn)》蜜宪。 ?