java加密,支持window和linux (防止反编译)

# 情境
项目需要,所以我来做技术调研,对我们也很有利,在公司项目中引入自己封装的jar
加密后别人看不到自己的源码,只能调用,才能显示出来自己的价值


# 过程
之前参考了网上四种方案,连接奉上,不过先把我这篇文章看完再说,以下测试结论以实际为准

主要参考本篇文章,window和linux加解密都可以实现,但是可以通过idea反编译,且项目会启动两次
https://blog.csdn.net/weixin_39747279/article/details/90214044

加密成功,window和linux都解不了
https://blog.csdn.net/ddjc123/article/details/108118775

同上,可以对自定义main方法进行加解密,但是不能启动项目(linux环境测试)
http://lxw1234.com/archives/2017/05/851.htm

这个没有测试
https://github.com/core-lib/xjar

# 我的实验环境
windows:
springboot2.3.4.RELEASE jdk1.8.0_251 visualstudio2010
linux:
ubuntu安装vscode jdk1.8.0_161

# 我的github项目地址
https://github.com/ainusers/encryption-java-source-code.git

# 进入正题
1. 创建一个demo项目,如果是springboot项目,要用自定义maven打包,不然会找不到加密的类
   demo项目会放在最后github项目,如果需要自行打包,maven配置如下所示

注意:生成jar包之后,需要把lib和config两个包,和jar文件放在一起,因为自定义maven打包,是将配置和依赖分离了
<!--<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>-->

    <build>
        <finalName>demo</finalName>
        <resources>
            <resource>
                <!--指定mapping下的所有xml文件打包在jar中-->
                <targetPath>${project.build.directory}/classes</targetPath>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>mapping/*.xml</include>
                </includes>
            </resource>

            <resource>
                <!--resources下一级的所有.xml .properties文件复制到config目录下-->
                <targetPath>${project.build.directory}/config</targetPath>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>**.xml</include>
                    <include>**.properties</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <!--maven-dependency插件,将项目所有依赖包放到lib目录下-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <type>jar</type>
                            <includeTypes>jar</includeTypes>
                            <outputDirectory>
                                ${project.build.directory}/lib
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <classesDirectory>target/classes/</classesDirectory>
                    <archive>
                        <!--生成的jar中,不要包含pom.xml和pom.properties这两个文件-->
                        <addMavenDescriptor>false</addMavenDescriptor>
                        <manifest>
                            <mainClass>com.data.demo.DemoApplication</mainClass>
                            <!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
                            <useUniqueVersions>false</useUniqueVersions>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                        <manifestEntries>
                            <!--jar中的MANIFEST.MF文件ClassPath需要添加config目录才能读取到配置文件-->
                            <Class-Path>config/ .</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
2. 生成dll文件
通过下载的visual studio 2010工具,打开我的github项目中的.cpp和.h
如果报错缺少.h文件:
第一种方案是把github项目提供的.h文件复制到F:\vs2010\VC\include (实际路径自行修改)
第二种方案是把自己环境下的.h拷贝到vs下的include路径,jdk的路径为:
C:\Program Files\Java\jdk1.8.0_251\include
C:\Program Files\Java\jdk1.8.0_251\include\win32

拷贝完成后,注意要配置一下生成64位的dll文件,需要额外的配置一下,如下图所示

3. 通过idea,git clone我上面提供的项目地址,先运行ByteCodeEncryptorTest
   再运行JarEncryptorTest,之后会在demo.jar的同级目录生成一个demo_encrypted.jar

注意项目里面有三处路径,需要修改,一个dll文件路径,一个demo.jar路径,一个加密的类路径
注意,此处加密和解密的路径,需要一致,不然会出现魔数异常,解密不成功

Caused by: java.lang.ClassFormatError: Incompatible magic value 3456286402 in class file com/data/demo/controller/Demo

4. 查看加密

5. 解密,运行项目

上面是window环境下测试的加密和解密,下面简要的说下linux环境的,整体思想就是将window环境的dll文件

打包成linux环境的so文件

1. ubuntu系统安装vscode
下载链接:https://www.lanzoux.com/ipc1ygv69na
通过dpkg -i xxx进行安装

2. 安装好之后,启动要用如下命令启动,不然创建文件或者安装东西,会报没有权限
sudo code --user-data-dir="~/.vscode-root"

3. 安装c/c++插件

-- 如下三个文件,需要额外的注意,配置文件,如下所示
4. launch.json文件

5. tasks.json

6. tasks.out
launch.json

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/tasks.out",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "preLaunchTask": "build",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}
tasks.json

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "g++",
            "args": ["-g", "${file}","-std=c++11","tasks.out"]
        }
     ]
}
7. 使用ubuntu中的vscode生成so文件,如下图所示
注意;linux系统认可的so文件,需要加lib前缀,如果你要的是demo.so
那么你生成命名的时候,需要些libdemo.so

8. linux环境测试
在这里java在linux有默认的依赖读取路径,当然在window也有,如果想看的话,可以使用如下输出
System.out.println(System.getProperty("java.class.path"));

所以,我将libdemo.so放在了/usr/lib目录下当然其他目录也可以

linux环境运行命令:
1. 这个环境变量的路径可以自定义
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/lib
2. 运行
java -agentlib:demo -jar demo_encrypted.jar

如果大家遇到了任何问题,文章下面留言,我会及时回复,即时更新文章

众所周知,java开发语言提供了很方便的开发平台,而且开发出来的程序很容易在不同的平台上面进行移植,现在越来越多的人使用它开发软件。 Java有了它方便的一个方面,但是他同时也带给了开发者一个烦恼,这就是保护的办法不多,而且大多数不是很好用,这样自己辛苦开发出来的程序很容易被人反编译过来而据为己有,一般情况下,大多数的人都是用混编器(java obfuscator)来把开发出来的程序进行打乱以达到没有办法来反编译观看源代码,但是这种办法在网上很容易找到相关的软件来重新整理,那么这个混编只能控制一些本来也没有办法动您的软件的人,而对于一些掌握工具的人几乎是透明的,还有就是利用硬件加密锁,但大多数公司提供的硬件加密锁只是提供了一些dll的连接或简单的api调用,只要反编译他们,就很容易把一些api调用去掉,这样硬件加密锁也就不起作用了,但是现在到底有没有好的办法呢? 市场上现有的几款防止反编译工具其实都是改进了加载过程。但是加载到JAVA虚拟机后一样可以得到CLASS字节码的。 只要懂JAVA原理的人其实很用意破解的. JAVACOMPILE 这款工具就不一样了,javacompile 它是修改了虚拟机内核, 用户目录里没有需要的JAVA字节码,而是当JAVA需要调用函数的时候才通过网络下载相对应的已经二次编译的字节码,就算用户通过 CLASS.getClass 也得不到可以用来反编译字节码。 真正意义上保护了JAVA知识产权。 个人版限制编译30个CLASS文件文件打包方式下载。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值