2

我编写了一个 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 步,是否可以从计算机内存中卸载内容?

4

2 回答 2

5

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

您的类加载器将是您的安全系统的最薄弱环节。它不能被加密,因此反编译它会相对容易。

现在,由于 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);
于 2012-06-21T11:55:52.167 回答
0

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

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)。这将保护您免受普通黑客的攻击,而不是最好的黑客。

于 2012-06-21T11:56:14.690 回答