读书人

反编译而且修改Android APK包

发布时间: 2012-08-24 10:00:20 作者: rapoo

反编译并且修改Android APK包

了某的,我估反 Android 用程式的可行性,本文即是者的心得的例,供考。就者的知,目前有 Android 的 DEX to Java source 反工具,可理一般的 Android 用程式,多半要圈,得到不甚理想的果,不,smali 反工具,已是可用了,只是得付似 Jasmin 法的 Dalvik 合言。者打包了 smali Frozen Bubble for Android,作示:

http://0xlab.org/~jserv/dex-dis-example.tar.bz2在 GNU/Linux 境中,首先取得 Android SDK,用 Eclair/2.1,工具行的路是 android-sdk-linux_86/tools,此路放入 $PATH 境,如此一,就可以操作 adb, aapt, apkbuilder 一的工具程式。者提供的套件已包含 Frozen Bubble 行,名 "FrozenBubble-orig.apk"。一旦 Android emulator 後,即可安去行:(後的操作也需要 Emulator 持)
$ adb install -r FrozenBubble-orig.apk
以下是行面:



反编译而且修改Android APK包
?
然,必要者置喙如何玩典,不我倒是想更改原本的行。在行之前,我先 Android APK 的建立,考 "How to build Android application package (.apk) from the command line using the SDK tools + continuously integrated using CruiseControl." 一文,我可以下表知悉部的流程:



反编译而且修改Android APK包
?

