zoukankan      html  css  js  c++  java
  • 反编译APK文件的三种方法(转)

    因为学习Android编程的需要,有时我们需要对网络上发布的应用项目进行学习,可是Android项目一般是通过APK文件进行发布的,我们看不到源代码,嘿嘿,办法总会有的,而且不止一个...

       ps:对于软件开发人员来说,保护代码安全也是比较重要的因素之一,不过目前来说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 Filesandroid-sdk-windows-1.6_r1platformsandroid-1.6 ools>dexdump.exe -d classes.dex > spk.dump.txt

         得到的文件内容,描述了类的信息,但实在是不好读啊~~~~

    二、dex2jar + XJad 方法

         该方法是使用dex2jar.jar包,将classes.dex文件解包成jar,在通过XJad(或者其他class反编译工具)进行java反编译。如:

         1、dex2jar.bat d:playclasses.dex

              默认的输出路径同classes.dex,生成的文件名为classes.dex.dex2jar.jar

         2、使用XJad反编译该jar包

              之后的使用方法,大家都懂的:)

         该方法的好处在于,通过XJad反编译后,大家可直接开到java源文件,缺点在于只能反编译出开发时的java文件,而开发时使用的lib包不能反编译出来。

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

          这个方法就强大了,AXMLPrinter2是还原AndroidManifest.xml和main.xml的工具,直接打开这两个xml文件是乱码,而通过还原之后,可以很明白的看到里面的内容(我猜测还是使用了字节异或的方式加的密)。

          baksmali.jar是反解析dex的工具,smali.jar则是再还原成dex的工具

          操作方式如下:

         1、java -jar AXMLPrinter2.jar D:playAndroidManifest.xml > AndroidManifest.txt

         2、java -jar AXMLPrinter2.jar D:play eslayoutmain.xml > main.txt

         3、java -jar baksmali-1.2.5.jar -o classout/ d:playclasses.dex

          baksmali可解析(注意,是解析,不是反编译)原java包以及引用的lib包,解析出的文件认真看还是能看懂,比如以下片段:

    view plaincopy to clipboardprint?
    .class Lcom/paul/test/a;   
    .super Landroid/view/View;   
      
    # static fields   
    .field private static final a:Landroid/graphics/Typeface;   
      
    # instance fields   
    .field private b:I   
    .field private c:I   
    .field private d:Z   
    .field private e:J   
    .field private f:I   
    .field private l:[Ljava/lang/String;   
      
    # direct methods   
    .method static constructor <clinit>()V   
        .registers 2  
        sget-object v0, Landroid/graphics/Typeface;->SANS_SERIF:Landroid/graphics/Typeface;   
        const/4 v1, 0x0  
        invoke-static {v0, v1}, Landroid/graphics/Typeface;->create(Landroid/graphics/Typeface;I)Landroid/graphics/Typeface;   
        move-result-object v0   
        sput-object v0, Lcom/wiyun/ad/a;->a:Landroid/graphics/Typeface;   
        return-void  
    .end method   
    #   
    # other methods ..........   
    #   
    # virtual methods   
    .method public onKeyUp(ILandroid/view/KeyEvent;)Z   
        .registers 4  
        const/16 v0, 0x42  
        if-eq p1, v0, :cond_8   
        const/16 v0, 0x17  
        if-ne p1, v0, :cond_b   
        :cond_8   
        invoke-direct {p0}, Lcom/paul/test/a;->d()V   
        :cond_b   
        const/4 v0, 0x0  
        invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V   
        invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z   
        move-result v0   
        return v0   
    .end method  
    .class Lcom/paul/test/a;
    .super Landroid/view/View;

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

    # instance fields
    .field private b:I
    .field private c:I
    .field private d:Z
    .field private e:J
    .field private f:I
    .field private l:[Ljava/lang/String;

    # direct methods
    .method static constructor <clinit>()V
        .registers 2
        sget-object v0, Landroid/graphics/Typeface;->SANS_SERIF:Landroid/graphics/Typeface;
        const/4 v1, 0x0
        invoke-static {v0, v1}, Landroid/graphics/Typeface;->create(Landroid/graphics/Typeface;I)Landroid/graphics/Typeface;
        move-result-object v0
        sput-object v0, Lcom/wiyun/ad/a;->a:Landroid/graphics/Typeface;
        return-void
    .end method
    #
    # other methods ..........
    #
    # virtual methods
    .method public onKeyUp(ILandroid/view/KeyEvent;)Z
        .registers 4
        const/16 v0, 0x42
        if-eq p1, v0, :cond_8
        const/16 v0, 0x17
        if-ne p1, v0, :cond_b
        :cond_8
        invoke-direct {p0}, Lcom/paul/test/a;->d()V
        :cond_b
        const/4 v0, 0x0
        invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V
        invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z
        move-result v0
        return v0
    .end method


    认真一看,就知道:

    # static fields             定义静态变量的标记

    # instance fields        定义实例变量的标记

    # direct methods       定义静态方法的标记

    # virtual methods      定义非静态方法的标记

    以onKeyUp方法为例,其中定义了处理逻辑,if-eq p1, v0, :cond_8 表示如果p1和v0相等,则执行cond_8的流程:

        :cond_8
        invoke-direct {p0}, Lcom/paul/test/a;->d()V

    调用com.paul.test.a的d()方法

    不相等: if-ne p1, v0, :cond_b 则执行cond_b的流程:

        :cond_b
        const/4 v0, 0x0

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

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

        move-result v0

    大概意思就是调用com.paul.test.a的setPressed方法,然后再调用父类View的onKeyUp方法

    最后 return v0

          该方法,能把外部引用的lib包类也解析出来,能开到包的全貌。缺点在于,解析出的smali文件并不是反编译出的java文件,可读性降低了,但仔细研究也能看出大概。

  • 相关阅读:
    mysql报错:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
    MD5登陆密码的生成
    15. 3Sum、16. 3Sum Closest和18. 4Sum
    11. Container With Most Water
    8. String to Integer (atoi)
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    几种非线性激活函数介绍
    AI初探1
    AI初探
  • 原文地址:https://www.cnblogs.com/qq78292959/p/4290121.html
Copyright © 2011-2022 走看看