维基百科对ProGuard的介绍是:ProGuard是一个压缩(shrink),优化(optimize)与混淆(Obfuscate)Java代码的开源命令行工具。也就是说混淆只是ProGuard的其中一个功能,本文也只介绍它的混淆功能。

About ProGuard

ProGuard能通过重命名类名,字段名,方法名为一些没有意义的名字来混淆Java和Android程序,从而使逆向工程更难。并且ProGuard已经是Android SDK的一部分了,当然本文只讲如何混淆Java代码。

用法

本文介绍两种方式:使用UI工具 和 Maven集成。

  • UI工具

这个比较简单,先从https://sourceforge.net/projects/proguard/下载最新版的ProGuard,然后解压,到bin目录下找到proguardgui.bat双击即可,程序运行后的界面如下:

ProGuard

Input/Output中,Add input选择要混淆的JAR包(ProGuard不支持混淆单个class文件,但是我们可以通过命令把一个或多个class打成jar包:jar cvf Test.jar com/afei/test/*.class),Add output指定输出文件名。Obfuscation中有很多混淆自定义规则,根据需求自行调整,ShrinkingOptimization视情况而定是否需要勾选(如果只是混淆代码,则建议关闭)。最后选择Process,点击右下角的Process!即可。如下图所示,User.java混淆前后对比,我们发现类名,属性名都被重命名为一些毫无意义的命名了:

image.png
  • Maven集成

通过maven集成方式从而在maven打包阶段就达到了混淆的目。集成方式非常简单,只需修改POM,添加如下一些代码即可:

-- 添加依赖<dependency>    <groupId>net.sf.proguardgroupId>    <artifactId>proguard-baseartifactId>    <version>5.3.3version>dependency>

-- 添加插件<plugin>    <groupId>com.github.wvengengroupId>    <artifactId>proguard-maven-pluginartifactId>    <version>2.0.15-SNAPSHOTversion>    <executions>        <execution>            <phase>packagephase>            <goals><goal>proguardgoal>goals>        execution>    executions>    <configuration>        <proguardVersion>5.3.3proguardVersion>        <injar>${project.build.finalName}.jarinjar>        <outjar>${project.build.finalName}.jaroutjar>        <obfuscate>trueobfuscate>        <libs>            <lib>${java.home}/lib/rt.jarlib>            <lib>${java.home}/lib/jce.jarlib>        libs>        <options>

            <option>-dontshrinkoption>

            <option>-dontoptimizeoption>            <option>-keepnames interface **option>                      <option>-keepparameternamesoption>            <option>-keeppackagenamesoption>                            options>    configuration>plugin>

集成后执行maven package打包,就会看到target目录下会多出一些命名中带有proguard的文件,例如afei-demo-1.0.0-SNAPSHOT_proguard_base.jarproguard_map.txtproguard_seed.txt等,并且每个目录下的类名都被重命名为a, b, c等毫无意义的类名:

confusion target

  • 配置说明

maven集成ProGuard后,可自定义的地方主要集中在options标签中,一些option说明如下:

-dontshrinkshrink是ProGuard几大核心功能之一,配置了dontshrink表示不需要压缩,即关闭shrink功能

-dontoptimizeoptimize也是ProGuard几大核心功能之一,配置了dontoptimize表示不需要优化,即关闭soptimize功能

-keeppackagenames是否不混淆包名,如果配置了该项,那么包名会完整保留。如果没有配置,那么除了根目录(com.afei.test),子目录(例如bean, controller, impl等)都会被混淆。

-keepattributes SourceFile,LineNumberTable抛出异常时保留代码行号,在异常分析中可以方便定位

-dontusemixedcaseclassnames这个是给Windows系统用户的,因为ProGuard假定使用的操作系统是能区分大小写名,但是Windows不是这样的操作系统,所以必须为ProGuard指定-dontusemixedcaseclassnames选项

-keep class com.afei.test.ApplicationApplication这个类名不混淆,但是方法名,属性名,以及方法中的内容还是会混淆;

-keep class com.afei.test.Application { *; }Application这个类的类名,方法名,属性名完全保留不做任何混淆,但是方法体内的内容还是会混淆。

-keepnames interface **所有接口类命名不做任何混淆,但是接口里的属性和方法会还是会被混淆;

-keepnames enum **枚举类名不做任何混淆,但是枚举的值会混淆;

-keep public class * implements java.io.Serializable{    public *;    protected *;    private *;}保留实现了Serializable接口类中的公有的,友好的,私有的成员(属性和方法),这个配置主要是对应实体类的配置。

-keep class com.afei.test.dao.** { *; }dao层的类名和方法都不混淆;

-keepnames用法如下,保留Application的类名和main方法不混淆:-keepnames public class com.afei.test.Application {public static void main(java.lang.String[]);    }

用法如下,保留FtpConfigSaveJob的类名和execute方法不混淆:-keepclasseswithmembers public class com.afei.test.job.FtpConfigSaveJob {        com.xxl.job.core.biz.model.ReturnT execute(java.lang.String);    }

配置中符号的含义:

!:感叹号表示除这个以外,例如-keep class !com.afei.test.Application表示出了Application.java,其他的类名都不混淆

遇到的问题

通过使用ProGuard混淆springboot项目的过程,笔者遇到了下面这些问题:

  1. 工程目录要清晰,比如VO, DTO, PO存放目录要统一,自定义Exception子类存放目录等。因为这些类名,甚至属性名都不能混淆,VO属性名与接口定义有关,PO与Mapper.xml有关;

  2. 与序列化反序列相关的对象也不会混淆,与第三方约定的接口相关的模型也不能混淆等;

  3. xxl-job相关类不能混淆,方法申明必须是execute(String),笔者相信还会有其他的框架也会有类似的约定和限制;

  4. springboot的Application.java也不能混淆,因为main方法不能被重命名,Application.java类名最好也不要被重命名,因为maven中有配;置com.afei.test.Application

  5. 很多注解不能混淆

  6. … …

如下图所示,是默认配置混淆后的Application.java,很明显,这样的springboot工程是无法启动的,因为main主方法被混淆为a了:

混淆后的Application.java

另外,由于ProGuard默认会将每个子目录下的类都重命名为a, b, c。例如com.afei.test.a下的类会被重命名为a.class,b.class,c.class,而com.afei.test.b下的类也会被重命名为a.class,b.class,c.class。这样就会导致spring初始化加载bean时抛出下面的异常:

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'b' for bean class [com.afei.test.config.b] conflicts with existing, non-compatible bean definition of same name and class [com.afei.test.common.b]        at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:345)        at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:283)        at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:135)        at 

ProGuard总结

通过上面的分析可知,ProGuard或者类似原理的代码混淆工具的限制太多太多,对工程目录有严格的要求,而且很多地方需要明确配置不允许混淆,以后有新增的代码,还需要评估是否需要申明不需要混淆。这样分析下来后发现,如果想要使用ProGuard混淆服务端的代码,最后几乎只能混淆方法体内的内容。

XJar

针对ProGuard或者同原理方案的缺陷,笔者找到了另一种方案:XJar。

官方介绍XJar是Spring Boot JAR 安全加密运行工具,同时支持的原生JAR。基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译。功能特性如下:

  • 无需侵入代码,只需要把编译好的JAR包通过工具加密即可。

  • 完全内存解密,杜绝源码以及字节码泄露或反编译。

  • 支持所有JDK内置加解密算法。

  • 可选择需要加解密的字节码或其他资源文件,避免计算资源浪费。

详细的介绍和用法请参考XJar GitHub主页: https://github.com/core-lib/xjar,介绍的非常详细。

android 打包 混淆配置_玩转代码混淆工具:ProGuard相关推荐

  1. android 移除泛型中元素_Android 代码混淆 混淆方案

    欢迎关注专栏:里面定期分享Android和Flutter架构技术知识点及解析,还会不断更新的BATJ面试专题,欢迎大家前来探讨交流,如有好的文章也欢迎投稿. Flutter跨平台开发终极之选​zhua ...

  2. android 打包 混淆配置_android 实际项目中混淆文件的配置(参考做法)

    之前对项目混淆一直了解不是很透,趁着打包正式项目的时候有特意的去了解了一番,做些记录,备忘! -optimizationpasses 5 -dontusemixedcaseclassnames -do ...

  3. Android笔记:防反编译、代码混淆中,解决第三方jar包不被混淆的一些心得,及gson防混淆方法...

    为了防止代码被反编译,一般在签名导出前需要对代码进行混淆.最近发现自己的一个项目工程在代码混淆后,使用中出现了异常.以下是自己这几天在解决代码混淆以及引入第三方jar包导致混淆出现的问题处理的一些心得 ...

  4. Android开发笔记(七十三)代码混淆与反破解

    代码混淆 ProGuard是ADT自带的apk混淆器,它的用途有: 1.压缩apk包的大小,能删除无用的代码,并简化部分类名和方法名. 2.加大破解源码的难度,因为部分类名和方法名被重命名,使得程序逻 ...

  5. OOM分析(1) Android 源,如何分析android的OOM,与java静态代码分析工具

    用MAT分析OOM 很多OOM看似发生在bitmap 分配得时候,但它一般不是rootcause.根本原因都在于本应该自动释放的资源,因为代码的错误,而导致某些对象一直被引用(Reference),例 ...

  6. 如何分析android的OOM,与java静态代码分析工具

    2019独角兽企业重金招聘Python工程师标准>>> 用MAT分析OOM 很多OOM看似发生在bitmap 分配得时候,但它一般不是rootcause.根本原因都在于本应该自动释放 ...

  7. JetBrains PyCharm 配置pylint(Python代码审阅工具)教程

    代码规范的重要性 一.规范的代码可以促进团队开发 二.规范的代码可以减少人力资源投入 三.规范的代码可以降低维护成本 四.规范的代码有助于代码审阅(说白了别人看着舒服,也能看懂) Pylint 是什么 ...

  8. 统计gitlab代码行脚本_详解代码统计工具cloc--计算文件数、空白行数、注释行和代码行...

    概述 Cloc是一款使用Perl语言开发的开源代码统计工具,支持多平台使用.多语言识别,能够计算指定目标文件或文件夹中的文件数(files).空白行数(blank).注释行数(comment)和代码行 ...

  9. android标题栏添加按钮_几行代码实现Android通用标题栏(轻松向左右两侧添加Menu)...

    秦子帅明确目标,每天进步一点点..... 作者 |  丶E 地址 |  https://www.jianshu.com/p/8c15fc4114a7 前言 标题栏是app开发经常用到的东西,几乎每个页 ...

最新文章

  1. ec20 复位命令_《EC20 — AT指令》
  2. 如何在鼠标hover时改变标注的样式
  3. 常见汉字Unicode编码
  4. IPSec的NAT穿越
  5. ITK:从测量列表创建直方图
  6. 数据权限设计(原创)
  7. pppoe路由桥混合模式启用_无线路由器怎么设置
  8. MVC学习笔记:MVC实现用户登录验证ActionFilterAttribute用法并实现统一授权
  9. Hibernate 查询缓存
  10. 红包封面发货平台卡密系统 全新红包封面平台可搭建分站独立后台的源码
  11. java300集高淇老师学习笔记
  12. java代码从初始化到具象执行
  13. gtx1060+linux+双显卡,Manjaro Linux 安装1060显卡驱动
  14. sql中替换字段的部分字符
  15. 语句的认识,选择语句和循环语句(2022.11.13)
  16. 服务器老被攻击,该如何解决?
  17. 树莓派下DS18B20获取实时温度
  18. 安装vue-cli遇到npm ERR! code ECONNREFUSED问题
  19. 用面包板搭建4bit加法器
  20. 小森林顺序_小森林——值得在深夜一看的电影

热门文章

  1. 常见的6种MySQL约束
  2. 5G多输入多输出技术,到底是个啥东东?
  3. 中俄国际社区大佬共话Java,苦Lambda表达式久矣?
  4. Flask框架flash消息闪现学习与优化符合闪现之名
  5. 百度鹰眼html打开,BMap:WEB 服务API
  6. Spark之SparkStreaming的DStream操作
  7. Android笔记 隐式意图vs显示意图+隐式意图打开短信应用demo
  8. BroadcastReceiver之动态广播 demo+笔记
  9. 实用的powershell小技巧,持续更新……
  10. Linux查找历史命令