假我完全法取得原始程式,如何行呢?,就透 smali,化繁的流程,者包 Makefile,所以只要先解反:
$ make extract
候看到目:
smali-src : 存放反的程式出workspace : 原本 Frozen Bubble 的 Android resource files二不,然是察反的果:
smali-src$ find
./org/jfedor/frozenbubble/FrozenBubble.smali
./org/jfedor/frozenbubble/R$id.smali
./org/jfedor/frozenbubble/GameView.smali
./org/jfedor/frozenbubble/SoundManager.smali
./org/jfedor/frozenbubble/LaunchBubbleSprite.smali
./org/jfedor/frozenbubble/Compressor.smali
./org/jfedor/frozenbubble/R$attr.smali
./org/jfedor/frozenbubble/BubbleFont.smali
./org/jfedor/frozenbubble/PenguinSprite.smali
./org/jfedor/frozenbubble/GameView$GameThread.smali
./org/jfedor/frozenbubble/BubbleSprite.smali./org/jfedor/frozenbubble/R$string.smali
./org/jfedor/frozenbubble/R$drawable.smali
./org/jfedor/frozenbubble/ImageSprite.smali
./org/jfedor/frozenbubble/BubbleManager.smali
./org/jfedor/frozenbubble/GameScreen.smali
./org/jfedor/frozenbubble/R.smali
./org/jfedor/frozenbubble/R$layout.smali
./org/jfedor/frozenbubble/BmpWrap.smali./org/jfedor/frozenbubble/FrozenGame.smali
./org/jfedor/frozenbubble/Sprite.smali
./org/jfedor/frozenbubble/LevelManager.smali
./org/jfedor/frozenbubble/R$raw.smali
就忠地依 Java package 的方式呈,名尾是 ".smali"。者的修改目是,一始的卡 (Level) 第一直接跳到第五。在 smali 原始程式 (注意:完全不同於 Java 原始程式,而是近 Dalvik VM 所接受的 DEX 案的合言形式) 搜 "Level" 字眼,可主要的分就落於案:
./org/jfedor/frozenbubble/GameView$GameThread.smali./org/jfedor/frozenbubble/LevelManager.smali前者就是 org/jfedor/frozenbubble/GameView.java 的出,因是 inner class,立出 org/jfedor/frozenbubble/GameView.class$GameThread.smali,由 class 命名方式大概就可猜出其重要性,基本上只要能控制此 class 的做,就掌握此 Android 用程式的行。而 class LevelManager 名思,看掌握了行的程序控制。先察其 method 列表:
smali-src$ grep "\.method" org/jfedor/frozenbubble/LevelManager.smali
.method public constructor <init>([BI)V
.method private getLevel(Ljava/lang/String;)[[B
.method public getCurrentLevel()[[B
.method public getLevelIndex()I
.method public goToFirstLevel()V
.method public goToNextLevel()V.method public restoreState(Landroid/os/Bundle;)V
.method public saveState(Landroid/os/Bundle;)V
倘若我以 "goToFirstLevel" 一的字,在 org/jfedor/frozenbubble/GameView$GameThread.smali 案中搜,可找出有具的呼叫行:
smali-src$ grep -r goToFirstLevel *
org/jfedor/frozenbubble/GameView$GameThread.smali: invoke-virtual {v2}, Lorg/jfedor/frozenbubble/LevelManager;->goToFirstLevel()V
org/jfedor/frozenbubble/LevelManager.smali:.method public goToFirstLevel()V
由此更定我之前的猜想。其中合言以下:
move-object/from16 v0, p0

iget-object v0, v0, Lorg/jfedor/frozenbubble/GameView$GameThread;->mLevelManager:Lorg/jfedor/frozenbubble/LevelManager;

move-object v2, v0

invoke-virtual {v2}, Lorg/jfedor/frozenbubble/LevelManager;->goToFirstLevel()V
不要被貌似的法到了,基本上掌握 Java 程式言的原 "Everything is Object" (不仍有提供 primitive type),合言仍作 Java Object 的化 (instantialization),Dalvik 本身是 Register-based Virtual Machine,而扣除 static/class method 外,Java 中所有的 method invocation 多 virtual function (於 C++ 的,才能更具用械方式思考),所以合言的指令 "invoke-virtual" (注意有字,此 Java bytecode 不同),"{v2}" 表示第一受者的 Register,此 Object 本。接著, Java bytecode 一,"Lorg/jfedor/frozenbubble/LevelManager;" 就表示 Java 面的 class "org.jfedor.frozenbubble.LevelManager",字母 "L" 即 class 的,而 "->" 就很直了,自然是 method invocation,所以看,一段合言的 Java 意思:
objectLevelManager.goToFirstLevel();
其中 objectLevelManager 是一 class LevelManager 的例/ (instance)。倘若需要在 method invocation ,入,那前述的 "{v2}" 一般被替 "{v0, v1, v2, ...} 的 register 列表。於的,可考 Dalvik 非官方明,另外 smali 的 wiki 也提供一些例,可多加利用。

回到者定的目,我既然知道 class org.jfedor.frozenbubble.GameView$GameThread 掌控了程式理,自然一堆的、method 呼叫,都在此行,那我先著用 "level" 字串去搜,想法找出常定,後者在 Dalvik 中,集中保存於 constant pool 中,而 smali 的合言法大致是 "const" 的宣告,端看其型而定。以程式追的目的,我注於以下:
const-string : primitive string (不同於 java.lang.String) 表示const/4 : 度 4 bytes (32 bit) 的整表示字串何其多,依之前的推,我要找接近 "LevelManager" 字眼的合言程式,道理很明,一般 Java programmer 的作去反推。一番搜,我找到以下的反程式: (位於案 org/jfedor/frozenbubble/GameView$GameThread.smali中)
const-string v3, "level"
const/4 v4, 0x0
move-object/from16 v0, v25 move-object v1, v3
move v2, v4
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
move/from16 v2, p4 invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V
在上述程式列表中,"Lorg/jfedor/frozenbubble/LevelManager;-><init>" 表示呼叫 class LevelManager 的 constructor,也就是 "<init>"。注意到 method invocation 方式就不同了,是 "invoke-direct",表示 class constructor,而之前要有 "new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;" 的合言指令宣告。

前面「倘若需要在 method invocation ,入,一般被替 "{v0, v1, v2, ...} 的 register 列表」的概念,我可推知,Register v1 v2 就是上 class org.jfedor.frozenbubble.LevelManager 的 constructor 。就程式的看,class GameView 就是依某流程,要求 LevelManager 去改,所以的,其就是初始值,非常的重要。

Register v1 相的合言指令有行:(用粗字示)
const-string v3, "level"
const/4 v4, 0x0
move-object/from16 v0, v25
move-object v1, v3
move v2, v4
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
move/from16 v2, p4
invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V
然,Register v1 被入到 android.content.Shared.Preference.getInt() method,而更早以前,其含值被定 Register v3 的值,也就是常字串 (const-string) "level",好像我的焦不同。另外,像是 Register v22 大的 register,表示 local variable,需要多留意,因 Java 程式的,往往程式切割若干 method,而 method 做中,又有多的 local variable,於是往往可合言反推 Java 原始的型。

那,看看 Register v2 吧,同用粗字示相的指令:
const-string v3, "level"
const/4 v4, 0x0
move-object/from16 v0, v25
move-object v1, v3
move v2, v4
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
move/from16 v2, p4
invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V
Register v4 的含值 "0x0" 指派到 Register v2 中,而我似乎找到方向了,回看看 class org.jfedor.frozenbubble.LevelManager 的 constructor 宣告方式: (之前 grep 果的第一行)
smali-src$ grep "\.method" org/jfedor/frozenbubble/LevelManager.smali
.method public constructor <init>([BI)V
其中 "public" 是 ACL (存取限) 的宣告,而 constructor 的符 "<init>",注意到括 "(" ")" 面的大字母,表示接受,的型:
B : byteI : int在 Java Dalvik virtual machine 皆以同的形式作宣告,看到,我在忍不住要手修改了,然,一切都是性。既然一,面就示 Level 1,表示 LevelManager 一始接受的 level 是 "0",然後依 GameView 的,逐一升或中行,那,如果要一起就是 Level 5,是不是要把含值改 0x4 即可?也就是 "invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V" 的 Register v2 含值 0x4,不就任成了?想到此,不禁心一笑。

不,回稍早 Register v2 的相程式出,其中有行需要留意 (以粗字主):
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
move/from16 v2, p4
"p4" 用以保存 method invocation 之後的回值,然,Register v2 受到 p4 的指派,也就是被更 android.content.Shared.Preference.getInt() method 的回值,存在不定性,於是,我乾脆一口改掉: (修改的部份用井字 "#" 作解)
# Modified from 0x0 to 0x4"
const/4 v4, 0x4
move-object/from16 v0, v25
move-object v1, v3
move v2, v4
# Modified: removed the following 2 lines
# invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
# move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
# Modified: removed the following 1 line
# move/from16 v2, p4
invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V
改好程式,然要,回到上一目,透 smali 提供的器,重新生 Dalvik DEX 出,了化流程,者把 smali, apkbuilder, aapt, adb install 都一次整合去,所以直接 Android Emulator 生效,看看我的果吧:


反编译而且修改Android APK包
?注意到左下角,表示我成功了,完全不用取得 Java 原始程式,就可以作反且修改的作。

读书人网 >Android

热点推荐