使用JVMTI实现Java源码加密及SpringBoot项目包加密解决方案实践总结

这里写自定义目录标题)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

  本文主要介绍利用JVMTI加密JAVA源码的实践方法以及SpringBoot项目加密的解决方案,并对几种常见的加密方式进行对比分析,JVMTI加密网上已经有很多相似文章,但对于SpringBoot包加密的方案及过程中遇到的问题都没有讲的太清晰,针对这个问题,文中着重用一章节内容来分析讨论,相信大家认真读完后会对SpringBoot包的加密问题及其框架运行方式有进一步深入的理解。

1. 为什么要对源码加密

  技术方面:首先强调下这里的源码加密指的是对使用Java开发的软件产品源码进行加密,Java是解释型语言(实事上是编译型与解释型混合),在生成软件产品时源代码被编译成有规范可循的二进制字节码.class文件进行打包,然后由JVM将.class解释给CPU执行,而非C/C++、C#等编译型语言一样源码被直接编译成CPU可执行的机器码,所以我们拿到Java的软件产品后,对照相应的编译规范,很容易将.class文件内容还原成源代码,即便是人工还原也只是时间问题,不存在很困难的技术问题,也就是说.class文件基本上可以等同于源码文件,而这里说的源码加密也主要是对.class文件进行处理,使其在现有的手段下难以被反编译还原。
  生产方面:源码加密最主要的原因就是为了保护知识产权,不论是个人还是公司、单位,软件都是劳动的成果,而源码就是成果的核心,加密就是为了保护劳动成果不被窃取。
  安全方面:软件交付部署后,尤其是web应用,如果被还原成源码,很容易理清内部业务运行的逻辑关系或发现潜在漏洞,被非法利用操作,对系统数据产生破坏,因此安全也是源码加密的重要因素。

2. 源码加密的方法

  加密的目的是人读不懂机器明白,所以方法也要从这两点入手,对于解释型语言,一般有混淆和字节码转换两大类:
  (1)混淆
  主要思路就是通过对变量、函数、类名等进行替换,或者更深层的对语义上进行转换,使得代码不容易阅读,但对整个代码的逻辑关系和结构没有影响,而且可以借助jd-gui等工具直接将.class文件转换成源码,只要有耐心,弄懂源码设计思路完全没有问题,是相对比较简单的方式,总结起来就是加密让人难读懂,但不影响机器明白。
  (2)字节码转换
  主要思路是通过加密算法修改.class文件,然后打包成软件产品,运行时调用解密算法对.class文件动态解密,转换成能够被JVM装载识别的二进制字节码,操作起来技术含量较高,也不容易被反编译,是相对比较稳妥的加密方式,总结起来就是加密后让人和机器都读不懂,但给个机器明白的解密算法帮助机器懂;从解密方法实现上来说,又分为以下几种:
  a) 定制ClassLoader
  主要思路是通过在软件中加入自定义类加载器,集成解密算法,在读取类二进制节码后,先对字节码解密再成类;
  b) 利用Instrument
  主要思路是通过继承Instrument中的ClassFileTransformer,编写对应的transform方法进行解密,生成相应的类包文件decrypt.jar,使用java -javaagent:decrypt.jar –jar xxx.jar命令启动加密后的软件,通过Premain-Class,向Instrumentation注入ClassFileTransformer实现进行运行时类文件的解密;
  c) JVMTI编程
  主要思路是通过JVMTI编程,使用C/C++将解密算法封装在decrypt.dll文件中,使用java -agentpath:decrypt.dll –jar xxx.jar命令启动加密后的软件,通过Agent_OnLoad引入ClassFileLoadHook实现运行时类文件的解密。
  除以上两大类方法外,还有一些别的方法,例如将软件整体加密,启动前先解密后再运行,也都可以在特定场景下满足一定的源码加密需求,但没有绝对安全不可破的加密方法,我们要做的只是通过一定的手段,增加盗版的成本,尽可能最大程度的对源码进行保护。
  本文在项目源码加密方案中使用了JVMTI编程这种方法,所以下文会着重论述这种方法的特点、实现方法及在SpringBoot项目中存在的问题与解决办法。

3. 为什么选择JVMTI方法

