混淆
Java的bytecode很容易通过JAD等反编译工具还原出源代码。这样势必不满足安全的定义。如何一定程度上保护需要防止被反编译的源代码呢?混淆(obfuscate)技术。注意:用obfuscate防盗版是根本不可能,连汇编这种东西都能被破解掉,而java代码基本上等同于开源的同义词。用obfuscate只是为了增加反编译的难度,保护源代码的知识产权。混淆包照常运行,没有任何问题。可以使用反编译工具如jd-gui查看混淆后的包,验证混淆效果。 下面对Java中的几个混淆器obfuscator进行简介。
混淆技术
名称混淆
即 name Obfuscation,将有意义的类,字段、方法名称更改为无意义的字符串。生成的新名称越短,字节代码越小。在名称混淆的字节代码中,包,类,字段和方法名称已重命名,并且永远不能恢复原始名称。不幸的是,控制流程仍然清晰可见。故而需要Flow Obfuscation,流混淆。
流混淆
Flow Obfuscation,用于if, switch, while,for等关键字,对字节码进行细微的修改,模糊控制流,而不改变代码在运行时的行为。通常情况下,选择和循环等逻辑构造会被更改,因此它们不再具有直接等效的Java源代码。流模糊的字节码通常强制反编译器将一系列标签和非法的goto语句插入到它们生成的源代码中。源代码有时会因为反编译错误而变得更加模糊。
异常混淆
Exception Obfuscation,与流混淆类似,作用于异常。
字符串加密混淆
String Encryption
引用混淆
Reference Obfuscation
yguard
对yguard不会详细论述太多,仅仅只是为了说明混淆的一些概念、术语和技术手段等,因为推荐选择proguard。yguard官网yguard_ant_howto
介绍
一个java类文件模糊器,官网下载得到一个jar文件,没有找到maven dependency GAV;使用之前需要确保系统配置好ant,通过antrun的方式,即build.xml文件来配置Task。这一点实在是落后。 把生成的class文件打包成jar文件,然后对jar文件进行模糊化;还能够通过分析源码,移除未使用的类、方法、属性等;较小jar文件。可以完成以下模糊化工作:模糊化方法以及类中的变量名、方法名、类名、包路径,去除class文件中的调试信息等等。对模糊化类的成员变量名、方法名、类名,可以分别设置保护级别。设置的修饰符和java的修饰(访问控制)符一致,包括:public、protected、private、none。以保护方法名为例
- public: 表示除public的方法名不需要混淆外,模糊化其他所有的方法名(protected和private)
- protected: 表示除public和protected的方法名不进行混淆,其余方法名都要进行模糊化(private)
- private: 表示对方法名不进行混淆
- none: 表示对所有方法名均进行模糊化
<expose>
<class classes="public" methods="public" ields="public"/>
</expose>
混淆后的效果:
生成的jar包里面的MANIFEST.MF文件:
安全考虑,混淆技术;
MANIFEST.MF文件:
Class-Path: . bcprov-jdk14-150.jar
Ant-Version: Apache Ant 1.8.2
Created-By: yGuard Bytecode Obfuscator 2.5.2
Main-Class: SoftEncExchange
Name: A/A/A/A/A.class
SHA-1-Digest: rTJ++qML61cQW+9pghvdpI4LyjA=
Digest-Algorithms: SHA-1, MD5
MD5-Digest: 40phkXrhaJlsqjAhNzztTg==
其他更多配置,参考yguard_ant_howto
ProGuard
ProGuard官网 ProGuard,一款shrinker(压缩:检测和删除没有使用的类,字段,方法和属性), optimizer(优化:对字节码进行优化,并且移除无用指令), obfuscator(混淆:使用a,b,c等无意义的名称,对类,字段和方法进行重命名), and preverifier(审核:在Java平台上对处理后的代码进行预检)工具。
简单使用 从这里下载得到最新版6.0.3,首先看readme,解压缩之后得到的诸多目录,只需关注bin,docs,lib,examples,其他目录是源码和脚本文件。
Allatori
Allatori官网,第二代Java混淆器。所谓第二代混淆器,不仅仅能进行字段混淆,还能实现流混淆。
Allatori does not just obfuscate, it also minimizes application size, and boosts the speed, has full watermark functionality.
Allatori有以下几种混淆方式:命名混淆,流混淆,调试信息混淆,字符串混淆,及水印技术。可免费用于教育和非商业项目。支持war和jar格式,支持对需要混淆代码的应用程序添加有效日期。
入门
没有找到allatori的maven GAV,需要去官网下载 allatori.jar,放置在项目的根目录下,或安装到本地Maven仓库,或上传到内网的Nexus私服仓库。
pom.xml配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-and-filter-allatori-config</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target</outputDirectory>
<resources>
<resource>
<directory>${basedir}/allatori</directory>
<includes>
<include>allatori.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>run-allatori</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Xms128m</argument>
<argument>-Xmx512m</argument>
<argument>-jar</argument>
<argument>${basedir}/lib/allatori.jar</argument>
<argument>${basedir}/target/allatori.xml</argument>
</arguments>
</configuration>
</plugin>
allatori.xml配置文件:
<config>
<input>
<jar in="demo-0.0.1-SNAPSHOT.jar" out="demo-0.0.1-SNAPSHOT-obfuscated.jar"/>
</input>
<keep-names>
<class access="protected+">
<field access="protected+"/>
<method access="protected+"/>
</class>
</keep-names>
<property name="log-file" value="log.xml"/>
</config>
选择
从两个或者多个功能类似的开源(或闭源)框架(或工具)中选择一个,在Java世界是一件再寻常不过的事情。适合自己的才是最好的。所以一定得搞清楚自己的需要是什么,目标是什么,为了这个目标可以放弃什么代价(牺牲什么成本)等。 但总归是有一些比较通用的选择的参考标准。
- 是否开源,以及活跃度,Google的搜索指数如何
- 速度
- 效率
- 是否支持包名obfuscate
- 是否支持增量obfuscate
- 对资源、配置文件的混淆,如jdbc.properties