作者:微信小助手
发布时间:2023-07-28T15:54:01
点击蓝字之后,我们就是好朋友了啦 15
前言
最近和朋友聊天,他接了个外包项目,他问我有没有办法让自己的源码不被反编译破解,我就跟他说可以对代码进行混淆和加密。今天我们就来聊聊如何通过对代码进行加密实现代码防反编译,至于混淆因为可以直接利用proguard-maven-plugin进行配置实现,相对比较简单,就不在本文论述
代码防编译整体套路
1、编写加密工具类
@Slf4j
public class EncryptUtils {
private static String secretKey = "test123456lyb-geek"+System.currentTimeMillis();
private EncryptUtils(){}
public static void encrypt(String classFileSrcPath,String classFileDestPath) {
System.out.println(secretKey);
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(classFileSrcPath);
fos = new FileOutputStream(classFileDestPath);
int len;
String[] arrs = secretKey.split("lyb-geek");
long key = Long.valueOf(arrs[1]);
System.out.println("key:"+key);
while((len = fis.read())!=-1){
byte data = (byte)(len + key + secretKey.length());
fos.write(data);
}
} catch (Exception e) {
log.error("encrypt fail:"+e.getMessage(),e);
}finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2、对需要防止被反编译代码加密
public static void main(String[] args) {
String classFileSrcPath = classFileSrcPath("UserServiceImpl");
System.out.println("classFileSrcPath:--->"+classFileSrcPath);
String classFileDestDir = ServiceGenerate.class.getClassLoader().getResource("META-INF/services/").getPath();
System.out.println("classFileDestDir:--->"+classFileDestDir);
String classFileDestPath = classFileDestDir + "com.github.lybgeek.user.service.impl.UserServiceImpl.lyb";
EncryptUtils.encrypt(classFileSrcPath,classFileDestPath);
}
3、对加密代码进行反编译验证
打开反编译工具jd-gui,把加密的代码拖入jd-gui
打不开,至少说明不能用jd-gui来反编译加密过的代码。
我们打开正常的编译的class文件,其内容形如下
从内容我们大概还是能看出一些东西,比如包名啥的。而打开加密后的文件,其内容如下
内容宛若天书
思考一:代码都被加密了,那jvm如何识别?
答案:既然有加密,自然可以通过解密来使用。那这个解密得存放在什么地方进行解密?
如果对类加载有一定了解的朋友,就会知道java的class文件是通过类加载器把class加载入jvm内存中,因此我们可以考虑把解密放在类加载器中。常用的类加载有启动类加载器、扩展类加载器、系统类加载。我们正常classpath路径下的类都是通过系统类加载器进行加载。而不巧这三个jdk提供的加载器没法满足我们的需求。因此我们只能自己实现我们的类加载器。其自定义加载器代码如下
@Slf4j
public class CustomClassLoader extends ClassLoader{
/**
* 授权码
*/
private String secretKey;
private String SECRETKEY_PREFIX = "lyb-geek";
/**
* class文件的根目录
*/
private String classRootDir = "META-INF/services/";
public CustomClassLoader(String secretKey) {
this.secretKey = secretKey;
}
public String getClassRootDir() {
return classRootDir;
}
public void setClassRootDir(String classRootDir) {
this.classRootDir = classRootDir;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
&n