3.1 加密方法分析

  前面已经讨论过几类加密的方法,下面结合个人理解,从设计思路、技术要求、算法依赖性及效果等方面对上述几种方法的优势与不足进行分析:
  (1) 源码混淆
  这种方法的主要思路是增加源码阅读障碍,也就是说不影响源码的打开查看,加密等级最低,但从实现来说却需要加密者对.class文件的结构非常熟悉(当然使用第三方组件、工具另论),要能准确识别其中的各类变量、函数、类名等,需建立一套混淆关系表,统一处理各类之间的相互引用、方法及变量的调用等,否则会出现加密后类文件损坏、类引用失败或方法调用错误等问题。
  a) 这类方法设计思路相对比较简单,并且已经有很多功能完善的第三方组件、工具,直接使用即可,这也是一大优势。
  b) 技术上要求对.class文件内容结构非常熟悉,而且实现起来需要注意的细节多、操作繁琐。
  c) 算法上主要是对类变量、函数、方法等名称的处理,技术难度不高;软件对算法的依赖度低,当然这是优点也是缺点,方便自己的同时也方便了别人。
  d) 效果上混淆后.class文件内容结构未发生改变,业务逻辑及处理算法等未受到有效保护,保护程度低。
  总体来说如果自己要从零开始搞一套的话性价比不高。
  (2) 字节码转换
  字节码转换的方法比较釜底抽薪,可以从根本上改变.class文件的结构,加密后的文件就是一份普通的二进制文件,甚至给人的感觉是一份损坏的.class文件,在没有解密算法的情况下很难被反编译,可以有效的保护软件源码。
  a) 设计思路上这类方法基本相通,都是对加密过的.class文件二进制编码进行解密处理后转再换成具体类,只是实现过程有所不同:定制ClassLoader方式需要手动调用解密方法,而利用Instrument(底层实现也是基于JVMTI)和JVMTI编程则是把这个调用过程交给JVM自动实现。
  b) 技术上涉及知识面广,除了对.class文件内容结构有一定了解外,还要对Java类的加载机制原理、自定义类加载器、JNI、JVMTI及JVM运行等有一定了解,技术要求高。
  c) 算法上主要是对.class文件的处理,这个过程本身技术要求不高,但算法设计是重点,而且软件对算法依赖度高,缺失解密算法软件产品或不能正常运行。
  d) 效果上依实现方式差异而有所不同,前面总结过这类方法目的是加密后让人和机器都读不懂,但给个机器明白的解密算法帮助机器懂,解密算法是关键并且要随软件交付,所以问题也就从对源码的保护进一步转移到了对加解密算法的保护;好的算法固然可以使.class文件难以被反编译,但算法被破解了,所有的加密操作都将功亏一篑,所以这类加密的效果主要依赖于对算法的保护:定制ClassLoader与Instrument使用Java语言实现解密过程,虽然对.class文件进行了加密,但解密过程却被暴露了,对于经验丰富的程序员来说找到相应解密算法,从而破解并反编译出源码只是时间问题;而JVMTI编程使用C/C++语言实现解密过程,然后封装成dll文件,最终由JVM自动调用解密,鉴于C/C++编译型语言的特性,dll文件不容易被破解,所以算法也就能更好的被保护起来,当然这也不是绝对的方法,技术专家可以通过JVM本身或其他手段获取到软件源码,但这需要较高的技术能力和丰富的开发经验。

3.2 选择JVMTI方法

  通过分析不难看出,JVMTI编程这种方法对.class加密,不仅能够很好的实现源码的保护,更能使解密算法及解密过程被保护起来,总体来说是目前效果最理想的办法,也是本文后续着重讲述的技术点。

4. JVMTI加密实现

  前面已经论述过加密思路,这里直接上图,更直观的说明从生成dll文件到类加解密调用整个过程:
图4-1 JVMTI加密及解密总图

图4-1 JVMTI加密及解密总图

4.1 思路

  (1) 使用C++编写加解密算法,并封装成jarencrypt.dll文件,对应上图深蓝色步骤①-⑤;
  (2) 编写加密工具调用jarencrypt.dll中的算法实现jar包内.class文件加密,上图红色部分;
  (3) 使用加密工具对demo进行测试验证,对应上图浅蓝色步骤①-⑦。

4.2 环境

  (1) VisualStdio2012,用于编写算法、封装dll;
  (2) IDEA2018(JDK8),用于编写加密工具及测试工程;
  (3) SpringBoot(2.3.4.RELEASE),测试工程引用版本,用于后续对SpringBoot工程jar包加密方法的讨论。

4.3 实施

4.3.1 封装jarencrypt.dll

  这一步是整个加密方案的核心内容,涉及JNI、JVMTI编程两部分,相关技术细节不再赘述,重点讲述方法的实现步骤:
在这里插入图片描述

图4-2 编写jarencrypt.dll引入类并编译成JarEncrypt.class

在这里插入图片描述

图4-3 使用命令javah JarEncrypt生成JarEncrypt.h头文件

在这里插入图片描述

图4-4 打开VisualStudio新建Win32项目编写jarencrypt.dll

在这里插入图片描述

图4-5 将前面生成的JarEncrypt.h内容作为dll项目的头文件,命名自定义

在这里插入图片描述

图4-6 将jni.h、jni_md.h、jvmti.h三文件复制并引入到头文件中,文件路径见上图红框

在这里插入图片描述

