• Android Apk的反编译与代码混淆


    一、反编译

    1.获取工具:
      既然是反编译,肯定要用到一些相关的工具,工具可以到这里下载,里面包含三个文件夹,用于反编译,查看反编译之后的代码;
      其实这两工具都是google官方出的,也可在google code上下载 dex2jarapktool

    2-1.反编译获取Java源代码:
      将要反编译的apk文件后缀改为zip并解压,得到classes.dex,它就是java文件编译再通过dx工具打包而成的,将classes.dex复制到apk2java目录下的dex2jar-0.0.9.9文件夹;在命令行下进入dex2jar-0.0.9.9文件夹,输入命令:dex2jar.bat classes.dex,会生成一个jar文件classes_dex2jar.jar,用工具包中jdgui工具即可查看代码;

    2-2.反编译获取程序的源代码和图片、XML配置、语言资源等文件:
      打开apk2java文件夹,进入apktool1.4.1,里面有三个文件aapt.exeapktool.batapktool.jar;
      在命令行下定位到apktool1.4.1文件夹,输入命令:apktool.bat  d  abc123.apk  abc123;后两个参数分别是apk所在位置,反编译后代码存放位置;下面是我反编译QQ得到的AndroidManifest.xml文件的内容,输入命令为:apktool.bat d c:qq.apk c:qq;

    2-3.将反编译出来的文件重新打包:同样,在apktool1.4.1文件夹下,输入命令:apktool.bat b c:qq c:\qq表示需要重新打包的文件所在的位置;

      等待生成,生成的文件在qq/dist文件夹下,当然,这个程序是不能使用的,因为没有签名;关于签名后面会有讲述;

    3.图形化反编译:
      在工具包中,还有一个文件夹Androidfby,里面包含两个图形化反编译工具,其本质上就是对dex2jar和apktool两个工具进行了一层包装,使之有一个图形化的操作界面;

      
      

    二、代码混淆

      前面说了反编译,我们当然不希望我们的应用被别人反编译,所以就得在打包的时候进行代码混淆,这样的包也可反编译出代码,但是代码的可读性很低,从而达到保护代码的目的;
      在我们新建的项目中,都有一个proguard-project.txt文件,默认里面是没有任何配置的,只有一些说明性的注释文字;我们就是能过它,来进行代码混淆的,首先需要为该文件添加需要混淆的代码说明;

     -optimizationpasses 5
     -dontusemixedcaseclassnames
     -dontskipnonpubliclibraryclasses
     -dontpreverify
     -verbose
     -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
    
     -keep public class * extends android.app.Activity
     -keep public class * extends android.app.Application
     -keep public class * extends android.app.Service
     -keep public class * extends android.content.BroadcastReceiver
     -keep public class * extends android.content.ContentProvider
     -keep public class * extends android.app.backup.BackupAgentHelper
     -keep public class * extends android.preference.Preference
     -keep public class com.android.vending.licensing.ILicensingService
    
     -keepclasseswithmembernames class * {
         native <methods>;
     }
    
     -keepclasseswithmembernames class * {
         public <init>(android.content.Context, android.util.AttributeSet);
     }
    
     -keepclasseswithmembernames class * {
         public <init>(android.content.Context, android.util.AttributeSet, int);
     }
    
     -keepclassmembers enum * {
         public static **[] values();
         public static ** valueOf(java.lang.String);
     }
    
     -keep class * implements android.os.Parcelable {
       public static final android.os.Parcelable$Creator *;
     }
      在上面的脚本文件混淆中,保留了继承自Activity、Service、Application、BroadcastReceiver、ContentProvider等基本组件以及com.android.vending.licensing.ILicensingService,并保留了所有的Native变量名及类名,所有类中部分以设定了固定参数格式的构造函数,枚举等等。(详细信息请参考android-sdk oolsproguardexamples中的例子及注释。)
      最后,在project.properties文件中,添加对proguard-project.txt文件的引用:proguard.config=proguard-project.txt
      下面是一个代码混淆过后的apk反编译之后得到的代码,可以看出,如果给你一个这样的jar文件,你如何去读取整理它的代码?
      
     
    >>延伸扩展:
    1。当程序中有使用第三方jar包时,常常需要过滤掉反射的R文件及jar包,以及防止读取jar包是出现读取错误、防止因为警告导致打包不成功等等问题;
      -keep class **.R$* {   *;  }   过滤R文件
      -keep class packagename.** {*;}   过滤第三方包(packagename为第三方包的包名)
      -libraryjars libs/mmbilling.jar   防止读取第三方jar包时读取内容错误
      -dontwarn android.net.http.**   不提示读取某个包的警告
    2。当混淆打包的apk文件上有bug时,我们一般所用的统计平台所收集到的错误信息也是混淆之后的代码信息,我们自身也看不明白了,这种情况下可以单独把某个类提取出来,不进行混淆;参考上面对继承了Activity的类的保留方法,对单个个别的类进行保留;
      
    三、程序打包签名
      生成keystore,生成keystore有两种方式,一是在eclipse中生成,还有一种是在命令行中生成,在这里我只说在命令行中生成;
    • 打开命令行窗口,进入jdk文件夹下面的bin目录,输入命令:keytool -genkey -v -keystore android.keystore -alias android.keystore -keyalg RSA -validity 20000
    • 接下来会让输入一个keystore文件的属性配置,输入合法的属性就行,最后会让确认信息是否正确,输入y,创建keystore完成;
    • 对未签名的程序进行签名:jarsigner -verbose -keystore appkey.keystore -signedjar c: est_signed.apk c: est_unsign.apk your_alias
    • 进入apk所在文件目录:jarsigner -verbose -keystore appkey.keystore -storepass xoxopassword -signedjar test_signed.apk -digestalg SHA1 -sigalg MD5withRSA test_unsign.apk your_alias
    可能遇到的问题:找不到xx的证书链。xx必须引用包含专用密钥和相应的公共密钥证书链的有效密钥库密钥条目。
    这个问题一般是签名的别名写错了,可以通过如下的命令查看keystore文件的别名(前提是要在jdk所在文件夹下面的bin目录);
    keytool -list  -v -keystore xxxx.keystore -storepass (password密码)
     
     
     
     
     
  • 相关阅读:
    Log4Net 自定义级别,分别记录到不同的文件中
    带着忧伤,寻觅快乐
    程序员进阶学习书籍
    PHP编码技巧
    PHP精度问题
    Laravel5 构造器高级查询条件写法
    正则表达式 /i /g /m /ig /gi
    MySQL运算符的优先级
    PHP获取当前页面完整路径URL
    使用ssl模块配置同时支持http和https并存
  • 原文地址:https://www.cnblogs.com/a284628487/p/3555550.html
Copyright © 2020-2023  润新知