混淆

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>

混淆后的效果:

Java 字符串模糊匹配中文 java字符串混淆_jar

生成的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