前言
最近一段时间没有怎么写原著文章了,转载了不少文章,主要还是因为文章作者写的太好就直接摘抄了。本文算安全方面的应用,在工作过程中应该会有所遇到,主要就是关于程序员完成项目之后对源码的处理,像java开发中就会遇到,为了避免源码被反编译来揣测项目的业务原理,往往都会做一些操作,比如混淆源码【proguard】,如果隐藏方法体【classfinal】,还有直接加密jar包避免被工具直接看到的【xjar】,本文主要介绍这三种方式,接下来是截图和源码的展示,毕竟这是我写作的一贯作风主要还是为了大家更好的观看。
proguard
】强烈不推荐简明
将源码的类名方法名用字母进行替换,并且同步修改所有相关的类方法及属性名,但可以看到具体的实现,只是对于有严格命名规范的书写方式来说看起来很头疼,但花时间看还是能看明白。但是混淆之后再来启动jar
包的时候你会发现启动不了了,然后又得去配置文件添加更多的配置来规避一些类,依次搞定还好,多几次说实话你就会感觉非常的难受了。
#指定Java的版本
-target 1.8
#proguard会对代码进行优化压缩,他会删除从未使用的类或者类成员变量等
-dontshrink
#是否关闭字节码级别的优化,如果不开启则设置如下配置
-dontoptimize
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
# 对于类成员的命名的混淆采取唯一策略
-useuniqueclassmembernames
#混淆时不生成大小写混合的类名,默认是可以大小写混合
-dontusemixedcaseclassnames
#混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代
-adaptclassstrings#对异常、注解信息予以保留
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# 此选项将保存接口中的所有原始名称(不混淆)-->
-keepnames interface ** { *; }
# 此选项将保存所有软件包中的所有原始接口文件(不进行混淆)
#-keep interface * extends * { *; }
#保留参数名,因为控制器,或者Mybatis等接口的参数如果混淆会导致无法接受参数,xml文件找不到参数
-keepparameternames
# 保留枚举成员及方法
-keepclassmembers enum * { *; }
# 不混淆所有类,保存原始定义的注释-
-keepclassmembers class * {@org.springframework.context.annotation.Bean *;@org.springframework.beans.factory.annotation.Autowired *;@org.springframework.beans.factory.annotation.Value *;@org.springframework.stereotype.Service *;@org.springframework.stereotype.Component *;}#忽略warn消息
-ignorewarnings
#忽略note消息
-dontnote
#打印配置信息
-printconfiguration
-keep public class com.example.Application {public static void main(java.lang.String[]);}
注意
下列代码是springboot项目的启动类,表示启动类不混淆
-keep public class com.example.Application {public static void main(java.lang.String[]);}
com.github.wvengen proguard-maven-plugin 2.6.0 package proguard ${project.build.finalName}.jar ${project.build.finalName}.jar true ${project.basedir}/proguard.cfg ${java.home}/lib/rt.jar ${java.home}/lib/jce.jar ${java.home}/lib/jsse.jar !META-INF/**,!META-INF/versions/9/**.class ${project.basedir}/target org.springframework.boot spring-boot-maven-plugin repackage com.example.Application
mvn clean install
打包下列是混淆的部分日志
下面提出混淆效果图,对于关键字的都是保留了的,并且对于接口的都是保留了的,配置文件里有相应的配置信息
简明
classfinal
和proguard
有些类似,但不一样的是classfinal
会隐藏方法体,但不会重命名包名,类名,方法名,如果要隐藏配置文件这类关键的信息,不是一定能够处理成功的,存在各种各样的bug
,我试过隐藏application.properties
,和logback.xml
,前者隐藏不影响系统启动和使用,但后者被隐藏之后,无法解析,项目无法启动,另外如果项目使用了flument-mybatis
的框架也是无法被加密的,打包期间会报错,并且对任何文件都没有加密
net.roseboy classfinal-maven-plugin 1.2.1 com.example *.properties,*.xml org.spring package classFinal
mvn clean install
打包以下是打包日志,打包完成之后会有两个jar
,一个是正常的jar
,一个是加密的jar
,加密的jar
会在最后加【-encrypted
】
JD-GUI
打开加密的jar
包下面是使用工具反编译的效果图,类名方法名都没有被重命名,但方法体没有了,但是构造函数的方法体并没有被隐藏,所以classfinal
总体来说还是存在缺陷
java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jar
然后输入密码:`r123456`
xjar
实现jar
包的加密【推荐】简明
xjar
可以直接加密整个jar
,也可以加密重要的部分,像一些开源的其实是不需要加密的,xjar加密的内容是不能使用JD-GUI
等反编译工具打开的,他会生成一个以.xjar
为后缀的包和一个以.go
为后缀的包,前一个包就是加密的后的包,后一个是可以用于执行加密包的可执行程序,但需要在go
环境下才能使用,当然也可以不用go
环境启动加密包,后续会进行介绍。但使用xjar
的maven
插件对集成了flument-mybatis
框架的项目不能正常加密,单独加密jar
包我没有试过,可以自行操作。
xjar-maven-plugin
com.github.core-lib xjar-maven-plugin 4.0.1 build install /com/example/**/*.class /mapper/**/*.xml /*.properties /*.xml /templates/**.* /static/**.*
jitpack.io https://jitpack.io
mvn clean install -Dxjar.password=yourPassword
进行打包
JD-GUI
工具反编译xjar
的后缀,改为jar
JD-GUI
反编译jar
包,发现根据看不到class
的内容,并且application.properties
和logback.xml
都已经被加密,被更改为二进制文件了方法一:通过go
环境启动项目【本文介绍windows
环境】
go
环境,前往官网下载并安装,安装流程不做讲述https://golang.google.cn/dl/
xjar.go
go build xjar.go
xjar.exe java -jar xxx-en.jar
方法二:直接使用java -jar
启动加密包
java -jar xxx-en.xjar
然后在控制台依次输入【算法,密钥长度,向量长度,密码】
AES/CBC/PKCS5Padding
128
128
r123456