【问题标题】:Java - Can I run an encrypted native executable without writing it to a harddisk first? [closed]Java - 我可以在不先将其写入硬盘的情况下运行加密的本机可执行文件吗? [关闭]
【发布时间】:2014-07-31 04:01:17
【问题描述】:

我有一个已编译的本机程序,该程序为安全起见进行了加密(例如加密的 exe 文件)。我想在不将纯文本(未经加密的)副本写入用户硬盘的情况下运行它。我知道本机程序可以使用 java 的运行时类运行,但我希望能够运行加密版本。在不将未加密的数据写入磁盘的情况下,如何在 Java 中解密和运行本机程序。我可以在 Java 运行时执行字节数组吗?如果是这样,我是否必须使用 JNA/JNI?

另外,对于 Microsoft Word 文档或 PDF 等非本地专有文件类型,这是否可行?

如果可能,我希望避免使用第三方软件,例如 TrueCrypt。

提前感谢您的帮助。

【问题讨论】:

  • 我认为你必须澄清你的问题,我已经阅读了 4 次,但仍然不知道你在问什么。从它的声音来看,你已经将一些数据加密到一个文件和/数据库中,如果有什么方法可以通过其他进程加载它?是的,如果您提供可以解密该内容的方法...
  • hummm 一个黑客工作......我认为这里不适合这种事情。
  • 你好,请假设内存中的字节数组被解密,我主要关心硬盘活动。我应该研究哪些方法/JPA/JNI 方法?
  • 使用传统的ramdisk?
  • 如果二进制文件 Java,你会有更多希望。然后你可以写一个自定义类加载器。如果要执行加密的 EXE,则必须重新实现所有操作系统的加载等,我怀疑这在一般情况下是否可行。

标签: java encryption java-native-interface runtime native


【解决方案1】:

我相信 CipherInputStream 可能会对您有所帮助。它的功能与普通的 InputStream 对象一样,但也应用了 Cipher(加密或解密)。如果您想以非纯文本格式读取文件,请使用 CipherOutputStream 写入文件,然后像在另一端使用 CipherInputStream 的任何其他文件一样正常读取它。

如果您的文件已经加密(听起来确实如此),您只需要将 CipherInputStream 初始化为用于创建本机代码的任何加密方法。

        FileInputStream in = new FileInputStream("YOUR DIRECTORY");
        Cipher decryptionCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, createKey(password));

        CipherInputStream ciphIn = new CipherInputtStream(in, decryptionCipher);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[8];
        int i = in.read(buffer);
        while (i != -1)
        {
            //just like a file copy
            out.write(buffer, 0, i)
            i = in.read(buffer);
        }

        /*
         * YOUR NATIVE DATA UNENCRYPTED
         */
        byte[] nativeFileData = out.toByteArray();

        ciphIn.close();
        in.close();

创建密钥方法:

public SecretKey createKey(String password) throws NoSuchAlgorithmException, InvalidKeySpecException
{
        //hash the password
        MessageDigest msgDigest = MessageDigest.getInstance("SHA-1");
        msgDigest.update(key);
        byte[] hash = msgDigest.digest();

        byte[] salt = new byte[8]{};
        new SecureRandom(hash).nextBytes(salt);

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(hash, salt, 65536, 128);
        SecretKey tmp = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        return secret;
}

您现在将拥有一个包含本机未加密字节的字节数组。所以现在你可以使用 JNI/JNA 类来运行它(假设它像一个 exe 或其他东西)。可以将本机代码加载到内存中。然后将该内存分配为可执行文件,您可以使用本机系统调用将其作为汇编指令运行。已经有一篇关于这样做的堆栈溢出文章位于here。由您决定以 JNI 格式实现它。

就打开 PDF/DOCS 文件而言,您说的是使用您一无所知的系统调用接口的专有程序读取专有文件格式。我也很困惑为什么用户可以打开这些文件并查看内容,但他们无法访问该文件。如果你能澄清那将是很棒的。您可以做的是获取此字节数组并使用库将 pdf 渲染为 png 图像,然后使用 javafx 显示图像。

我知道这个答案并不正确,但我希望它对您有所帮助或至少为您指明正确的方向。

干杯。

【讨论】:

  • 您现在可以运行字节数组如何?
  • 您可以使用本地系统调用 VirtualProtect() 将 C/C++ 中的字节数组加载到可执行内存中,然后将该内存作为汇编指令执行。已经有一个关于这个主题的 C++ stackoverflow 问题。我没有在用户要求的上下文中看到这一点,但是在您指出它之后,我发现我错过了它。谢谢。我将编辑问题。
猜你喜欢
  • 2018-07-16
  • 1970-01-01
  • 2012-06-15
  • 2019-11-10
  • 2011-03-31
  • 2021-01-16
  • 2014-12-16
  • 1970-01-01
  • 2017-11-19
相关资源
最近更新 更多