Android apkの逆アセンブリをしてJavaソース、XMLを取り出す方法



Androidアプリ開発において、リバースエンジニアリング(Reverse engineering)を行いたい人向けの内容です。

他人の実装しているAndroidアプリからJavaのソースコードやAndroidManifest.xmlを取り出す事は可能です(難読化されている可能性はあります)。

スポンサードリンク

端末から APKを取り出す方法

Android端末とパソコンをUSBで接続し、コマンドプロンプトを起動します。

adb shell pm list packages -f | findstr ****

「****」の部分はパッケージファイルの名前の一部を入力します。

例:

$ adb shell pm list packages -f | findstr remote
package:/data/app/com.google.android.tv.remote-1.apk=com.google.android.tv.remote

同じくコマンドプロンプトを起動し次のコマンドを入力します。

adb pull ****/****/****.apk

例:

$ adb pull /data/app/com.google.android.tv.remote-1.apk
3945 KB/s (4432568 bytes in 1.097s)

これで必要なapkは入手できました。次にJavaやXMLを取り出してみましょう。

pm list package オプション

オプション説明
-ddisbled packagesのリスト表示
-eenable packagesのリスト表示
-fassociated fileのリスト表示

パッケージの有効化の方法

pm enable ****

APKからJavaソースコード、XMLを取り出すためのツール

まず、用途によって幾つかダウンロードが必要です。

AndroidManifest.xml だけ見たい

何も必要ありませんが、XMLがバイナリ表示される場合にはツールを使って下さい。

XML、Javaソースコードを取り出す

XMLを取り出す

dex2jarとjadを利用して変換したにも関わらず、XMLがバイナリの場合があります。
その場合にXMLの変換を試みるツールを2つ紹介します。

その他

バッチファイルで一気に変換を行いたい場合には入手しておいてください。

APKからJavaソースコード、XMLを取り出す方法

手順0:.apkからAndroidManifest.xml、classes.dexを取得

「****.apk」のファイルの拡張子を「****.zip」と変換し、解凍してください。

手順1:.apkからclasses.dexを取得

解凍すると、次のようなファイルが入っていると思います。

ファイル・フォルダ名 内容
META-INF 署名が行われる際に生成されるフォルダ
res 画像・音声ファイル等を保存するフォルダ
AndroidManifest.xml アプリケーションに関する必要不可欠な情報を記載
classes.dex Dalvik VMのバイトコード
resources.arsc リソースファイル

「classes.dex」に、Javaのソースコード一式が入っています。

手順2:dex2jarで.dex→.class変換

dex2jarはDalvik VMのコードをJava VMのコードに変換するツールです。

dex2jar

dex2jarの使い方はとても簡単で、以下のように変換するdexファイルを指定します。

$ dex2jar.bat classes.dex
this cmd is deprecated, use the d2j-dex2jar if possible
dex2jar version: translator-0.0.9.15
dex2jar classes.dex -> classes_dex2jar.jar
Done.

正常終了したらclasses.dexと同じ階層にclasses_dex2jar.jarが出来ます。

次にこのjarファイルの拡張子をzipにして解凍します。

手順3:jadで.class→.java変換

jadツールを使用すると.classファイルから.javaファイルが取得できます。

jadツール

jad158g.win.zipを解凍します。解凍するとjad.exeがあるので確認しましょう。

コマンドプロンプトで下記を実行します。

C:\>  -8 -d <出力パス> -s .java -r <.classファイルパス>

例としては sample以下にある全てのclassファイルを変換対象とする場合には次のようになります。

C:\> C:\jad158g.win\jad.exe -8 -d C:\out -s .java -r C:\sample\**\*.class

jadコマンドが正常終了すると、出力パスに指定したディレクトリに.javaファイルができます。

スポンサードリンク

バイナリXMLをテキストXMLへ変換

AndroidManifest.xmlがバイナリ表示の場合は、XMLへコンバートしましょう。

