Android筆記 (8): 反編譯 - 查看源代碼

前一章順利搭建了反編譯的環(huán)境,該環(huán)境只是我為了方便使用而搭建的,如果讀者想自己練習(xí),除了像我一樣搭建環(huán)境外,只要有正確的工具和命令,也可以進(jìn)行反編譯-查看源代碼-代碼注入-回編譯-簽名等一系列操作。


本章使用上一章節(jié)所搭建的環(huán)境和工具,同時(shí)也使用之前Volley系列的成果作為源文件。工具和源文件可到這里下載,同時(shí)也可參考上一章節(jié)進(jìn)行環(huán)境配置。

我們的源文件VolleyDemo.apk之所以還是一個(gè)很簡(jiǎn)單的應(yīng)用,并未做代碼混淆等處理,是為了接下來以最直觀的方式講解反編譯的一系列流程。[1]

應(yīng)用反編譯適用于參考別人的UI效果,邏輯實(shí)現(xiàn)等,但后續(xù)的代碼注入等方式,只是技術(shù)分享,切記不可用于惡意用途或違法操作,否則造成的一切后果自行負(fù)責(zé),與本人無關(guān)。


至于apk文件結(jié)構(gòu)等知識(shí),這里就不科普了,反編譯系列重點(diǎn)記錄我自己的處理方式,當(dāng)然,如果能帶給讀者一定的啟發(fā)更好,哈哈。

查看Java代碼

回顧上一章節(jié),我們配置環(huán)境時(shí),已經(jīng)在/user/local/bin/下創(chuàng)建鏈接。


/usr/local/bin/目錄

也就意味著我們可以隨時(shí)隨地直接使用apksign, apktool, dex2jar, jd-gui四個(gè)命令。

接下來需要查看應(yīng)用的java源碼,分為兩步:

  1. 將apk/dex轉(zhuǎn)換為jar包
  2. 反編譯jar包得到j(luò)ava代碼

接下來執(zhí)行如下命令:

  dex2jar VolleyDemo.apk

該操作將輸出結(jié)果:

并且可以看到,在該目錄下生成了一個(gè)新文件VolleyDemo_dex2jar.jar。

然后使用jd-gui查看jar包代碼:

jd-gui VolleyDemo_dex2jar.jar

彈出如下界面:


使用jd-gui查看源碼

我們這里使用jd-gui工具,方法非常簡(jiǎn)單,選擇左邊的包路徑,比如com.joyin.volleydemo.app.MyApplication打開后,就能看到我們的源代碼,如果讀者是從封裝Volley實(shí)現(xiàn)自動(dòng)化網(wǎng)絡(luò)處理一路過來的,對(duì)這部分代碼應(yīng)該會(huì)感到很眼熟。

jd-gui查看反編譯后的MyApplication

而原本我們項(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;
    }
}

對(duì)比一下jd-gui里面得到的代碼,對(duì)于我們來說,簡(jiǎn)直就是一模一樣啊。
而且左側(cè)目錄結(jié)構(gòu)可以展開,代碼中有下劃線的地方,點(diǎn)擊可跳轉(zhuǎn)過去,非常方便。


至此,各位讀者應(yīng)該已經(jīng)會(huì)通過反編譯得到apk的java源碼了,但是該代碼只能看不能改,而若想修改apk,進(jìn)行代碼注入,所接觸到的就不是java代碼,而是smali代碼了。


查看smali代碼

這里推薦兩篇關(guān)于反編譯和smali的文章,這些文章都寫的非常好,所以具體細(xì)節(jié)我不過多講解,反編譯系列的重點(diǎn)在于掌握解決思路。

Android 反編譯 -smali語法
APK反編譯之一:基礎(chǔ)知識(shí)

除此之外,還有dalvik opcodes,以及網(wǎng)絡(luò)上很多其他的相關(guān)資源文章,有興趣的各位請(qǐng)自行搜索。

上一章節(jié)講了反編譯回編譯和簽名的流程,反編譯的命令如下:

apktool d VolleyDemo.apk 

生成的目錄結(jié)構(gòu)如下:


其中smali目錄下的各文件即為java代碼編譯后生成的對(duì)應(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的語法和基本知識(shí),因?yàn)橛械腶pk經(jīng)過處理后,通過jd-gui或者SmaliToJava一類的工具查看不到j(luò)ava代碼,此時(shí)能讀懂smali代碼就很重要了。我也不精通于smali代碼,但是個(gè)人感覺改apk(代碼注入)和平時(shí)寫代碼一樣,有思路才是最重要的。

本章到此結(jié)束,下一章將通過代碼注入的方式,開始修改我們的VolleyDemo.apk。



  1. 如果進(jìn)行代碼混淆,反編譯得到的代碼中,一些變量、方法或者類名就變成a、b、c等難以辨識(shí)的詞匯。當(dāng)然,市場(chǎng)上絕大部分應(yīng)用都是進(jìn)行過代碼混淆的,我在此也強(qiáng)烈建議大家上線的時(shí)候一定要記得混淆,不然自己的業(yè)務(wù)以及敏感數(shù)據(jù)很容易被暴露出來,在商業(yè)項(xiàng)目中是比較危險(xiǎn)的。然而僅僅對(duì)代碼進(jìn)行混淆,對(duì)于熟練反編譯技能的人來說,只是降低代碼可讀性,并未從本質(zhì)上解決安全性問題,此時(shí)可以選擇應(yīng)用加固等方式。應(yīng)用加固參考文章:《Android中的Apk的加固(加殼)原理解析和實(shí)現(xiàn)》?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,917評(píng)論 25 709
  • apk是安卓工程打包的最終形式,將apk安裝到手機(jī)或者模擬器上就可以使用APP。反編譯apk則是將該安卓工程的源碼...
    隋胖胖LoveFat閱讀 67,203評(píng)論 6 56
  • 1. 為什么要反編譯? 場(chǎng)景一 產(chǎn)品經(jīng)理:xxx,反編譯xxx的播放器,看看他們是怎么實(shí)現(xiàn)的? 場(chǎng)景二 測(cè)試:這個(gè)...
    傷口不該結(jié)疤閱讀 12,447評(píng)論 7 51
  • 很多人寫文章,喜歡把什么行業(yè)現(xiàn)狀啊,研究現(xiàn)狀啊什么的寫了一大通,感覺好像在寫畢業(yè)論文似的,我這不廢話,先直接上幾個(gè)...
    龐哈哈哈12138閱讀 3,062評(píng)論 1 8
  • “又是糟糕的一天,日復(fù)一日!”這是她患病后說的最多的一句話。假如有一天,你的心臟隨時(shí)有可能瞬間停止跳動(dòng)的話,你...
    星光閃爍閱讀 620評(píng)論 0 1

友情鏈接更多精彩內(nèi)容