Android開發:APK的反編譯(獲取程式碼和資原始檔)

我命傾塵發表於2019-04-15

一、反編譯工具:

  1、APKTool:

    APKTool是由GOOGLE提供的APK編譯工具,能夠完成反編譯及回編譯apk的工作。同時,它也有著安裝反編譯系統apk所需要的framework-res框架,以及清理以前反編譯資料夾等功能。

    APKTool的使用需要java支援。

  2、dex2jar:

    dex2jar 是將android的.dex檔案轉換成Java的.class檔案的轉換工具,如果在轉換過程中有問題的話,可以試用下其他的版本。

  3、jd-gui:

    JD分為JD-GUI、JD-Eclipse兩種執行方式,JD-GUI是以單獨的程式的方式執行,JD-Eclipse則是以一個Eclipse外掛的方式執行。

    jd-gui只能檢視,不能夠將那些檔案轉換成.java檔案。

  檔案下載地址:https://pan.baidu.com/s/1ucFu7NATp0V3u9ixSwfnng

  提取碼:eeir

二、APKTool使用:

  下載好的apktool資料夾中包含以下檔案:aapt.exeapktool.batapktool.jarcmd.exe.

  

 

  1、反編譯:

  將要反編譯的apk檔案複製到該資料夾下,開啟cmd.exe,進入cmd中,執行命令:

apktool.bat d hotword.apk

  (不復制也行,但是執行命令時要使用絕對路徑寫清apk檔案放置的精確位置

  

  

  在apktool資料夾下可以看到hotword資料夾,裡面儲存的有res下的資原始檔,和各種XML檔案:

  

  

  

  如果你給定的apk反編譯檔案已經存在,那麼輸入完該命令後會提示你,並且無法執行,需要重新修改命令加入-f指令:

apktool.bat d –f hotword.apk

  這樣會強行覆蓋已經存在的檔案。

  2、回編譯:

  執行命令:

apktool.bat b hotword

  引數b代表回編譯,hotword則是apk反編譯出來的資料夾名。

  

  回編譯完成會在hotword資料夾生成一個dist資料夾和一個build資料夾,dist資料夾裡面存放的就是回編譯後不帶有簽名的apk檔案,build資料夾裡面還有一個apk資料夾,裡面存放的是回編譯後沒有打包成apk的檔案。

  如下:

  

  

  

  3、安裝特定的framework-res.apk檔案:

  install-framework命令,應用於為APKTool安裝特定的framework-res.apk檔案,方便反編譯一些與ROM相互依賴的APK檔案。

三、dex2jar的使用:

  1、解壓檔案:

  將apk檔案的字尾名改為zip格式,解壓裡面的classes.dex檔案:

  

  

  將classes.dex放置到dex2jar資料夾下(或使用絕對路徑),執行命令:

d2j-dex2jar.bat classes.dex

  

  得到一個jar包:

  

四、jd-gui的使用:

  開啟jd-gui.exe:

  

  File-》open file···

  

  選中剛才生成的jar包,開啟可得:

  

五、關於反編譯:

  1、什麼是反編譯器 ?

  編譯的定義是:將原始碼轉換成二進位制執行程式碼的過程,將C原始碼編譯成exe可執行檔案這樣的就叫做編譯。

  反編譯:把二進位制執行程式碼還原成原始碼的過程,把exe轉換為C原始碼就叫反編譯。  

  像Java、.net這樣基於虛擬機器技術的程式語言則反編譯非常容易,Java平臺下有JD等反編譯器,.net平臺下則有Reflector等反編譯器。但是主流的C的編譯器都進行了程式碼的優化,把C編譯生成的exe檔案反編譯成C程式碼非常困難。

  2、反編譯得到的是否是原始碼?

   當然不是。

  程式碼與原始碼是非常接近的,基本90%還原,但是還是會有一些差異。比如說,原始碼裡的a=2+3;這行程式碼,編譯成apk再反編譯回來,就變成了a=5;不會還原到2+3那種程式碼了。

  3、既然程式可以反編譯,那是不是開發安卓程式很不安全,面臨隨時都會被破解的風險?

  這倒不至於,開發人員可以採用程式碼混淆等技術,以此來加大反編譯的難度和降低反編譯程式碼的可讀性。

  但歸根到底來說,不可能完全避免這種風險,不過可以大大減小,而且jd-gui只能檢視,不能夠將那些檔案轉換成.java檔案。

六、問題解決:

  在apktool反編譯的過程中可能出現如下錯誤:

  

  Exception in thread "main" brut.androlib.AndrolibException: Could not decode arsc file
    at brut.androlib.res.decoder.ARSCDecoder.decode(ARSCDecoder.java:54)
    at brut.androlib.res.AndrolibResources.getResPackagesFromApk(AndrolibResources.java:604)
    at brut.androlib.res.AndrolibResources.loadMainPkg(AndrolibResources.java:74)
    at brut.androlib.res.AndrolibResources.getResTable(AndrolibResources.java:66)
    at brut.androlib.Androlib.getResTable(Androlib.java:49)
    at brut.androlib.ApkDecoder.decode(ApkDecoder.java:93)
    at brut.apktool.Main.cmdDecode(Main.java:169)
    at brut.apktool.Main.main(Main.java:85)
  Caused by: java.io.IOException: Expected: 0x001c0001, got: 0x00000000
    at brut.util.ExtDataInput.skipCheckInt(ExtDataInput.java:48)
    at brut.androlib.res.decoder.StringBlock.read(StringBlock.java:43)
    at brut.androlib.res.decoder.ARSCDecoder.readPackage(ARSCDecoder.java:95)
    at brut.androlib.res.decoder.ARSCDecoder.readTable(ARSCDecoder.java:81)
    at brut.androlib.res.decoder.ARSCDecoder.decode(ARSCDecoder.java:49)
    ... 7 more

  這個報錯的錯因是:

  使用了新的adt,而反編譯使用的apktool.jar的版本太低了,無法反編譯某些apk,下載新的版本的apktool.jar並替換現在的版本即可。

  

  注:apk的反編譯只可用於學習和研究,堅決不可隨意修改他人程式碼,更加不可用作商用,望慎行!如有惡意行為,後果自負。

相關文章