AndroidManifest.xmlや、res/layout/*.xmlなどをテキスト形式のXMLへ変換することができるツールを紹介します。

AXMLPrinter2.jar

このツールはJavaで作成されているため、Java実行環境が必要。コマンドラインより、下記のようにして使用します。

java -jar AXMLPrinter2.jar AndroidManifest.xml

res/xml/**.xml のバイナリテキストをXMLに変換

「res/xml/****.xml」をテキストXMLに変換しようとすると次のようなエラーが出ます。

java -jar AXMLPrinter2.jar res/xml/****.xml
java.lang.ArrayIndexOutOfBoundsException: 96
        at android.content.res.StringBlock.getShort(StringBlock.java:231)
        at android.content.res.StringBlock.getString(StringBlock.java:91)
        at android.content.res.AXmlResourceParser.getName(AXmlResourceParser.java:140)
        at test.AXMLPrinter.main(AXMLPrinter.java:56)

その場合は、APKに対して apktoolを適用します。

apktool decode --no-src **.apk

「--no-src」のオプションはソースは不要だけど、リソースデータだけ必要という意味です。

バッチファイルで一括変換

次のバッチファイルをダウンロードして、変換したいAPKをドラックすると自動的に逆アセンブリを開始します。

@echo off

rem 各種、ダウンロードしたバージョンに合わせて書き換えてください
set APKTOOL_DIR="apktool1.5.2"
set DEX2JAR_DIR="dex2jar-0.0.9.15"
set JAD_WIN_DIR="jad158g.win"

%~d0%~p0\unzip.exe %1 -d %~d1%~p1\%~n1
call %~d0%~p0\%DEX2JAR_DIR%\dex2jar.bat %~d1%~p1\%~n1\classes.dex
MOVE %~d1%~p1\%~n1\classes_dex2jar.jar %~d1%~p1\%~n1\classes_dex2jar.zip
%~d0%~p0\unzip.exe %~d1%~p1\%~n1\classes_dex2jar.zip -d %~d1%~p1\%~n1\
%~d0%~p0\%JAD_WIN_DIR%\jad.exe -8 -d %~d1%~p1\%~n1\src -s .java -r %~d1%~p1\%~n1\**\*.class
call %~d0%~p0\%APKTOOL_DIR%\apktool.bat d -f %1 %~d1%~p1\%~n1.xml
%~d0%~p0\%APKTOOL_DIR%\aapt.exe dump xmltree %1 AndroidManifest.xml > %~d1%~p1\%~n1\AndroidManifest.xml.txt
java -jar %~d0%~p0\%APKTOOL_DIR%\AXMLPrinter2.jar %~d1%~p1\%~n1\AndroidManifest.xml > %~d1%~p1\%~n1\AndroidManifest.xml2.txt
%~d0%~p0\%APKTOOL_DIR%\aapt.exe l -a %1
MOVE %~d1%~p1\%~n1 %~d1%~p1\%~n1.2
rem バイナリXMLの場合を考慮して変換を試みる
call %~d0%~p0\%APKTOOL_DIR%\apktool.bat decode -f --no-src %1
MOVE %~d1%~p1\%~n1.2\src %~d1%~p1\%~n1
MOVE %~d1%~p1\%~n1.2\AndroidManifest.xml.txt %~d1%~p1\%~n1
DEL %~d1%~p1\%~n1.2

:EXIT

pause

次のようにダウンロードしたファイルを配置してください。

undefined

その他役立つコマンド

apkファイルのdump(label user permission表示)

# aapt d badging xxx.apk

apkファイルのversion

$ aapt l -a xxx.apk | grep "android:version"
    A: android:versionCode(0x0101021b)=(type 0x10)0x4
    A: android:versionName(0x0101021c)="1.4" (Raw: "1.4")

アプリケーション名・アイコン

$ aapt d badging xxx.apk | grep "application:"
application: label='HogeApp' icon='res/drawable/app_icon.png'

$ unzip xxx.apk
$ ls -l res/drawable/app_icon.png
-rw-rw-rw-  1 user 0 8121 2015-10-01 00:00 res/drawable/app_icon.png

apkファイルのSDKバージョン

$ aapt l -a xxx.apk  | grep "SdkVersion"
      A: android:minSdkVersion(0x0101020c)=(type 0x10)0x4
      A: android:targetSdkVersion(0x01010270)=(type 0x10)0xf

apkファイルのdump(permisson表示)

androidの「パッケージ名」「バージョン」などを確認できます。

# aapt d permissions xxx.apk

例)

$ aapt dump badging test.apk
package: name='com.test.sample' versionCode='' versionName='1.0.1.0' platformBuildVersionName=''
sdkVersion:'21'
targetSdkVersion:'21'
uses-permission: name='android.permission.INTERNET'

apkファイルのdump (resource表示)

# aapt d resources xxx.apk

apkファイルのversion情報の表示

# aapt d xmltree xxx.apk AndroidManifest.xml | grep android:versionName | cut -d'"' -f2

スポンサードリンク

スポンサードリンク