Android APK反编译教程

只愿长相守 提交于 2020-04-07 10:43:54
Google Android平台选择了Java Dalvik VM的方式使其程序很容易破解和被修改,首先APK文件其实就是一个MIME为ZIP的压缩包,我们修改ZIP后缀名方式可以看到内部的文件结构,类似Sun JavaMe的Jar压缩格式一样,不过比较去别的是Android上的二进制代码被编译成为Dex的字节码,所有的Java文件最终会编译进该文件中去,作为托管代码既然虚拟机可以识别,那么我们就可以很轻松的反编译。所有的类调用、涉及到的方法都在里面体现到,至于逻辑的执行可以通过实时调试的方法来查看,当然这需要借助一些我们自己编写的跟踪程序。Google最然在Android Market上设置了权限保护app-private文件夹的安全,但是最终我们使用修改定值的系统仍然可以获取到需要的文件。

一、dexdump方法  

dexdump是emulator自带提供的查看dex文件的工具,可使用类似这样的命令将dex文件dump到txt文件中:
D:\Program Files\android-sdk-windows-1.6_r1\platforms\android-1.6\tools>dexdump.exe -d classes.dex > spk.dump.txt
得到的文件内容,描述了类的信息,但是不怎么好阅读

二、AXMLPrinter2.jar + baksmali.jar + smali.jar 方法


这个方法就强大了,AXMLPrinter2是还原AndroidManifest.xml和main.xml的工具,直接打开这两个xml文件是乱码,而通过还原之后,可以很明白的看到里面的内容(我猜测还是使用了字节异或的方式加的密)。
baksmali.jar是反解析dex的工具,smali.jar则是再还原成dex的工具
操作方式如下:
  1. 1、java -jar AXMLPrinter2.jar D:\play\AndroidManifest.xml > AndroidManifest.txt
  2. 2、java -jar AXMLPrinter2.jar D:\play\res\layout\main.xml > main.txt
  3.      3、java -jar baksmali-1.2.5.jar -o classout/ d:\play\classes.dex
