Java JAR保护
我已经编写了一个Java应用程序,并计划在网上发布。每次发布都会被我制作的一个秘密序列密钥锁定 我需要从反编译器等保护我的jar文件。以下是我到目前为止所做的工作:Java JAR保护,java,classloader,urlclassloader,source-code-protection,Java,Classloader,Urlclassloader,Source Code Protection,我已经编写了一个Java应用程序,并计划在网上发布。每次发布都会被我制作的一个秘密序列密钥锁定 我需要从反编译器等保护我的jar文件。以下是我到目前为止所做的工作: 用户在表单中输入其串行密钥 序列号通过php脚本发送到我的开发服务器 该脚本生成一个新的jar-bin文件,该文件在AES 128中加密 我的“加载器”将jar文件作为字节下载并解密 它调用main方法 用户可以随意使用该应用程序 用户关闭应用程序 缓存被清除,所有内容都返回到步骤1或之前 我已经完成了步骤1到3,但是我需要知道是否
我已经完成了步骤1到3,但是我需要知道是否有可能创建一个自定义类加载器,从HTTP获取字节,解密它们并调用main方法。由于文件是完全加密的(在PHP服务器上保存为bin),我不能使用基本类加载器。关于步骤8,可以从计算机内存中卸载内容吗?是的,可以,但也没用 您的类加载器将是安全系统的最薄弱点。它不能被加密,因此反编译相对容易 现在,由于类加载器中有一个地方必须有一个以bytearray形式解密的类,攻击者唯一要做的就是将这个字节数组转储到一个文件中 参考公司代码:
是的,您可以向类加载器提供您获取的字节。我在一个类似的问题中这样做:
public class SecureClassLoader extends URLClassLoader {
@Override
protected Class<?> findClass(final String name) throws ClassNotFoundException {
if (isEncrypted(name)) {
final String resourceName = name.replace('.', '/') + ".class";
URL url = findResource(resourceName);
if (url != null) {
byte[] classBytes = null;
try {
classBytes = EncryptionUtil.decryptBytes(url, key);
return defineClass(name, classBytes, 0, classBytes.length);
} catch (ClassFormatError e) {
log.severe("Bad format for decrypted class " + name);
throw new EncryptedClassNotFoundException(name, e);
} catch (InvalidKeyException e) {
throw new EncryptedClassNotFoundException(name, e);
} catch (IOException e) {
throw new EncryptedClassNotFoundException(name, e);
}
}
}
// default loader
try {
return super.findClass(name);
} catch (ClassNotFoundException e) {
throw new EncryptedClassNotFoundException(name, e);
}
}
private boolean isEncrypted(String className) {
/// some things
}
}
公共类SecureClassLoader扩展了URLClassLoader{
@凌驾
受保护类findClass(最终字符串名称)引发ClassNotFoundException{
如果(已加密(名称)){
最后一个字符串resourceName=name.replace('.','/')+“.class”;
URL=findResource(资源名称);
如果(url!=null){
byte[]classBytes=null;
试一试{
classBytes=EncryptionUtil.decryptBytes(url,密钥);
返回defineClass(名称,classBytes,0,classBytes.length);
}捕获(类格式错误){
log.severe(“解密类的格式错误”+名称);
抛出新的EncryptedClassNotFoundException(名称,e);
}捕获(InvalidKeyException e){
抛出新的EncryptedClassNotFoundException(名称,e);
}捕获(IOE异常){
抛出新的EncryptedClassNotFoundException(名称,e);
}
}
}
//默认加载程序
试一试{
返回super.findClass(名称);
}catch(classnotfounde异常){
抛出新的EncryptedClassNotFoundException(名称,e);
}
}
私有布尔值已加密(字符串类名称){
///有些事情
}
}
但这不足以保护您的代码。至少,不要对两个用户使用相同的字节(你似乎这样做了)。并混淆您的代码(我使用proguard)。这将保护您免受普通黑客的攻击,而不是最好的黑客。我意识到这不是一个非常乐观或有益的想法,但如果您还不知道如何保护代码的安全,那么您不太可能编写了任何有人想要窃取的东西。您的努力可能最好集中在更高效的地方。“我需要从反编译器等保护我的jar文件。”当我在自定义JRE中运行它时,它是我的。这有什么意义?最终,一切都可能是逆向工程。让购买你的应用程序的人跳过这些障碍值得你花时间吗?如果你的罐子里没有防御性/敏感性的东西,我看不出这些东西有什么意义。想躲在窗帘后面偷看的人比例相当小。真正想躲在窗帘后面偷看的人比例更小,但他们不会放弃,他们会绕过你的方法。因此,我认为浪费时间这样做没有多大好处(除了学习)。@Dave我已经用allatori混淆了我的代码(实际上很好)。我需要一种无法破解的应用程序登录表单。@haylem它是这样做的,因为这是一个安全应用程序。这就是为什么我说混淆这一点是必要的(但还不够)。但您知道,大多数java都是在企业中使用的,只有少数客户没有足够的动机进行复杂的黑客攻击。该类也很容易找到,因为它将是唯一未加密的类,也是用户必须在其工作站上拥有的唯一类。即使你混淆了一个类加载器,反编译和理解它仍然是非常容易的,因为它只有很少的代码。。。我回答了具体的技术问题,我没有在(未知的)使用环境中验证通用方案。我想指出的是,很多人认为加密他们的JAR/类是一个好主意,实际上很少有人意识到它是多么容易被破坏。这就是全部。您的答案很好,我对您的代码没有其他异议:-)将
SecureClassLoader
(包含解密逻辑)保存在jar文件中,并使用以下工具将jar转换为exe/linux/mac格式:。我还没有试过,所以我不知道黑客攻击有多安全。每次用户尝试连接时都会生成字节。所有成功的连接都会收到下载jar的唯一链接。谢谢你的代码,我会试试看。即使我认为其他评论者做出了太多的假设,也不要完全忽略它们,关注这件事是值得的;)
public class SecureClassLoader extends URLClassLoader {
@Override
protected Class<?> findClass(final String name) throws ClassNotFoundException {
if (isEncrypted(name)) {
final String resourceName = name.replace('.', '/') + ".class";
URL url = findResource(resourceName);
if (url != null) {
byte[] classBytes = null;
try {
classBytes = EncryptionUtil.decryptBytes(url, key);
return defineClass(name, classBytes, 0, classBytes.length);
} catch (ClassFormatError e) {
log.severe("Bad format for decrypted class " + name);
throw new EncryptedClassNotFoundException(name, e);
} catch (InvalidKeyException e) {
throw new EncryptedClassNotFoundException(name, e);
} catch (IOException e) {
throw new EncryptedClassNotFoundException(name, e);
}
}
}
// default loader
try {
return super.findClass(name);
} catch (ClassNotFoundException e) {
throw new EncryptedClassNotFoundException(name, e);
}
}
private boolean isEncrypted(String className) {
/// some things
}
}