混淆_混淆矩阵 - CSDN
  • 数据仓库数据混淆

    千次阅读 2018-09-06 15:51:56
    一、什么是数据混淆? 在技术领域,数据混淆(也成为数据掩蔽)是将测试或开发环境中现有的敏感信息替换为看起来像真实生产信息的信息,但这些信息无法被任何人滥用。换句话说,测试或开发环境的用户不需要看到真实...

    一、什么是数据混淆?

    在技术领域,数据混淆(也成为数据掩蔽)是将测试或开发环境中现有的敏感信息替换为看起来像真实生产信息的信息,但这些信息无法被任何人滥用。换句话说,测试或开发环境的用户不需要看到真实生产数据,只要这些数据与真实数据相似即可。因此,数据混淆计划被用于保护数据,它可帮助掩蔽非生产环境中包含的敏感信息,让企业可缓解数据泄露的风险。数据混淆也是数据仓库体系厘里面一个重要的组成部分。

     

    二、对数据混淆技术的需求

    企业通常需要将生产数据库中存储的生产数据复制到非生产或测试数据库,这样做是为了真实地完成应用功能测试以及涵盖实时场景或最大限度减少生产漏洞或缺陷。这种做法的影响是,非生产环境很容易成为网络罪犯或恶意内部人员的简易目标,让他们可轻松地获取敏感数据。由于非生产环境并没有像生产环境那样受到严格控制和管理,当数据泄露事故发生时,企业可能需要花费数百万美元修复声誉损害或者品牌价值损失。监管要求是数据混淆技术的另一个关键驱动因素。

    例如,支付卡行业数据安全标准(PCI DSS)鼓励商家加强支付卡数据安全,广泛部署一致的数据安全做法,满足技术和操作要求。PCI DSS要求商家的生产环境和信息不能用于测试和开发。不当的数据泄露(无论是意外还是恶意事件)都会带来毁灭性后果,并可能导致高昂的罚款或法律行为。

     

    三、数据混淆用例

    数据混淆技术的典型用例是当开发环境数据库交由第三方供应商或外包商处理和管理时;

    数据混淆是确保第三方供应商可执行其职责及功能非常重要的工具。通过部署数据混淆技术,企业可使用数据库中相似值来替换敏感信息,而不必担心第三方供应商在开发期间暴露该信息。

    另一个典型用例是在零售业,零售商需要与市场研究公司共享客户销售点数据以运用高级分析算法来分析客户的购买模式和趋势。零售商不必向研究公司提供真实的客户数据,而可提供类似真实客户数据的替代数据。

    这种方法可帮助企业减少通过业务合作伙伴或其他第三方供应商泄露数据的风险。

     

    四、采取的技术方案

    1.数据仓库内部方案

    此处我使用的是Hive来做数据仓库,然后在Hive内部分层,利用SQL, 加密算法等从一个存储数据的层次抽取到另一个层次。然后将这个层次的数据展示给外部。

     

    2.数据外部使用方案

    此处我们引用轻量级结构化数据库Mysql或着其他的数据库, 利用第三方开源组件将数据加密抽取过来。

    展开全文
  • 代码混淆详解

    万次阅读 多人点赞 2014-11-12 20:45:56
    什么是代码混淆 Java 是一种跨平台的、解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中。由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量...

    什么是代码混淆

    Java 是一种跨平台的、解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中。由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码。为了防止这种现象,我们可以使用 Java 混淆器对 Java 字节码进行混淆。

    混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的况下,即使被反编译,也将难以阅读。同时混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

    混淆器的作用不仅仅是保护代码,它也有精简编译后程序大小的作用。由于以上介绍的缩短变量和函数名以及丢失部分信息的原因, 编译后 jar 文件体积大约能减少25% ,这对当前费用较贵的无线网络传输是有一定意义的。

    混淆文件 proguard.cfg 参数详解

    -optimizationpasses 5                                                           # 指定代码的压缩级别
    -dontusemixedcaseclassnames                                                     # 是否使用大小写混合
    -dontskipnonpubliclibraryclasses                                                # 是否混淆第三方jar
    -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 方法不被混淆
        native <methods>;
    }
    
    -keepclasseswithmembers class * {                                               # 保持自定义控件类不被混淆
        public <init>(android.content.Context, android.util.AttributeSet);
    }
    
    -keepclasseswithmembers class * {
        public <init>(android.content.Context, android.util.AttributeSet, int);     # 保持自定义控件类不被混淆
    }
    
    -keepclassmembers class * extends android.app.Activity {                        # 保持自定义控件类不被混淆
       public void *(android.view.View);
    }
    
    -keepclassmembers enum * {                                                      # 保持枚举 enum 类不被混淆
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    -keep class * implements android.os.Parcelable {                                # 保持 Parcelable 不被混淆
      public static final android.os.Parcelable$Creator *;
    }
    
    -keep class MyClass;                                                            # 保持自己定义的类不被混淆


    代码混淆的方法

    根据 SDK 的版本不同有 2 中不同的代码混淆方式,以上的 proguard.cfg 参数详解中所涉及到的信息是在较低版本 SDK 下的混淆脚本,事实上在高版本的 SDK 下混淆的原理和参数也与低版本的相差无几,只是在不同 SDK 版本的环境下引入混淆脚本的方式有所不同。具体方法如下:

    • 低版本 SDK 下,项目中同时包含 proguard.cfg 和 project.properties 文件,则只需在 project.properties 文件末尾添加 proguard.config=proguard.cfg 再将项目 Export 即可。
    • 高版本 SDK 下,项目中同时包含 proguard-project.txt 和 project.properties 文件,这时需要在 proguard-project.txt 文件中进行如下信息的配置,然后再将项目 Export 即可。下面以真实的文件进行演示说明。
    复制代码
    # This file is automatically generated by Android Tools.
    # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
    #
    # This file must be checked in Version Control Systems.
    #
    # To customize properties used by the Ant build system edit
    # "ant.properties", and override values to adapt the script to your
    # project structure.
    #
    # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
    #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
    
    proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
    
    # Project target.
    target=android-16
    复制代码

    以上的配置信息即是 project.properties 文件中内容,蓝色文字为我们在代码混淆过程中需要添加的配置信息,其中:sdk.dir 为你在当前机器上 SDK 的安装路径。如果想保留某个包下的文件不被混淆,可以在 proguard-project.txt文件中加入保留对应包名的语句即可。

    复制代码
    # To enable ProGuard in your project, edit project.properties
    # to define the proguard.config property as described in that file.
    #
    # Add project specific ProGuard rules here.
    # By default, the flags in this file are appended to flags specified
    # in ${sdk.dir}/tools/proguard/proguard-android.txt
    # You can edit the include path and order by changing the ProGuard
    # include property in project.properties.
    #
    # For more details, see
    #   http://developer.android.com/guide/developing/tools/proguard.html
    
    # Add any project specific keep options here:
    
    -dontwarn com.cnki.android.cnkireader.** 
    -keep class com.cnki.android.cnkireader.** { *; }
    
    # If your project uses WebView with JS, uncomment the following
    # and specify the fully qualified class name to the JavaScript interface
    # class:
    #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
    #   public *;
    #}
    复制代码


    -optimizationpasses 5


    # 混淆时不会产生形形色色的类名 
    -dontusemixedcaseclassnames


    # 指定不去忽略非公共的库类
    -dontskipnonpubliclibraryclasses


    # 不预校验
    # -dontpreverify


    # 预校验
    -dontoptimize 




    # 这1句是屏蔽警告
    -ignorewarnings 
    -verbose


    # 优化
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*


    # 这1句是导入第三方的类库,防止混淆时候读取包内容出错
    #-libraryjars libs/youjar.jar 


    # 去掉警告
    -dontwarn 
    -dontskipnonpubliclibraryclassmembers


    # 不进行混淆保持原样
    -keep public class * extends android.app.Activity
    -keep public class * extends android.app.Application
    -keep public class * extends android.app.Fragment 
    -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




    # 过滤R文件的混淆:
    -keep class **.R$* {*;}


    # 过滤第三方包的混淆:其中packagename为第三方包的包名
    # -keep class packagename.** {*;}
    -keep class com.hisilicon.android.hibdinfo.** {*;}
    -keep class com.huawei.iptv.stb.dlna.mymedia.dto.** {*;}
    -keep class com.huawei.iptv.stb.dlna.mymedia.facade.** {*;}
    -keep class com.huawei.mymediaprifacade.** {*;}
    -keep class com.hisilicon.android.mediaplayer.** {*;}
    -keep class com.nostra13.universalimageloader.** {*;}
    -keep class com.huawei.android.airsharing.** {*;}


    # 所有方法不进行混淆
    -keep public abstract interface com.huawei.android.airsharing.listener{
    public protected <methods>;
    }


    -keep public abstract interface com.huawei.android.airsharing.api{
    public protected <methods>;
    }


    # 对该方法不进行混淆
    # -keep public class com.asqw.android{
    # public void Start(java.lang.String); 
    # }


    # 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)
    #-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 class * extends android.app.Activity {
    public void *(android.view.View);
    }




    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }


    # 保护指定的类文件和类的成员
    -keep class * implements android.os.Parcelable {
      public static final android.os.Parcelable$Creator *;
    }


    #-libraryjars libs/android-support-v4.jar
    #-dontwarn android.support.v4.**{*;}


    # If your project uses WebView with JS, uncomment the following
    # and specify the fully qualified class name to the JavaScript interface
    # class:
    -keepclassmembers class fqcn.of.javascript.interface.for.webview {
       public *;
    }


    #不混淆第三方包中的指定内容
    -keep class android-support-v4.**{*;}
    -keep public class * extends android.support.v4.**
    -keep class android.view.**{*;}









    ProGuard是一个免费的java类文件压缩,优化,混淆器.它探测并删除没有使用的类,字段,方法和属性.它删除没有用的说明并使用字节码得到最大优化.它使用无意义的名字来重命名类,字段和方法.

    ProGuard的使用是为了:

    1.创建紧凑的代码文档是为了更快的网络传输,快速装载和更小的内存占用.
    2.创建的程序和程序库很难使用反向工程.
    3.所以它能删除来自源文件中的没有调用的代码
    4.充分利用java6的快速加载的优点来提前检测和返回java6中存在的类文件.

    参数:

    -include {filename} 从给定的文件中读取配置参数

    -basedirectory {directoryname} 指定基础目录为以后相对的档案名称

    -injars {class_path} 指定要处理的应用程序jar,war,ear和目录

    -outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称

    -libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件

    -dontskipnonpubliclibraryclasses 指定不去忽略非公共的库类。

    -dontskipnonpubliclibraryclassmembers 指定不去忽略包可见的库类的成员。

    保留选项
    -keep {Modifier} {class_specification} 保护指定的类文件和类的成员

    -keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好

    -keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。

    -keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)

    -keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除)

    -keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)

    -printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件

    压缩
    -dontshrink 不压缩输入的类文件

    -printusage {filename}

    -whyareyoukeeping {class_specification}

    优化
    -dontoptimize 不优化输入的类文件

    -assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用

    -allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员

    混淆
    -dontobfuscate 不混淆输入的类文件

    -printmapping {filename}

    -applymapping {filename} 重用映射增加混淆

    -obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称

    -overloadaggressively 混淆时应用侵入式重载

    -useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆

    -flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中

    -repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中

    -dontusemixedcaseclassnames 混淆时不会产生形形色色的类名

    -keepattributes {attribute_name,...} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.

    -renamesourcefileattribute {string} 设置源文件中给定的字符串常量

    因为我们开发的是webwork+spring+hibernate的架构的项目,所有需要很详细的配置。(经过n次失败后总结)

    Example:

    -injars <project>.jar

    -outjars <project>_out.jar

    -libraryjars <java.home>/lib/rt.jar

    -libraryjars <project.home>/webroot/WEB-INF/lib/webwork.jar

    .......

    # 保留实现Action接口类中的公有的,友好的,私有的属性 和 公有的,友好的方法。其它的全部压缩,优化,混淆。

    # 因为配置文件中的类名是一个完整的类名,如果经过处理后就有可能找不到这个类。

    # 属性是jsp页面所需要的,如果经过处理jsp页面就无法得到action中的数据。

    -keep public class * implements com.opensymphony.xwork.Action{

    public protected private <fields>;

    public protected <methods>;

    }

    # 保留实现了Serializable接口类中的公有的,友好的,私有的成员(属性和方法)

    # 这个配置主要是对应实体类的配置。

    -keep public class * implements java.io.Serializable{

    public protected private *;

    }



    由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解。下面将自己的理解和认识简要的做个笔记,有异议或者不解的,可以直接留言。

    什么是ProGuard工具?


    ProGuard是android提供的一个免费的工具,它能够移除工程中一些没用的代码,或者使用语义上隐晦的名称来重命名代码中的类、字段和函数等,达到压缩、优化和混淆代码的功能。具体来说,使用ProGuard工具,可以达到下面两个目的:

    • 删除了源文件中没有调用的那部分代码,最大化的精简了字节码文件,使得最终生成的apk文件更小。
    • 使用语义混淆的命名替换了代码中的类、字段和函数等,使得其他人无法反编译获取源代码,起到对代码的保护作用。

    我看网上有不少人根据ProGuard工具的作用,直接称呼其为“混淆代码工具”,本文也暂时用这个词简称。

    更多的理解,可以参考ProGuard工具的官方文档地址:http://developer.android.com/tools/help/proguard.html

    ProGuard工具的集成与使用环境


    其实,ProGuard工具是已经集成到我们android系统中的,所以不需要用户手动的去集成。但是有一点需要注意,仅在程序处于Release模式时ProGuard才有效,反之在Debug模式是不能通过ProGuard来混淆代码的。

    根据ProGuard的具体使用环境,我分在Eclipse工具和android源码两种编译环境浅谈ProGuard的使用方法。

    Eclipse环境中ProGuard的使用


    以我电脑的android4.0环境为例,当我们在Eclipse中新建一个项目,或者导入一个已存在项目(保证当前项目没有语法错误)后,在工程的根目录,会自动生成两个ProGuard的混淆文件:proguard-project.txt和project.properties(在老版本的ADT中,只会生成一个叫proguard.cfg的文件)。我们先看下文件project.properties :

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    # This file is automatically generated by Android Tools.
    # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
    #
    # This file must be checked in Version Control Systems.
    #
    # To customize properties used by the Ant build system edit
    # "ant.properties", and override values to adapt the script to your
    # project structure.
    #
    # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
    #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
    
    # Project target.
    target=android-16
    

    看后面一段注释:To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home) ,意指要让ProGuard 来压缩和混淆代码,把这句注释去掉即可!所以,我们只要把下面一句注释取消即可,如下所示:

    1
    2
    # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
    proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
    

    我们仔细的看下这部分代码:这个地方是通过设置proguard.config属性来指定混淆代码的配置文件为本机SDK目录下面的proguard-android.txt文件,以及制定混淆的个性化配置文件为当前工程(eclipse下)根目录下面的proguard-project.txt文件 ,而后面这个文件,恰是我们刚才看到的原本在根目录下自动生成的另外一个文件!

    其实打开了这个地方,我们就已经可以混淆代码了,不过这里要注意:不能试图通过运行eclipse中的Run as 和 Debug as 菜单来生成混淆代码,必须通过如下图所示的方法将apk导出才行,当然你可以选择“签名”或者“不签名”:

    图片说明文字

    这样一步操作后,算是代码混淆完成了。那么怎么才能检验我们真的混淆了代码了呢?首先,我们能够看到在工程的根目录新生产了一个文件夹proguard,里面有四个文件,其内容如下:

    • dump.txt : 描述了apk中所有类 文件中内部的结构体。( Describes the internal structure of all the class files in the .apk file )
    • mapping.txt : 列出了原始的类、方法和名称与混淆代码见得映射。( Lists the mapping between the original and obfuscated class, method, and field names. )
    • seeds.txt : 列出了没有混淆的类和方法。( Lists the classes and members that are not obfuscated )
    • usage.txt : 列出congapk中删除的代码。( Lists the code that was stripped from the .apk )

    同时使用反编译软件对新生成的apk反编译后会发现,里面的类名、方法和变量等,都变成了简单的a、b、c、d等毫无含义的字母,这样就达到了混淆的目的:
    图片说明文字

    但在实际使用过程中,我们会发现当前apk中的有些方法和类,是要供外部使用的,而此时混淆了名称,外部调用就会报错了,那么怎么解决这个问题?此时就要用到我们刚才提到的混淆的个性化配置文件proguard-project.txt,在其中去配置不需要混淆的类、方法和变量等。关于混淆文件的具体配置方法,请看下面的最后一个标题会有详述。

    Android源码环境中ProGuard使用


    在Google发布的android源码中,面对那么多代码和文件目录,此时该如何混淆代码与配置混淆文件呢?

    android中默认是将代码混淆ProGuard关闭的,在alps/build/core/proguard.flags中有下面一句,意指将默认不混淆,不需要代码删除,我们将这一句注释起来,就起到代码混淆编译的作用。

    1
    2
    # Don't obfuscate. We only need dead code striping.
    -dontobfuscate
    

    可以说,这句是android工程中代码混淆的总开关,然而,注释了上面的代码后,整个工程就已经是代码混淆了吗?不是的,这里还要关注一个文件alps/build/core/package.mk,在这个文件中有这么一段:

    1
    2
    3
    4
    5
    6
    ifndef LOCAL_PROGUARD_ENABLED
    ifneq ($(filter user userdebug, $(TARGET_BUILD_VARIANT)),)
        # turn on Proguard by default for user & userdebug build
        #LOCAL_PROGUARD_ENABLED :=full
    endif
    endif
    

    切记:当我们需要对整个工程进行代码混淆的时候,就把此处的 #LOCAL_PROGUARD_ENABLED :=full注释去掉,成为有效的宏即可。如果不想对整个工程代码混淆,而只是相对某个模块混淆的话,就先不要动这里的代码。

    接着建议将真个工程new一遍,之后就可以针对具体的apk文件进行混淆文件的设置和定制了。下面以alps/packages/apps/Music为例说说该如何对特定模块做到混淆代码:

    在Music目录下,我们看到一个平时不太关注,但今天一定很在意的文件名:proguard.flags ,对了,这个文件就是Music的混淆配置文件,可以打开看看(有些地方没有这个文件,用户可以自己手动新建一下,最好名称也叫proguard.flags,android下默认都是这个名字)。当然,设置了配置文件还是不够的,还需要在同目录的Android.mk中如下设置如下两句:

    1
    2
    LOCAL_PROGUARD_ENABLED  := full
    LOCAL_PROGUARD_FLAG_FILES := proguard.flags
    

    只有这样才能让混淆代码有效,并且将混淆配置文件关联起来。(有些模块没有这两句句,就自己手动加上)

    反之,如果用户已经在alps/build/core/package.mk打开了全工程混淆编译的控制点后,又在针对某个模块时不想混淆编译怎么办?这就简单了,将模块下的Android.mk中设置为**LOCAL_PROGUARD_ENABLED := disabled**即可。

    这样,我们通过mm编译后的代码生成的apk,或者new真个工程后生成的烧机代码,都是已经添加相应配置的混淆代码了。

    反编译后,除过proguard.flags中定制的不需要混淆的代码外,其他都是被混淆了,如图所示是android中Music模块的混淆后反编译结果:

    图片说明文字

    混淆文件的配置


    在实际使用过程中,我们会发现当前apk中的有些方法和类,是要供外部使用的,而此时混淆了名称,外部调用就会报错了,那么怎么解决这个问题?此时就需要我们配置混淆的个性化文件proguard-project.txt(eclipse环境中)或者proguard.flags(android源码环境),在其中去配置不需要混淆的类、方法和变量等。关于混淆文件的具体配置方法,大家可以去搜索下,我这里提供一段网上有人共享的配置代码,这个配置代码保留了工程文件中的Activity、Application、Service、BroadcastReceiver、ContentProvider、BackupAgentHelper、Preference和ILicensingService的子类,并保留了所有的Native变量名及类名,所有类中部分以设定了固定参数格式的构造函数,枚举等等,用来防止外部调用出错,大家可以借鉴下,以后来配置自己的文件:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    -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
    
     -keepclasseswithmembernames class * {
         native <methods>;
    }
    
    -keepclasseswithmembers class * {
        public <init>(android.content.Context, android.util.AttributeSet);
    }
    
    -keepclasseswithmembers class * {
        public <init>(android.content.Context, android.util.AttributeSet, int);
    }
    
    -keepclassmembers class * extends android.app.Activity {
        public void *(android.view.View);
    }
    
    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    -keep class * implements android.os.Parcelable {
        public static final android.os.Parcelable$Creator *;
    }
    

    就写这么多了,有问题和建议,欢迎一起讨论!

    4.2以下版本尝试

         1.android中默认是将代码混淆ProGuard关闭的,在alps/build/core/proguard.flags中有下面一句,意指将默认不混淆,不需要代码删除,我们将这一句注释起来,就起到代码混淆编译的作用。

    1

    2

    # Don't obfuscate. We only need dead code striping.

    -dontobfuscate

                      将上面改为

    1

    2

    # Don't obfuscate. We only need dead code striping.

    #-dontobfuscate

                 2.还要关注一个文件alps/build/core/package.mk,在这个文件中有这么一段:

    1

    2

    3

    4

    5

    6

    ifndef LOCAL_PROGUARD_ENABLED

    ifneq($(filter user userdebug, $(TARGET_BUILD_VARIANT)),)

        # turn on Proguard by defaultfor user& userdebug build

        #LOCAL_PROGUARD_ENABLED :=full

    endif

    endif

                      不动,如果没注释,请注释下,注释为了下面部分加扰,打开应该是全部加扰,没有尝试过

                      3.在自己的工程下下面Android.mk里添加

    LOCAL_PROGUARD_ENABLED  := full

    LOCAL_PROGUARD_FLAG_FILES := proguard.cfg

                      proguard.cfgAndroid.mk同级目录下。

                      4.把源码重新全编译下

    4.4版本  可能还涉及\build\core\java.mk  具体改法在测试中

    4.4的话,还需要改一处才生效

    Build/core/java.mk 里的

    ifeq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)

    # By default no obfuscation

    # proguard_flags += -dontobfuscate ――注释掉这句

    endif  # No obfuscation


    展开全文
  • Android混淆总结篇(一)

    万次阅读 2018-03-28 18:46:21
    上个月跟朋友讨论了这么一问题:“项目上线之后由于代码被混淆的缘故,导致收集到的异常信息看着很困难”,刚好最近在复习混淆方面的知识,在总结混淆的知识点的同时,顺便探讨总结下这问题。项目上线肯定避免不了的...

    前言

    这阵子自己的心又长草了,静不下来~又挺迷茫的!在这个纷纷跳槽的季节,感觉还是应该让自己静下心来多学习学习。还是写写博客,总结总结~梳理下心里的野草。

    上个月跟朋友讨论了这么一问题:“项目上线之后由于代码被混淆的缘故,导致收集到的异常信息看着很困难”,刚好最近在复习混淆方面的知识,在总结混淆的知识点的同时,顺便探讨总结下这问题。项目上线肯定避免不了的是对项目进行混淆、打包、签名和发布,可能还有APK加固等等,其实这流程并不复杂,都有一套明确的流程,所以整起来也不是很困难。而上面提到的“混淆导致上线后的异常信息查看起来挺困难”这问题,这几天也大概探讨完,打算记录在下篇文章~~那么这篇文章先开始扯淡吧!


    Ⅰ.简述

    混淆的概念:将Android项目进行打包之时,可以将项目里的包名、类名、变量名进行更改,使得代码不容易泄露,类似于对其apk中的文件加密.

    混淆的作用

    • 1.增加Apk反编译之后代码泄露的困难性
    • 2.生成的apk体积会缩小

    什么是混淆?

    Android SDK 本身就提供混淆的功能,将混淆开关进行开启后,开发者需要做的是对Android Studio工程项目中的proguard-rules.pro文件进行混淆白名单的配置.

    那么什么是混淆白名单呢?其实就是指定一些包名、类名、变量等不可以被混淆。假设没指定白名单就进行混淆打包,而某某类的类名被混淆了(假设变成了a),那么可能其他引用或使用该类的类就找不到该类,说不定应用就会因此崩溃或是导致相应的功能无法使用.

    那么所谓的混淆也就是配置混淆白名单,那么下面看看混淆之后的apk的内部结构.可以看到红圈圈出来的部分都是进行混淆的,而有部分是没有进行混淆的,比如黑圈圈出来的属性动画兼容库nineoldandroids,其包名类名就没有变成abc这样的代替符

    这里写图片描述

    上面我是用apk逆向助手对apk进行反编译,市场上的反编译工具有很多种,可以自行Google搜索。

    补充

    本篇文章记录的混淆知识点主要基于Android Studio开发工具。


    Ⅱ.开始混淆

    1.开启混淆开关

    混淆的开关在项目/app/build.gradle文件里,看下面的截图,将minifyEnabled设置为true就是开启混淆,关于下面的配置代码可以直接写在build.gradle文件的android节点下

    这里写图片描述

    代码混淆一般是在上线前的apk打包才会去配置混淆开启,要是忘记配置的代码,那怎么办呢?直接进去Project Structrue,然后根据下面截图所标识的进行设置,如此这般,只要打release包就是开启混淆进行打包的.

    这里写图片描述

    2.设置混淆白名单

    基于Android Studio创建的项目里有一文件名称为”proguard-rules.pro”的文件,路径是”项目/app/proguard-rules.pro”,没经过编辑之前,里面只有一些注释的代码,如下图

    这里写图片描述

    那么设置的混淆白名单又该怎么写呢?Google搜索的话会有很多博客上的模板可以复制进行套用.如下图,那么就可以进行参考,下面第三部分将常用的混淆指令和对应的注释都列举出来,基本常用的都有,有疏漏的那就自行搜索下.

    这里写图片描述


    Ⅲ.实际混淆指令

    在应用中,大多数的混淆指令是已经确定的了,比如下面的基本指令部分,基本不用修改的。而其他的混淆指令,比如第三方的SDK/框架的混淆指令一般在其官方文档都可以找到,所以相对来说还是比较方便的,下面将这几天归类的混淆指令总结下.

    基本指令:

        # 设置混淆的压缩比率 0 ~ 7
        -optimizationpasses 5
        # 混淆后类名都为小写   Aa aA
        -dontusemixedcaseclassnames
        # 指定不去忽略非公共库的类
        -dontskipnonpubliclibraryclasses
        #不做预校验的操作
        -dontpreverify
        # 混淆时不记录日志
        -verbose
        # 混淆采用的算法.
        -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
        #保留代码行号,方便异常信息的追踪
        -keepattributes SourceFile,LineNumberTable
    
        #dump文件列出apk包内所有class的内部结构
        -dump class_files.txt        
        #seeds.txt文件列出未混淆的类和成员
        -printseeds seeds.txt
        #usage.txt文件列出从apk中删除的代码
        -printusage unused.txt
        #mapping文件列出混淆前后的映射
        -printmapping mapping.txt
    

    避免混淆Android基本组件,下面是兼容性比较高的规则:

    -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
    
    #不提示V4包下错误警告
    -dontwarn android.support.v4.**
    #保持下面的V4兼容包的类不被混淆
    -keep class android.support.v4.**{*;}

    避免混淆所有native的方法,涉及到C、C++

    -keepclasseswithmembernames class * {
            native <methods>;
    }

    避免混淆自定义控件类的get/set方法和构造函数

    -keep public class * extends android.view.View{
            *** get*();
            void set*(***);
            public <init>(android.content.Context);
            public <init>(android.content.Context,
                                        android.util.AttributeSet);
            public <init>(android.content.Context,
                                        android.util.AttributeSet,int);
    }

    避免混淆枚举类

        -keepclassmembers enum * {
            public static **[] values();
            public static ** valueOf(java.lang.String);
    }

    避免混淆序列化类

        #不混淆Parcelable和它的实现子类,还有Creator成员变量
        -keep class * implements android.os.Parcelable {
          public static final android.os.Parcelable$Creator *;
        }
    
        #不混淆Serializable和它的实现子类、其成员变量
        -keepclassmembers class * implements java.io.Serializable {
            static final long serialVersionUID;
            private static final java.io.ObjectStreamField[] serialPersistentFields;
            private void writeObject(java.io.ObjectOutputStream);
            private void readObject(java.io.ObjectInputStream);
            java.lang.Object writeReplace();
            java.lang.Object readResolve();
        }

    避免混淆JSON类的构造函数

        #使用GSON、fastjson等框架时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象
        -keepclassmembers class * {
            public <init>(org.json.JSONObject);
        }
    

    避免混淆第三方SDK

        # ==================环信混淆start=================
        -keep class com.hyphenate.** {*;}
        -dontwarn  com.hyphenate.**
        # ==================环信end======================
    
        # ==================bugly start==================
        -dontwarn com.tencent.bugly.**
        -keep public interface com.tencent.**
        -keep public class com.tencent.** {*;}
        -keep public class com.tencent.bugly.**{*;}
        # ==================bugly end====================
    
        # ===============百度定位 start====================
        -keep class vi.com.gdi.** { *; }
        -keep public class com.baidu.** {*;}
        -keep public class com.mobclick.** {*;}
        -dontwarn com.baidu.mapapi.utils.*
        -dontwarn com.baidu.platform.comapi.b.*
        -dontwarn com.baidu.platform.comapi.map.*
        # ===============百度定位 end======================
    
        //备注:其他的第三方包的混淆指令可以到其官方文档去拷贝

    避免混淆第三方框架

        # ==================picasso框架 start===============
        -keep class com.parse.*{ *; }
        -dontwarn com.parse.**
        -dontwarn com.squareup.picasso.**
        -keepclasseswithmembernames class * {
            native <methods>;
        }
        # ==================picasso end====================
    
        # ==================EventBus start=================
        -keep class org.greenrobot.** {*;}
        -keep class de.greenrobot.** {*;}
        -keepclassmembers class ** {
            public void onEvent*(**);
            void onEvent*(**);
        }
        # ==================EventBus end===================
    
        # ==================okhttp start===================
        -dontwarn com.squareup.okhttp.**
        -keep class com.squareup.okhttp.** { *;}
        -dontwarn okio.**
        -keep class okio.**{*;}
        -keep interface okio.**{*;}
        # ==================okhttp end=====================
    
        //备注:其它框架的混淆指令可以到其官方文档去拷贝   

    其它混淆指令

        #避免混淆属性动画兼容库
        -dontwarn com.nineoldandroids.*
        -keep class com.nineoldandroids.** { *;}    
    
        #不混淆泛型
        -keepattributes Signature
    
        #避免混淆注解类
        -dontwarn android.annotation
        -keepattributes *Annotation*
    
        #避免混淆内部类
        -keepattributes InnerClasses
    
        #避免混淆实体类,修改成你对应的包名
        -keep class com.wyk.test.bean.** { *; }
        -keep class com.wyk.test.event.** { *; }
        -keep public class com.wyk.test.utils.eventbus.** { *;}
    
        #避免混淆Rxjava/RxAndroid
        -dontwarn sun.misc.**
        -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
         long producerIndex;
         long consumerIndex;
        }
        -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
         rx.internal.util.atomic.LinkedQueueNode producerNode;
        }
        -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
         rx.internal.util.atomic.LinkedQueueNode consumerNode;
        }
    
    #避免混淆js相关的接口
    -keepattributes *JavascriptInterface*
    -keep class com.wyk.test.js.** { *; }
    

    Ⅳ.混淆配置注意点

    1.假设当配置 “-libraryjars libs/jpush-android-2.1.6.jar” 对jar包进行混淆白名单化,如果gradle报错的话,可以考虑注释掉(格式:-libraryjars [jar包名])这样的配置信息.采用下面的配置信息进行替换

     -dontwarn cn.jpush.**
     -keep class cn.jpush.** { *; }

    2.下面是对属性动画兼容库的混淆白名单配置信息,刚开始觉得只是保持com.nineoldandroids包下的类不被混淆,后来经过反编译混淆后的apk包,发现效果是”不混淆该class com.nineoldandroids包下的类、子包和子包的类,也不混淆其中类的成员变量.

    -keep class com.nineoldandroids.** { *;}       

    Ⅴ.其它

    1.混淆套用模板

    个人觉得下面链接的博文就写得非常好,所以可以进行参考.

    参考博文:5分钟搞定android混淆

    2.资源混淆

    Proguard混淆只是针对代码进行混淆,解压之后的apk包还是能看到项目的资源文件和其名称,比如布局、logo图片等等.这时可以选择对资源文件进行混淆,下面两个链接是腾讯推出的资源混淆工具相关的博文,可以参考.

    资源混淆工具相关的博文

    http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=42
    https://github.com/shwenzhang/AndResGuard/blob/master/README.zh-cn.md

    3.加固

    为了使得apk更加不容易被破解,混淆之后还可以对apk进行加固,现今市面上的加固技术有很多种,有360加固、爱加密加固、梆梆加固等等,可以自行选择,加固技术就相当于给apk包加多一个壳,相应的体积也会增大,大概增大1M~2M左右,需要的话可以自行搜索,加固还是挺简单的.

    4.参考链接

    http://blog.csdn.net/maxwell_nc/article/details/51998766
    http://blog.csdn.net/chen930724/article/details/49687067
    http://blog.csdn.net/lovexjyong/article/details/24652085
    http://www.jianshu.com/p/f3455ecaa56e

    5.睡觉 ing~~~

    展开全文
  • 可能资源被反编译影响还不是很大,而重新打包又由于有签名的保护导致很难被盗版,但代码被反编译就有可能会泄漏核心技术了,因此一款安全性高的程序最起码要做到的一件事就是:对代码进行混淆混淆代码并不是让...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/50451259
    在上一篇文章当中,我们学习了Android程序反编译方面的知识,包括反编译代码、反编译资源、以及重新打包等内容。通过这些内容我们也能看出来,其实我们的程序并没有那么的安全。可能资源被反编译影响还不是很大,重新打包又由于有签名的保护导致很难被盗版,但代码被反编译就有可能会泄漏核心技术了,因此一款安全性高的程序最起码要做到的一件事就是:对代码进行混淆。

    混淆代码并不是让代码无法被反编译,而是将代码中的类、方法、变量等信息进行重命名,把它们改成一些毫无意义的名字。因为对于我们而言可能Cellphone类的call()方法意味着很多信息,而A类的b()方法则没有任何意义,但是对于计算机而言,它们都是平等的,计算机不会试图去理解Cellphone是什么意思,它只会按照设定好的逻辑来去执行这些代码。所以说混淆代码可以在不影响程序正常运行的前提下让破解者很头疼,从而大大提升了程序的安全性。

    今天是我们Android安全攻防战系列的下篇,本篇文章的内容建立在上篇的基础之上,还没有阅读过的朋友可以先去参考 Android安全攻防战,反编译与混淆技术完全解析(上)


    混淆

    本篇文章中介绍的混淆技术都是基于Android Studio的,Eclipse的用法也基本类似,但是就不再为Eclipse专门做讲解了。

    我们要建立一个Android Studio项目,并在项目中添加一些能够帮助我们理解混淆知识的代码。这里我准备好了一些,我们将它们添加到Android Studio当中。
    首先新建一个MyFragment类,代码如下所示:

    public class MyFragment extends Fragment {
        
        private String toastTip = "toast in MyFragment";
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_layout, container, false);
            methodWithGlobalVariable();
            methodWithLocalVariable();
            return view;
        }
    
        public void methodWithGlobalVariable() {
            Toast.makeText(getActivity(), toastTip, Toast.LENGTH_SHORT).show();
        }
    
        public void methodWithLocalVariable() {
            String logMessage = "log in MyFragment";
            logMessage = logMessage.toLowerCase();
            System.out.println(logMessage);
        }
    
    }
    

    可以看到,MyFragment是继承自Fragment的,并且MyFragment中有一个全局变量。onCreateView()方法是Fragment的生命周期函数,这个不用多说,在onCreateView()方法中又调用了methodWithGlobalVariable()和methodWithLocalVariable()方法,这两个方法的内部分别引用了一个全局变量和一个局部变量。
    接下来新建一个Utils类,代码如下所示:

    public class Utils {
    
        public void methodNormal() {
            String logMessage = "this is normal method";
            logMessage = logMessage.toLowerCase();
            System.out.println(logMessage);
        }
    
        public void methodUnused() {
            String logMessage = "this is unused method";
            logMessage = logMessage.toLowerCase();
            System.out.println(logMessage);
        }
    
    }
    

    这是一个非常普通的工具类,没有任何继承关系。Utils中有两个方法methodNormal()和methodUnused(),它们的内部逻辑都是一样的,唯一的据别是稍后methodNormal()方法会被调用,而methodUnused()方法不会被调用。
    下面再新建一个NativeUtils类,代码如下所示:

    public class NativeUtils {
    
        public static native void methodNative();
    
        public static void methodNotNative() {
            String logMessage = "this is not native method";
            logMessage = logMessage.toLowerCase();
            System.out.println(logMessage);
        }
    
    }
    

    这个类中同样有两个方法,一个是native方法,一个是非native方法。

    最后,修改MainActivity中的代码,如下所示:

    public class MainActivity extends AppCompatActivity {
    
        private String toastTip = "toast in MainActivity";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            getSupportFragmentManager().beginTransaction().add(R.id.fragment, new MyFragment()).commit();
            Button button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    methodWithGlobalVariable();
                    methodWithLocalVariable();
                    Utils utils = new Utils();
                    utils.methodNormal();
                    NativeUtils.methodNative();
                    NativeUtils.methodNotNative();
                    Connector.getDatabase();
                }
            });
        }
    
        public void methodWithGlobalVariable() {
            Toast.makeText(MainActivity.this, toastTip, Toast.LENGTH_SHORT).show();
        }
    
        public void methodWithLocalVariable() {
            String logMessage = "log in MainActivity";
            logMessage = logMessage.toLowerCase();
            System.out.println(logMessage);
        }
    
    }
    

    可以看到,MainActivity和MyFragment类似,也是定义了methodWithGlobalVariable()和methodWithLocalVariable()这两个方法,然后MainActivity对MyFragment进行了添加,并在Button的点击事件里面调用了自身的、Utils的、以及NativeUtils中的方法。注意调用native方法需要有相应的so库实现,不然的话就会报UnsatisefiedLinkError,不过这里其实我也并没有真正的so库实现,只是演示一下让大家看看混淆结果。点击事件的最后一行调用的是LitePal中的方法,因为我们还要测试一下引用第三方Jar包的场景,到LitePal项目的主页去下载最新的Jar包,然后放到libs目录下即可。

    完整的build.gradle内容如下所示:

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.2"
    
        defaultConfig {
            applicationId "com.example.guolin.androidtest"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:appcompat-v7:23.2.0'
    }
    

    好的,到这里准备工作就已经基本完成了,接下来我们就开始对代码进行混淆吧。

    混淆APK

    在Android Studio当中混淆APK实在是太简单了,借助SDK中自带的Proguard工具,只需要修改build.gradle中的一行配置即可。可以看到,现在build.gradle中minifyEnabled的值是false,这里我们只需要把值改成true,打出来的APK包就会是混淆过的了。如下所示:

    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    

    其中minifyEnabled用于设置是否启用混淆,proguardFiles用于选定混淆配置文件。注意这里是在release闭包内进行配置的,因此只有打出正式版的APK才会进行混淆,Debug版的APK是不会混淆的。当然这也是非常合理的,因为Debug版的APK文件我们只会用来内部测试,不用担心被人破解。

    那么现在我们来打一个正式版的APK文件,在Android Studio导航栏中点击Build->Generate Signed APK,然后选择签名文件并输入密码,如果没有签名文件就创建一个,最终点击Finish完成打包,生成的APK文件会自动存放在app目录下。除此之外也可以在build.gradle文件当中添加签名文件配置,然后通过gradlew assembleRelease来打出一个正式版的APK文件,这种方式APK文件会自动存放在app/build/outputs/apk目录下。

    那么现在已经得到了APK文件,接下来就用上篇文章中学到的反编译知识来对这个文件进行反编译吧,结果如下图所示:

    很明显可以看出,我们的代码混淆功能已经生效了。

    下面我们尝试来阅读一下这个混淆过后的代码,最顶层的包名结构主要分为三部分,第一个a.a已经被混淆的面目全非了,但是可以猜测出这个包下是LitePal的所有代码。第二个android.support可以猜测出是我们引用的android support库的代码,第三个com.example.guolin.androidtest则很明显就是我们项目的主包名了,下面将里面所有的类一个个打开看一下。

    首先MainActivity中的代码如下所示:

    可以看到,MainActivity的类名是没有混淆的,onCreate()方法也没有被混淆,但是我们定义的方法、全局变量、局部变量都被混淆了。

    再来打开下一个类NativeUtils,如下所示:

    NativeUtils的类名没有被混淆,其中声明成native的方法也没有被混淆,但是非native方法的方法名和局部变量都被混淆了。
    接下来是a类的代码,如下所示:

    很明显,这个是MainActivity中按钮点击事件的匿名类,在onClick()方法中的调用代码虽然都被混淆了,但是调用顺序是不会改变的,对照源代码就可以看出哪一行是调用的什么方法了。

    再接下来是b类,代码如下所示:

    虽然被混淆的很严重,但是我们还是可以看出这个是MyFragment类。其中所有的方法名、全局变量、局部变量都被混淆了。

    最后再来看下c类,代码如下所示:

    c类中只有一个a方法,从字符串的内容我们可以看出,这个是Utils类中的methodNormal()方法。
    我为什么要创建这样的一个项目呢?因为从这几个类当中很能看出一些问题,接下来我们就分析一下上面的混淆结果。

    首先像Utils这样的普通类肯定是会被混淆的,不管是类名、方法名还是变量都不会放过。除了混淆之外Utils类还说明了一个问题,就是minifyEnabled会对资源进行压缩,因为Utils类中我们明明定义了两个方法,但是反编译之后就只剩一个方法了,因为另外一个方法没有被调用,所以认为是多余的代码,在打包的时候就给移除掉了。不仅仅是代码,没有被调用的资源同样也会被移除掉,因此minifyEnabled除了混淆代码之外,还可以起到压缩APK包的作用。

    接着看一下MyFragment,这个类也是混淆的比较彻底的,基本没有任何保留。那有些朋友可能会有疑问,Fragment怎么说也算是系统组件吧,就算普通方法名被混淆了,至少像onCreateView()这样的生命周期方法不应该被混淆吧?其实生命周期方法会不会被混淆和我们使用Fragment的方式有关,比如在本项目中,我使用的是android.support.v4.app.Fragment,support-v4包下的,就连Fragment的源码都被一起混淆了,因此生命周期方法当然也不例外了。但如果你使用的是android.app.Fragment,这就是调用手机系统中预编译好的代码了,很明显我们的混淆无法影响到系统内置的代码,因此这种情况下onCreateView()方法名就不会被混淆,但其它的方法以及变量仍然会被混淆。

    接下来看一下MainActivity,同样也是系统组件之一,但MainActivity的保留程度就比MyFragment好多了,至少像类名、生命周期方法名都没有被混淆,这是为什么呢?根据我亲身测试得出结论,凡是需要在AndroidManifest.xml中去注册的所有类的类名以及从父类重写的方法名都自动不会被混淆。因此,除了Activity之外,这份规则同样也适用于Service、BroadcastReceiver和ContentProvider。

    最后看一下NativeUtils类,这个类的类名也没有被混淆,这是由于它有一个声明成native的方法。只要一个类中有存在native方法,它的类名就不会被混淆,native方法的方法名也不会被混淆,因为C++代码要通过包名+类名+方法名来进行交互。 但是类中的别的代码还是会被混淆的。

    除此之外,第三方的Jar包都是会被混淆的,LitePal不管是包名还是类名还是方法名都被完完全全混淆掉了。
    这些就是Android Studio打正式APK时默认的混淆规则。

    那么这些混淆规则是在哪里定义的呢?其实就是刚才在build.gradle的release闭包下配置的proguard-android.txt文件,这个文件存放于<Android SDK>/tools/proguard目录下,我们打开来看一下:

    # This is a configuration file for ProGuard.
    # http://proguard.sourceforge.net/index.html#manual/usage.html
    
    -dontusemixedcaseclassnames
    -dontskipnonpubliclibraryclasses
    -verbose
    
    # Optimization is turned off by default. Dex does not like code run
    # through the ProGuard optimize and preverify steps (and performs some
    # of these optimizations on its own).
    -dontoptimize
    -dontpreverify
    # Note that if you want to enable optimization, you cannot just
    # include optimization flags in your own project configuration file;
    # instead you will need to point to the
    # "proguard-android-optimize.txt" file instead of this one from your
    # project.properties file.
    
    -keepattributes *Annotation*
    -keep public class com.google.vending.licensing.ILicensingService
    -keep public class com.android.vending.licensing.ILicensingService
    
    # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
    -keepclasseswithmembernames class * {
        native <methods>;
    }
    
    # keep setters in Views so that animations can still work.
    # see http://proguard.sourceforge.net/manual/examples.html#beans
    -keepclassmembers public class * extends android.view.View {
       void set*(***);
       *** get*();
    }
    
    # We want to keep methods in Activity that could be used in the XML attribute onClick
    -keepclassmembers class * extends android.app.Activity {
       public void *(android.view.View);
    }
    
    # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    -keepclassmembers class * implements android.os.Parcelable {
      public static final android.os.Parcelable$Creator CREATOR;
    }
    
    -keepclassmembers class **.R$* {
        public static <fields>;
    }
    
    # The support library contains references to newer platform versions.
    # Dont warn about those in case this app is linking against an older
    # platform version.  We know about them, and they are safe.
    -dontwarn android.support.**
    

    这个就是默认的混淆配置文件了,我们来一起逐行阅读一下。

    -dontusemixedcaseclassnames 表示混淆时不使用大小写混合类名。

    -dontskipnonpubliclibraryclasses 表示不跳过library中的非public的类。
    -verbose 表示打印混淆的详细信息。

    -dontoptimize 表示不进行优化,建议使用此选项,因为根据proguard-android-optimize.txt中的描述,优化可能会造成一些潜在风险,不能保证在所有版本的Dalvik上都正常运行。

    -dontpreverify 表示不进行预校验。这个预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度。

    -keepattributes *Annotation* 表示对注解中的参数进行保留。

    -keep public class com.google.vending.licensing.ILicensingService
    -keep public class com.android.vending.licensing.ILicensingService
    

    表示不混淆上述声明的两个类,这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。

    -keepclasseswithmembernames class * {
        native <methods>;
    }
    

    表示不混淆任何包含native方法的类的类名以及native方法名,这个和我们刚才验证的结果是一致的。

    -keepclassmembers public class * extends android.view.View {
       void set*(***);
       *** get*();
    }
    

    表示不混淆任何一个View中的setXxx()和getXxx()方法,因为属性动画需要有相应的setter和getter的方法实现,混淆了就无法工作了。

    -keepclassmembers class * extends android.app.Activity {
       public void *(android.view.View);
    }
    

    表示不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick="buttonClick"属性,当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了。

    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    

    表示不混淆枚举中的values()和valueOf()方法,枚举我用的非常少,这个就不评论了。

    -keepclassmembers class * implements android.os.Parcelable {
      public static final android.os.Parcelable$Creator CREATOR;
    }
    

    表示不混淆Parcelable实现类中的CREATOR字段,毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败。

    -keepclassmembers class **.R$* {
        public static <fields>;
    }
    

    表示不混淆R文件中的所有静态字段,我们都知道R文件是通过字段来记录每个资源的id的,字段名要是被混淆了,id也就找不着了。

    -dontwarn android.support.** 表示对android.support包下的代码不警告,因为support包中有很多代码都是在高版本中使用的,如果我们的项目指定的版本比较低在打包时就会给予警告。不过support包中所有的代码都在版本兼容性上做足了判断,因此不用担心代码会出问题,所以直接忽略警告就可以了。

    好了,这就是proguard-android.txt文件中所有默认的配置,而我们混淆代码也是按照这些配置的规则来进行混淆的。经过我上面的讲解之后,相信大家对这些配置的内容基本都能理解了。不过proguard语法中还真有几处非常难理解的地方,我自己也是研究了好久才搞明白,下面和大家分享一下这些难懂的语法部分。

    proguard中一共有三组六个keep关键字,很多人搞不清楚它们的区别,这里我们通过一个表格来直观地看下:

    关键字 描述
    keep 保留类和类中的成员,防止它们被混淆或移除。
    keepnames 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。
    keepclassmembers 只保留类中的成员,防止它们被混淆或移除。
    keepclassmembernames 只保留类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。
    keepclasseswithmembers 保留类和类中的成员,防止它们被混淆或移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。
    keepclasseswithmembernames 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。

    除此之外,proguard中的通配符也比较让人难懂,proguard-android.txt中就使用到了很多通配符,我们来看一下它们之间的区别:

    通配符 描述
    <field> 匹配类中的所有字段
    <method> 匹配类中的所有方法
    <init> 匹配类中的所有构造函数
    * 匹配任意长度字符,但不含包名分隔符(.)。比如说我们的完整类名是com.example.test.MyActivity,使用com.*,或者com.exmaple.*都是无法匹配的,因为*无法匹配包名中的分隔符,正确的匹配方式是com.exmaple.*.*,或者com.exmaple.test.*,这些都是可以的。但如果你不写任何其它内容,只有一个*,那就表示匹配所有的东西。
    ** 匹配任意长度字符,并且包含包名分隔符(.)。比如proguard-android.txt中使用的-dontwarn android.support.**就可以匹配android.support包下的所有内容,包括任意长度的子包。
    *** 匹配任意参数类型。比如void set*(*)就能匹配任意传入的参数类型,* get*()就能匹配任意返回值的类型。
    匹配任意长度的任意类型参数。比如void test(…)就能匹配任意void test(String a)或者是void test(int a, String b)这些方法。

    虽说上面表格已经解释的很详细了,但是很多人对于keep和keepclasseswithmembers这两个关键字的区别还是搞不懂。确实,它们之间用法有点太像了,我做了很多次试验它们的结果都是相同的。其实唯一的区别就在于类中声明的成员存不存在,我们还是通过一个例子来直接地看一下,先看keepclasseswithmember关键字:

    -keepclasseswithmember class * {
        native <methods>;
    }
    

    这段代码的意思其实很明显,就是保留所有含有native方法的类的类名和native方法名,而如果某个类中没有含有native方法,那就还是会被混淆。

    但是如果改成keep关键字,结果会完全不一样:

    -keep class * {
        native <methods>;
    }
    

    使用keep关键字后,你会发现代码中所有类的类名都不会被混淆了,因为keep关键字看到class *就认为应该将所有类名进行保留,而不会关心该类中是否含有native方法。当然这样写只会保证类名不会被混淆,类中的成员还是会被混淆的。

    比较难懂的用法大概就这些吧,掌握了这些内容之后我们就能继续前进了。

    回到Android Studio项目当中,刚才打出的APK虽然已经成功混淆了,但是混淆的规则都是按照proguard-android.txt中默认的规则来的,当然我们也可以修改proguard-android.txt中的规则,但是直接在proguard-android.txt中修改会对我们本机上所有项目的混淆规则都生效,那么有没有什么办法只针对当前项目的混淆规则做修改呢?当然是有办法的了,你会发现任何一个Android Studio项目在app模块目录下都有一个proguard-rules.pro文件,这个文件就是用于让我们编写只适用于当前项目的混淆规则的,那么接下来我们就利用刚才学到的所有知识来对混淆规则做修改吧。

    这里我们先列出来要实现的目标:

    • 对MyFragment类进行完全保留,不混淆其类名、方法名、以及变量名。
    • 对Utils类中的未调用方法进行保留,防止其被移除掉。
    • 对第三方库进行保留,不混淆android-support库,以及LitePal库中的代码。

    下面我们就来逐一实现这些目标。

    首先要对MyFragment类进行完全保留可以使用keep关键字,keep后声明完整的类名,然后保留类中的所有内容可以使用*通配符实现,如下所示:

    -keep class com.example.guolin.androidtest.MyFragment {
        *;
    }
    

    然后保留Utils类中的未调用方法可以使用keepclassmembers关键字,后跟Utils完整类名,然后在内部声明未调用的方法,如下所示:

    -keepclassmembers class com.example.guolin.androidtest.Utils {
        public void methodUnused();
    }
    

    最后不要混淆第三方库,目前我们使用了两种方式来引入第三方库,一种是通过本地jar包引入的,一种是通过remote引入的,其实这两种方式没什么区别,要保留代码都可以使用**这种通配符来实现,如下所示:

    -keep class org.litepal.** {
        *;
    }
    
    -keep class android.support.** {
        *;
    }
    

    所有内容都在这里了,现在我们重新打一个正式版的APK文件,然后再反编译看看效果:

    可以看到,现在android-support包中所有代码都被保留下来了,不管是包名、类名、还是方法名都没有被混淆。LitePal中的代码也是同样的情况:

    再来看下MyFragment中的代码,如下所示:

    可以看到,MyFragment中的代码也没有被混淆,按照我们的要求被完全保留下来了。
    最后再来看一下Utils类中的代码:

    很明显,Utils类并没有被完全保留下来,类名还是被混淆了,methodNormal()方法也被混淆了,但是methodUnused()没有被混淆,当然也没有被移除,因为我们的混淆配置生效了。

    经过这些例子的演示,相信大家已经对Proguard的用法有了相当不错的理解了,那么根据自己的业务需求来去编写混淆配置相信也不是什么难事了吧?

    Progaurd的使用非常灵活,基本上能够覆盖你所能想到的所有业务逻辑。这里再举个例子,之前一直有人问我使用LitePal时的混淆配置怎么写,其实真的很简单,LitePal作为开源库并不需要混淆,上面的配置已经演示了如何不混淆LitePal代码,然后所有代码中的Model是需要进行反射的,也不能混淆,那么只需要这样写就行了:

    -keep class * extends org.litepal.crud.DataSupport {
        *;
    }
    

    因为LitePal中所有的Model都是应该继承DataSupport类的,所以这里我们将所有继承自DataSupport的类都进行保留就可以了。

    关于混淆APK的用法就讲这么多,如果你还想继续了解关于Proguard的更多用法,可以参考官方文档:

    http://proguard.sourceforge.net/index.html#manual/usage.html

    混淆Jar

    在本篇文章的第二部分我想讲一讲混淆Jar包的内容,因为APK不一定是我们交付的唯一产品。就比如说我自己,我在公司是负责写SDK的,对于我来说交付出去的产品就是Jar包,而如果Jar包不混淆的话将会很容易就被别人反编译出来,从而泄漏程序逻辑。

    实际上Android对混淆Jar包的支持在很早之前就有了,不管你使用多老版本的SDK,都能在 <Android SDK>/tools目录下找到proguard这个文件夹。然后打开里面的bin目录,你会看到如下文件:

    其中proguardgui.bat文件是允许我们以图形化的方式来对Jar包进行混淆的一个工具,今天我们就来讲解一下这个工具的用法。

    在开始讲解这个工具之前,首先我们需要先准备一个Jar包,当然你从哪里搞到一个Jar包都是可以的,不过这里为了和刚才的混淆逻辑统一,我们就把本篇文章中的项目代码打成一个Jar包吧。

    Eclipse中导出Jar包的方法非常简单,相信所有人都会,可是Android Studio当中就比较让人头疼了,因为Android Studio并没有提供一个专门用于导出Jar包的工具,因此我们只能自己动手了。

    我们需要知道,任何一个Android Studio项目,只要编译成功之后就会在项目模块的build/intermediates/classes/debug目录下生成代码编译过后的class文件,因此只需通过打包命令将这些class文件打包成Jar包就行了,打开cmd,切换到项目的根目录,然后输入如下命令:

    jar -cvf androidtest.jar -C app/build/intermediates/classes/debug .
    

    在项目的根目录下就会生成androidtest.jar这个文件,这样我们就把Jar包准备好了。
    现在双击proguardgui.bat打开混淆工具,如果是Mac或Ubuntu系统则使用sh proguardgui.sh命令打开混淆工具,界面如下图所示:

    其实从主界面上我们就能看出,这个Proguard工具支持Shrinking、Optimization、Obfuscation、Preverification四项操作,在左侧的侧边栏上也能看到相应的这些选项。Proguard的工作机制仍然还是要依赖于配置文件,当然我们也可以通过proguardgui工具来生成配置文件,不过由于配置选项太多了,每个都去一一设置太复杂,而且大多数还都是我们用不到的配置。因此最简单的方式就是直接拿现有的配置文件,然后再做些修改就行了。

    那么我们从<Android SDK>/tools/proguard目录下将proguard-android.txt文件复制一份出来,然后点击主界面上的Load configuration按钮来加载复制出来的这份proguard-android.txt文件,完成后点击Next将进入Input/Output界面。

    Input/Output界面是用于导入要混淆的Jar包、配置混淆后文件的输出路径、以及导入该Jar包所依赖的所有其它Jar包的。我们要混淆的当然就是androidtest.jar这个文件,那么这个Jar包又依赖了哪些Jar包呢?这里就需要整理一下了。

    • 首先我们写的都是Java代码,Java代码的运行要基于Jre基础之上,没有Jre计算机将无法识别Java的语法,因此第一个要依赖的就是Jre的rt.jar。
    • 然后由于我们导出的Jar包中有Android相关的代码,比如Activity、Fragment等,因此还需要添加Android的编译库,android.jar。
    • 除此之外,我们使用的AppCompatActivity和Fragment分别来自于appcompat-v7包和support-v4包,那么这两个Jar包也是需要引入的。
    • 最后就是代码中还引入了litepal-1.3.1.jar。

    整理清楚了之后我们就来一个个添加,Input/Output有上下两个操作界面,上面是用于导入要混淆的Jar包和配置混淆后文件的输出路径的,下面则是导入该Jar包所依赖的所有其它Jar包的,全部导入后结果如下图所示:

    这些依赖的Jar包所存在的路径每台电脑都不一样,你所需要做的就是在你自己的电脑上成功找到这些依赖的Jar包并导入即可。

    不过细心的朋友可能会发现,我在上面整理出了五个依赖的Jar包,但是在图中却添加了六个。这是我在写这篇文章时碰到的一个新的坑,也是定位了好久才解决的,我觉得有必要重点提一下。由于我平时混淆Jar包时里面很少会有Activity,所以没遇到过这个问题,但是本篇文章中的演示Jar包中不仅包含了Activty,还是继承自AppCompatActivity的。而AppCompatActivity的继承结构并不简单,如下图所示:

    其中AppCompatActivity是在appcompat-v7包中的,它的父类FragmentActivity是在support-v4包中的,这两个包我们都已经添加依赖了。但是FragmentActivity的父类就坑爹了,如果你去看BaseFragmentActivityHoneycomb和BaseFragmentActivityDonut这两个类的源码,你会发现它们都是在support-v4包中的:


    可是如果你去support-v4的Jar包中找一下,你会发现压根就没有这两个类,所以我当时一直混淆报错就是因为这两个类不存在,继承结构在这里断掉了。而这两个类其实被规整到了另外一个internal的Jar包中,所以当你要混淆的Jar包中有Activity,并且还是继承自AppCompatActivity或FragmentActivity的话,那么就一定要记得导入这个internal Jar包的依赖,如下图所示:

    接下来点击Next进入Shrink界面,这个界面没什么需要配置的东西,但记得要将Shrink选项钩掉,因为我们这个Jar包是独立存在的,没有任何项目引用,如果钩中Shrink选项的话就会认为我们所有的代码都是无用的,从而把所有代码全压缩掉,导出一个空的Jar包。

    继续点击Next进入Obfuscation界面,在这里可以添加一些混淆的逻辑,和混淆APK时不同的是,这里并不会自动帮我们排除混淆四大组件,因此必须要手动声明一下才行。点击最下方的Add按钮,然后在弹出的界面上编写排除逻辑,如下图所示:

    很简单,就是在继承那一栏写上android.app.Activity就行了,其它的组件原理也相同。
    继续点击Next进入Optimiazation界面,不用修改任何东西,因为我们本身就不启用Optimization功能。继续点击Next进入Information界面,也不用修改任何东西,因为我们也不启用Preverification功能。

    接着点击Next,进入Process界面,在这里可以通过点击View configuration按钮来预览一下目前我们的混淆配置文件,内容如下所示:

    -injars /Users/guolin/AndroidStudioProjects/AndroidTest/androidtest.jar
    -outjars /Users/guolin/androidtest_obfuscated.jar
    
    -libraryjars /Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/rt.jar
    -libraryjars /Users/guolin/Library/Android/sdk/platforms/android-23/android.jar
    -libraryjars /Users/guolin/AndroidStudioProjects/AndroidTest/app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.2.0/jars/classes.jar
    -libraryjars /Users/guolin/AndroidStudioProjects/AndroidTest/app/build/intermediates/exploded-aar/com.android.support/support-v4/23.2.0/jars/classes.jar
    -libraryjars /Users/guolin/AndroidStudioProjects/AndroidTest/app/build/intermediates/exploded-aar/com.android.support/support-v4/23.2.0/jars/libs/internal_impl-23.2.0.jar
    -libraryjars /Users/guolin/AndroidStudioProjects/AndroidTest/app/libs/litepal-1.3.1.jar
    
    -dontshrink
    -dontoptimize
    -dontusemixedcaseclassnames
    -keepattributes *Annotation*
    -dontpreverify
    -verbose
    -dontwarn android.support.**
    
    
    -keep public class com.google.vending.licensing.ILicensingService
    
    -keep public class com.android.vending.licensing.ILicensingService
    
    # keep setters in Views so that animations can still work.
    # see http://proguard.sourceforge.net/manual/examples.html#beans
    -keepclassmembers public class * extends android.view.View {
        void set*(***);
        *** get*();
    }
    
    # We want to keep methods in Activity that could be used in the XML attribute onClick
    -keepclassmembers class * extends android.app.Activity {
        public void *(android.view.View);
    }
    
    -keepclassmembers class * extends android.os.Parcelable {
        public static final android.os.Parcelable$Creator CREATOR;
    }
    
    -keepclassmembers class **.R$* {
        public static <fields>;
    }
    
    -keep class * extends android.app.Activity
    
    -keep class * extends android.app.Service
    
    -keep class * extends android.content.BroadcastReceiver
    
    -keep class * extends android.content.ContentProvider
    
    # Also keep - Enumerations. Keep the special static methods that are required in
    # enumeration classes.
    -keepclassmembers enum  * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    # Keep names - Native method names. Keep all native class/method names.
    -keepclasseswithmembers,allowshrinking class * {
        native <methods>;
    }
    

    恩,由此可见其实GUI工具只是给我们提供了一个方便操作的平台,背后工作的原理还是通过这些配置来实现的,相信上面的配置内容大家应该都能看得懂了吧。

    接下来我们还可以点击Save configuration按钮来保存一下当前的配置文件,这样下次混淆的时候就可以直接Load进来而不用修改任何东西了。

    最后点击Process!按钮来开始混淆处理,中间会提示一大堆的Note信息,我们不用理会,只要看到最终显示Processing completed successfully,就说明混淆Jar包已经成功了,如下图所示:

    混淆后的文件我将它配置在了/Users/guolin/androidtest_obfuscated.jar这里,如果反编译一下这个文件,你会发现和刚才反编译APK得到的结果是差不多的:MainActivity的类名以及从父类继承的方法名不会被混淆,NativeUtils的类名和其中的native方法名不会被混淆,Utils的methodUnsed方法不会被移除,因为我们禁用了Shrink功能,其余的代码都会被混淆。由于结果实在是太相似了,我就不再贴图了,参考本篇文章第一部分的截图即可。


    好了,本篇文章的内容就到这里,混淆技术掌握这么多相信已经足够大家在平时的工作当中使用了。当然除了使用混淆之外,还有一些加固软件也能提升程序的安全性,不过这些软件都是第三方的,并非Google原生支持,所以我就不进行讲解和推荐了。那么我们Android安全攻防战系列的文章到此结束,感谢大家有耐心看到最后。

    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

    20160507110203928         20161011100137978

    展开全文
  • 今天给大家介绍一个开源.net混淆器——ConfuserEx http://yck1509.github.io/ConfuserEx/ 由于项目中要用到.net 混淆器,网上搜寻了很多款,比如Dotfuscator、xeoncode、foxit等等。 但大部分收费,当然也...
  • 代码混淆

    2019-08-17 16:21:04
    混淆 https://gitee.com/minhengqiang/proguard-spring-boot-example/blob/master/pom.xml 链接项目pom.xml有proguard混淆的基本配置,其中混淆程度需要根据项目具体摸索 自动化 将混淆后的代码打包 1、只保留混淆的...
  • ProGuard 最全混淆规则说明

    千次阅读 2018-08-01 10:19:59
    文章对Android混淆规则做一个解释说明。作者才疏学浅,如有错误,请谅解!&lt;@_@&gt; Android混淆入门可参考《Android 代码混淆零基础入门》 5326.png Input/Output Options 输入输出选项 ...
  • 混淆代码总结

    千次阅读 2017-07-14 16:44:18
    混淆代码网址很棒的网址: 1.Android项目实战(二十五):Android studio 混淆+打包+验证是否成功 2.Android Studio(十一):代码混淆及打包apk 3.Android代码混淆混淆规则 4.Error:warning: Ignoring Inner...
  • 关于混淆,你需要知道的全部

    万次阅读 2018-07-05 10:09:30
    混淆(obfuscate)使用简短的、无意义的名称重全名类名、方法名、字段等;预校验(preverify)为class添加预校验信息。一、4个步骤中的常量配置1. 压缩(shrink)-dontshrink声明不进行压缩操作,默认情况下,除了-...
  • 混淆的文章其实网上也很多,介绍的都很好,但是关于多个module的混淆规则就不是这么详细,有的也是错误的,经过了2天的多次实践以及查阅资料(多次打包和反编译看源码,很费时间啊),终于达到了我的目的。...
  • Android Studio 代码混淆(包教包会)

    万次阅读 多人点赞 2019-10-28 16:49:47
    前言 ...其实还有一个重要的功能,就是能apk瘦身,混淆后的apk要比不混淆的小很多,这个大家可以自己验证。 一般以下情况都不需要混淆: 1.使用了自定义控件那么要保证它们不参与混淆 2.使...
  • 混淆

    2018-07-03 09:58:05
    -optimizationpasses 5 #指定代码的压缩级别#包明不混合大小写-dontusemixedcaseclassnames#不去忽略非公共的库类-dontskipnonpubliclibraryclasses #优化 不...混淆时所采用的算法-optimizations !code/simplific...
  • 混淆矩阵是ROC曲线绘制的基础,同时它也是衡量分类型模型准确度中最基本,最直观,计算最简单的方法。 一句话解释版本: 混淆矩阵就是分别统计分类模型归错类,归对类的观测值个数,然后把结果放在一个表里展示...
  • 混淆矩阵(Confusion Matrix)分析

    万次阅读 多人点赞 2015-04-07 22:46:35
    在机器学习领域,混淆矩阵(confusion matrix),又称为可能性表格或是错误矩阵。它是一种特定的矩阵用来呈现算法性能的可视化效果,通常是监督学习(非监督学习,通常用匹配矩阵:matching matrix)。其每一列代表...
  • Android Studio 代码混淆(你真的会混淆吗)

    万次阅读 多人点赞 2017-04-18 23:14:06
    一、前言今天要打包新产品,突然忘了混淆的参数是怎么写的了,虽然之前也混淆过,可是具体配置的参数代码有些记不起来了,因此决定花点时间写篇博客记录一下,方便以后查找和自己的记忆。二、Android Studio 代码...
  • iOS安全攻防(二十三):Objective-C代码混淆

    万次阅读 多人点赞 2014-06-07 17:00:52
    iOS安全攻防(二十三):Objective-C代码混淆class-dump可以很方便的导出程序头文件,不仅让攻击者了解了程序结构方便逆向,还让着急赶进度时写出的欠完善的程序给同行留下笑柄。所以,我们迫切的希望混淆自己的代码...
  • 在实际的开发成产品apk的发布过程中,我们经常会使用到代码混淆技术。不过在讲解如何进行代码混淆之前,我先跟大家演示一下反编译的过程,这样才能让大家明白为什么需要进行代码混淆。    一、代码反编译  ...
  • Android 混淆代码总结

    万次阅读 多人点赞 2015-05-25 09:21:50
    Android 混淆代码总结
  • 2.优化类名混淆重名问题; 3.优化代码和项目结构; 更新说明 https://gitee.com/zfj1128/ZFJObsLib_dmg ----------------------------------------分割线-------------------------------------...
  • Jocky混淆编译器是在Sun JDK中提供的Java编译器(javac)的基础上完成的,修改了其中的代码生成过程,对编译器生成的中间代码进行混淆,最后再生成class文件,这样编译和混淆只需要一个步骤就可以完成。另外可以在源...
1 2 3 4 5 ... 20
收藏数 303,452
精华内容 121,380
关键字:

混淆