复制代码
baksmali可解析(注意,是解析,不是反编译)原java包以及引用的lib包,解析出的文件认真看还是能看懂,比如以下片段:


  1. view plaincopy to clipboardprint?
  2. .class Lcom/paul/test/a;   
  3. .super Landroid/view/View;   
  4.   
  5. # static fields   
  6. .field private static final a:Landroid/graphics/Typeface;   
  7.   
  8. # instance fields   
  9. .field private b:I   
  10. .field private c:I   
  11. .field private d:Z   
  12. .field private e:J   
  13. .field private f:I   
  14. .field private l:[Ljava/lang/String;   
  15.   
  16. # direct methods   
  17. .method static constructor <clinit>()V   
  18.     .registers 2  
  19.     sget-object v0, Landroid/graphics/Typeface;->SANS_SERIF:Landroid/graphics/Typeface;   
  20.     const/4 v1, 0x0  
  21.     invoke-static {v0, v1}, Landroid/graphics/Typeface;->create(Landroid/graphics/Typeface;I)Landroid/graphics/Typeface;   
  22.     move-result-object v0   
  23.     sput-object v0, Lcom/wiyun/ad/a;->a:Landroid/graphics/Typeface;   
  24.     return-void  
  25. .end method   
  26. #   
  27. # other methods ..........   
  28. #   
  29. # virtual methods   
  30. .method public onKeyUp(ILandroid/view/KeyEvent;)Z   
  31.     .registers 4  
  32.     const/16 v0, 0x42  
  33.     if-eq p1, v0, :cond_8   
  34.     const/16 v0, 0x17  
  35.     if-ne p1, v0, :cond_b   
  36.     :cond_8   
  37.     invoke-direct {p0}, Lcom/paul/test/a;->d()V   
  38.     :cond_b   
  39.     const/4 v0, 0x0  
  40.     invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V   
  41.     invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z   
  42.     move-result v0   
  43.     return v0   
  44. .end method  
  45. .class Lcom/paul/test/a;
  46. .super Landroid/view/View;

  47. # static fields
  48. .field private static final a:Landroid/graphics/Typeface;

  49. # instance fields
  50. .field private b:I
  51. .field private c:I
  52. .field private d:Z
  53. .field private e:J
  54. .field private f:I
  55. .field private l:[Ljava/lang/String;

  56. # direct methods
  57. .method static constructor <clinit>()V
  58.     .registers 2
  59.     sget-object v0, Landroid/graphics/Typeface;->SANS_SERIF:Landroid/graphics/Typeface;
  60.     const/4 v1, 0x0
  61.     invoke-static {v0, v1}, Landroid/graphics/Typeface;->create(Landroid/graphics/Typeface;I)Landroid/graphics/Typeface;
  62.     move-result-object v0
  63.     sput-object v0, Lcom/wiyun/ad/a;->a:Landroid/graphics/Typeface;
  64.     return-void
  65. .end method
  66. #
  67. # other methods ..........
  68. #
  69. # virtual methods
  70. .method public onKeyUp(ILandroid/view/KeyEvent;)Z
  71.     .registers 4
  72.     const/16 v0, 0x42
  73.     if-eq p1, v0, :cond_8
  74.     const/16 v0, 0x17
  75.     if-ne p1, v0, :cond_b
  76.     :cond_8
  77.     invoke-direct {p0}, Lcom/paul/test/a;->d()V
  78.     :cond_b
  79.     const/4 v0, 0x0
  80.     invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V
  81.     invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z
  82.     move-result v0
  83.     return v0
  84. .end method
复制代码
认真一看,就知道:
# static fields             定义静态变量的标记
# instance fields        定义实例变量的标记
# direct methods       定义静态方法的标记
# virtual methods      定义非静态方法的标记
以onKeyUp方法为例,其中定义了处理逻辑,if-eq p1, v0, :cond_8 表示如果p1和v0相等,则执行cond_8的流程:

  1.     :cond_8
  2.     invoke-direct {p0}, Lcom/paul/test/a;->d()V
复制代码
调用com.paul.test.a的d()方法
不相等: if-ne p1, v0, :cond_b 则执行cond_b的流程:

  1.     :cond_b
  2.     const/4 v0, 0x0

  3.     invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V

  4.     invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z

  5.     move-result v0
复制代码
大概意思就是调用com.paul.test.a的setPressed方法,然后再调用父类View的onKeyUp方法
最后
  1. return v0
复制代码
      该方法,能把外部引用的lib包类也解析出来,能开到包的全貌。缺点在于,解析出的smali文件并不是反编译出的java文件,可读性降低了,但仔细研究也能看出大概。

三、dex2jar + XJad 方法

一、反编译Apk得到Java源代码
首先要下载两个工具:dex2jar和JD-GUI
前者是将apk中的classes.dex转化成Jar文件,而JD-GUI是一个反编译工具,可以直接查看Jar包的源代码。以下是下载地址:
dex2jar:http://laichao.googlecode.com/files/dex2jar-0.0.7-SNAPSHOT.zip
JD-GUI:http://laichao.googlecode.com/files/jdgui.zip
具体步骤:
首先将apk文件,将后缀改为zip,解压,得到其中的classes.dex,它就是java文件编译再通过dx工具打包而成的;
解压下载的dex2jar,将classes.dex复制到dex2jar.bat所在目录。在命令行下定位到dex2jar.bat所在目录
运行
dex2jar.bat    classes.dex
生成
classes.dex.dex2jar.jar
生成jar文件的截图如下:
0_1314542835TY9r.gif 

运行JD-GUI(jd-gui.exe),打开上面生成的jar包,即可看到源代码了


0_1314542895t80o.gif 


HelloAndroid源码(编译前的apk源码对照)如下:
0_1314542945u7Th.gif 


二、反编译apk生成程序的源代码和图片、XML配置、语言资源等文件
如果是只是汉化软件,这将特别有用。
首先还是下载工具,这次用到的是apktool
下载地址:http://code.google.com/p/android-apktool/downloads/list
下载:apktool1.4.1.tar.bz2 和 apktool-install-windows-r04-brut1.tar.bz2(两个包都下载)
具体步骤:
将下载的两个包解压到同一个文件夹下,应该会有三个文件:aapt.exe,apktool.bat,apktool.jar
在命令行下定位到apktool.bat文件夹,输入以下命令:apktool d C:\*.apk C:\*文件夹,如下图:

0_1314543082NXJ7.gif 
命令行解释:apktool   d   [apk文件 ]   [输出文件夹]
反编译的文件如下(AndroidManifest.xml为例):



0_131454313515no.gif 



特别注意:你要反编译的文件一定要放在C盘的根目录里
将反编译完的文件重新打包成apk,很简单,输入apktool b c:\***文件夹(你编译出来文件夹)即可,命令如下:

0_1314543163UrUV.gif 

打包apk后的文件在目录C:\HelloAndroid下,生成了两个文件夹:
build
dist
其中,打包生成的HelloAndroid.apk,在上面的dist文件夹下,Ok


注 :上述android反编译教程,是在Windows 7  Ultimate  64bit ,测试通过


系列教程:
android应用、ROM开发者入门FAQ
JDK环境搭建以及APKTool和signapk整合工具及使用教程
Android平台ROM的定制及精简教程
Android APK反编译教程
Android ROM界面美化定制基础教程——第一屏开机动画修改
Android ROM定制——界面美化基础(framework-res、SystemUI修改)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!