【问题标题】:Java JAR protectionJava JAR 保护
【发布时间】:2012-06-21 11:52:13
【问题描述】:

我编写了一个 Java 应用程序,并计划在线分发它。每个版本都将使用我制作的秘密序列号进行锁定。

我需要保护我的 jar 文件免受反编译器等的影响。这是我目前所做的:

  1. 用户在表单中输入他的序列号
  2. 串口通过 php 脚本发送到我的开发服务器
  3. 脚本生成一个新的 jar bin 文件,该文件以 AES 128 加密
  4. 我的“加载器”将 jar 文件作为字节下载并解密。
  5. 它调用 main 方法。
  6. 用户可以随意使用应用程序
  7. 用户关闭应用
  8. 缓存被清除,一切都返回到第 1 步或之前。

我已经完成了步骤 1 到 3,但我需要知道是否可以制作一个自定义类加载器,从 HTTP 中获取字节、解密它们并调用 main 方法。由于文件是完全加密的(在 PHP 服务器上保存为 bin),我不能使用基本的类加载器。关于第 8 步,是否可以从计算机内存中卸载内容?

【问题讨论】:

  • 我意识到这不是一个非常乐观或有用的想法,但如果您还不知道如何保护您的代码,那么您不太可能编写任何有人想窃取的东西。你的努力可能最好集中在更有成效的地方。
  • “我需要保护我的 jar 文件免受反编译器等的影响。” 当我在自定义 JRE 中运行它时,它是我的。
  • 有什么意义?最终,一切都可以进行逆向工程。让购买您的应用程序的人跳过这些障碍值得您花时间吗?如果你的 JAR 不处理防御/敏感的东西,我在这些事情上看不到任何意义。想偷看幕后的人比例很小。而且真的想偷看幕后的人比例更小,但他们不会放弃,他们会绕过你的方法。所以我认为浪费时间这样做没有什么好处(也许除了学习)。
  • @Dave 我已经用 allatori 混淆了我的代码(实际上这非常好)。我的应用需要一种无法破解的登录表单。
  • @haylem 这样做是因为这是一个安全应用程序。

标签: java classloader urlclassloader source-code-protection


【解决方案1】:

是的,有可能,但也没用。

您的类加载器将是您的安全系统的最薄弱环节。不能加密,所以反编译比较容易。

现在,由于 Classloader 中有一个地方必须有一个字节数组形式的解密类,攻击者唯一需要做的就是将该字节数组转储到文件中。

参考dystroy的代码:

classBytes = EncryptionUtil.decryptBytes(url, key); 

// In this moment, classBytes contains unencrypted class.
// If an attacker adds:   
//
//   FileOutputStream fos = new FileOutputStream("some.name");
//   fos.write(classBytes);
//   fos.close();
// 
// he will destroy all your security.


return defineClass(name, classBytes, 0, classBytes.length);

【讨论】:

  • 这就是为什么我说混淆这是必要的(而不是充分的)。但是您知道,大多数 Java 都在企业中使用,只有少数客户没有足够的动力进行复杂的黑客攻击。
  • @dystroy ClassLoader 的构造相当简单。也很容易找到该类,因为它将是唯一未加密的类,也是用户在其工作站上必须拥有的唯一类。即使你混淆了一个类加载器,它仍然很容易反编译和理解它,因为它的代码很少。
  • 你对使用的解决方案做了很多假设......我回答了具体的技术点,我不会在其(未知)使用环境中验证一般方案。
  • 我想指出的是,很多人认为加密他们的 jars/classes 是个好主意,但实际上很少有人知道它是多么容易被破解。就这样。你的回答很好,我对你的代码没有其他异议:-)
  • SecureClassLoader(包含解密逻辑)保存在jar文件中,并使用jar2exe等工具将jar转换为exe / linux / mac格式。我没有尝试过,所以我不知道它对黑客的安全性有多大。
【解决方案2】:

是的,您可以向类加载器提供您抓取的字节。我在类似的问题中这样做:

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
    }
}

但这不足以保护您的代码。至少,不要为两个用户使用相同的字节(你似乎这样做了)。并混淆你的代码(我使用 proguard)。这将保护您免受普通黑客的攻击,而不是最好的。

【讨论】:

  • 每次用户尝试连接时都会生成字节。所有成功的连接都会收到一个唯一的链接来下载 jar。谢谢你的代码,我试试看。
  • 即使我认为其他评论者做出了太多假设,也不要完全忽略它们,关注这件事是值得的;)
猜你喜欢
  • 1970-01-01
  • 2016-05-16
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 1970-01-01
  • 2012-01-22
相关资源
最近更新 更多