图4-7 编写源文件-参照头文件
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
简要介绍 JAVA CLASS文件加密工具是一款专门为保护您的JAVA源代码而设计的软件。传统的JAVA代码保护方式通常是扰乱生成的CLASS文件,从而降低反编译生成的源代码的可读性;有的保护工具甚至能生成部分废代码(垃圾代码),使得反编译后的源码在重新编译时出现编译错误,不能直接生成CLASS文件。这种方法具有一定的效果,但是不能彻底保护您的JAVA源代码。 JAVA CLASS文件加密工具对CLASS文件进行加密保护,加密密钥高达256位(bit,即:32字节),并采用多重加密的算法,既安全又高效。加密后的CLASS文件不可能被破解;反编译工具对加密后的CLASS文件无能为力,根本就不能处理! 运行方式 运行时,加密后的CLASS文件要能正常加载,需要使用我们提供的动态库lanswon.dll。执行java时带上参数 -agentlib:<动态库文件所在路径>\lanswon 注意:不要加文件后缀.dll,直接使用文件的名字部分(classloader)! 举例说明:例如,本加密工具安装在c:\lanswonsoft\java_protect,执行加密后的CLASS文件的命令行如下: java -agentlib:c:\lanswonsoft\java_protect\lanswon <您的CLASS类及参数> 应用场合 独立的应用程序(Application,自定义main方法),运行java时,带上参数-agentlib:<所在路径>\lanswon Tomcat等JAVA Web Server,修改启动脚本,把执行java的命令行加上参数-agentlib:<所在路径>\lanswon JBOSS等JAVA Application Server(应用服务器),修改启动脚本,把执行java的命令行加上参数-agentlib:<所在路径>\lanswon 适用环境 操作系统:Windows 98/2000/XP 等Windows系统 JDK:1.5.0及以上版本
### 回答1: JVMTIJava虚拟机调试接口的缩写,它是Java平台提供的一组原生接口,可以帮助开发者在Java虚拟机层面参与程序的调试和分析过程。JVMTI可以为开发者提供很多方便的调试工具,比如断点、内存泄漏检查、垃圾回收统计信息等等。但是JVMTI本身并不提供加密jar的能力,因为它的主要作用是提供开发者在运行时操作虚拟机的接口,而不是加密jar。 如果您想对Java程序的jar进行加密或者保护,您可以考虑使用Java加密扩展(JCE)这个Java API。JCE可以帮助您实现加密通信、数字签名和安全密钥管理等功能。JCE的加密算法括DES、AES、RSA等多种标准算法,也支持其他自定义算法。使用JCE加密jar可以保护您的程序不被反编译或者恶意利用,同时也可以保护数据的机密性和完整性。 总之,JVMTI和JCE都是Java平台提供的重要接口,但是它们的作用不同,前者主要用于开发和调试,后者则是用于加密和保护数据安全的。如果您需要对Java程序进行加密保护,建议使用JCE这个Java API。 ### 回答2: JVMTIJava虚拟机工具接口的缩写,是JDK 1.5加入的一项新功能,它提供一组API,可以在运行时监控、检测和管理Java虚拟机和Java应用程序。JVMTI可以被用于加密Java程序的JAR加密JAR的目的在于保护Java程序的源代码,防止别人拷贝或查看程序的源代码。使用JVMTI进行JAR加密的步骤如下: 1. 创建一个新JAR文件,可以使用Java工具命令创建。 2. 将需要加密的JAR文件和一个密钥文件放入创建的新JAR文件中。 3. 使用JVMTI API,从Java VM中获取应用程序的字节码,然后使用密钥对其进行加密。 4. 加密后的字节码存入新的JAR文件中,并将原始JAR文件中的其他文件也复制到新的JAR文件中。 5. 加密后的JAR文件可以被用于发布Java程序。 JVMTI加密Jar可以确保Java程序源代码的安全性。虽然Java编译后会生成字节码,可以进行反编译,但加密后的字节码无法被反编译,从而保护程序的源代码不被泄露。 ### 回答3: JVMTIJava虚拟机工具接口的缩写,它提供了访问Java虚拟机内部的调试和监控的功能。在Java开发过程中,为了保护Java代码的安全性,我们通常会使用加密技术来保护Java代码,而对于已经被加密Java代码,我们需要使用JVMTI来进行反调试和监控。JVMTI可以访问Java虚拟机内部的数据结构,可以读写Java类的字节码、常量池、方法表和字段表。因此,我们可以使用JVMTI来解密加密Java代码,并获取其源代码和调试信息。 对于加密的jar,我们可以使用JVMTI工具来进行解密。首先,我们需要创建一个JVMTI的Agent程序,Agent是一种能够监控和修改Java应用程序的工具,它可以在程序运行时进行操作,可以读取和修改Java类的字节码,同时还可以获取应用程序内部的状态信息。然后,我们需要将Agent程序注入到Java虚拟机中,并使用JVMTI来获取加密的jar的字节码,并进行解密操作。解密完成之后,我们可以将解密后的字节码重新加载到虚拟机中,这样就可以获取到源代码和调试信息了。 总之,JVMTIJava开发中非常重要的工具,它可以帮助我们进行调试和监控Java应用程序,同时还可以帮助我们解密加密Java代码。使用JVMTI可以使我们更好地了解Java程序的运行机制,保护Java代码的安全性,并提高我们的开发效率。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值