如何locking编译的Java类以防止反编译?
如何locking已编译的Java类以防止反编译?
我知道互联网上的这个话题一定是非常好的,但是在提到这个话题之后,我不能得出任何结论。
许多人确实提出了混淆器,但他们只是将难以记忆的字符序列重新命名为类,方法和字段,但敏感常量值又是如何呢?
例如,您已经开发了基于密码的encryption技术的encryption和解密组件。 现在在这种情况下,任何普通的Java人都可以使用JAD来反编译类文件,并轻松地检索密码值(定义为常量)以及salt ,然后通过编写小的独立程序来解密数据!
或者应该用本地代码(例如VC ++)构build这种敏感的组件并通过JNI调用它们?
一些更高级的Java字节码混淆器不仅仅是类名称混合。 例如, Zelix KlassMaster也可以使您的代码stream以一种非常难以遵循的方式进行争夺,并作为优秀的代码优化器工作。
此外,许多混淆器也能够扰乱你的string常量并删除未使用的代码。
另一个可能的解决scheme(不一定排除混淆)是使用encryption的JAR文件和执行解密的定制类加载器(最好使用本机运行时库)。
第三(也可能提供最强的保护)是使用本地提前编译器(如GCC或Excelsior JET) ,例如,将Java代码直接编译为特定于平台的本机二进制文件。
无论如何,你必须记住,正如爱沙尼亚语所说:“锁是为了动物”。 意思是说,在运行期间,每一段代码都可用(加载到内存中),并给予足够的技巧,决心和动力,人们可以并将反编译,解密和破解你的代码。你的工作只是使过程不舒服你可以而且仍然保持工作的事情…
只要他们能够访问encryption的数据和解密它的软件,基本上没有办法让这个安全。 之前解决的方法是使用某种forms的外部黑盒来处理encryption/解密,如encryption狗,远程authentication服务器等。但即使如此,由于用户可以完全访问自己的系统,这只能使事情困难,并非不可能 – 无论如何,您可以将您的产品直接绑定到存储在“黑匣子”中的function,例如在线游戏服务器。
免责声明:我不是安全专家。
这听起来像一个坏主意:你让某人用你给他的一个“隐藏的”密钥来encryption。 我不认为这可以做到安全。
也许不对称的键可以工作:
- 使用公钥部署encryption的许可证进行解密
- 让客户创build一个新的许可证并发送给您进行encryption
- 发送新的许可证给客户端。
我不确定,但我相信客户端实际上可以使用您提供的公钥对许可证密钥进行encryption。 然后,您可以使用您的私钥解密并重新encryption。
您可以为每个客户保留一个单独的公钥/私钥对,以确保您实际上从正确的客户那里获得了东西 – 现在您要对钥匙负责。
不pipe你做什么,都可以“反编译”。 哎呀,你可以拆开它。 或者查看内存转储以查找常量。 你看,电脑需要知道他们,所以你的代码也需要。
该怎么办?
尽量不要将密钥作为代码中的硬编码常量发送:将其保存为每个用户的设置。 让用户负责照pipe该密钥。
看一看JavaWorld的文章,由Vladimir Roubtsov开发的Java字节码encryption 。 它解释了为什么类文件的encryption是毫无意义的。
@jatanp:或者更好的是,他们可以反编译,删除授权码,然后重新编译。 对于Java,我并不认为这个问题有适当的解决方法。 甚至连一个邪恶的小encryption狗都不能用Java来阻止这个。
我自己的经理人担心这一点,我想太多了。 但是,再次,我们把我们的应用程序卖给那些倾向于遵守许可条件的大公司,这通常是由于豆制品柜台和律师的安全的环境。 如果您的许可证正确写入,反编译本身的行为可能是非法的。
所以,我必须问,你是否真的需要加强保护,就像你正在寻找你的申请? 你的客户群是什么样的? (企业?还是青less年玩家群众,这在哪里会成为一个问题?)
我不认为有任何有效的离线反盗版方法。 video游戏产业多次试图find,他们的程序一直被破解。 唯一的解决scheme是,程序必须与您的服务器在线连接运行,以便您可以validationlincense密钥,并且一次只有被许可方的一个活动连接。 这是“ 魔兽世界”或“ 暗黑破坏神”的作品。 为了避开安全问题,开发专用服务器也非常困难。
话虽如此,我不相信大中型企业会使用非法复制的软件,因为这些软件的授权费用是最小的(也许我不知道您的程序要收费多less)一个试用版本的成本。
如果您正在寻找授权解决scheme,则可以查看TrueLicense API 。 它基于使用不对称的密钥。 但是,这并不意味着你的应用程序不能被破解。 每个应用程序都可以用足够的努力来破解。 正如斯图所说,真正重要的是要弄清楚你需要多大的保护。
您可以毫不畏惧地使用字节码encryption。
事实是,上面引用的文章“破解Java字节码encryption”包含一个逻辑谬误。 本文的主要要求是在运行之前,所有的类必须被解密并传递给ClassLoader.defineClass(...)
方法 。 但是这是错误的。
假设这里错过的假设是它们运行在真正的或标准的Java运行时环境中 。 没有什么可以强制受保护的Java应用程序不仅要启动这些类,但甚至解密并将它们传递给ClassLoader
。 换句话说,如果你在标准的JRE中,你不能拦截defineClass(...)
方法,因为标准的java没有为此目的的API,如果你使用修改后的ClassLoader
或任何其他“黑客技巧”不能这样做,因为受保护的Java应用程序根本无法工作,因此您将无法拦截。 而使用“修补程序查找程序”或黑客使用哪种技巧绝对无关紧要。 这些技术细节是一个完全不同的故事。
问:如果我encryption我的.class文件并使用自定义类加载器来dynamic加载和解密它们,这是否会阻止反编译?
答:防止Java字节码反编译的问题几乎和语言本身一样古老。 尽pipe市场上有一系列的混淆工具,新手的Java程序员仍然在思考如何保护自己的知识产权。 在这个Java Q&A系列文章中,我围绕一个经常在讨论论坛上重复讨论的想法打消了一些神话。
Java.class文件可以很容易地重构成与原始文件非常相似的Java源代码,这与Java字节码devise目标和折衷有很大关系。 除此之外,Java字节码是专为紧凑性,平台独立性,networking移动性以及易于通过字节码解释器和JIT(即时)/ HotSpotdynamic编译器进行分析而devise的。 可以说,编译后的.class文件清楚地expression了程序员的意图,他们可以比原始源代码更容易分析。
有几件事情可以做,如果不是防止反编译彻底,至less使其更难。 例如,作为后期编译步骤,您可以修改.class数据,以便在反编译时难以阅读字节代码,或者难以反编译为有效的Java代码(或两者)。 诸如执行极端方法名重载之类的技术对于前者来说工作得很好,并且操纵控制stream来创build不能通过Java语法来表示的控制结构对于后者来说工作良好。 更成功的商业混淆器使用这些和其他技术的混合。
不幸的是,这两种方法都必须改变JVM运行的代码,许多用户害怕(理所当然地)这种转换可能会给应用程序增加新的bug。 此外,方法和字段重命名可能导致reflection调用停止工作。 更改实际的类名称和包名称可能会破坏其他几个Java API(JNDI(Java命名和目录接口),URL提供程序等)。 除了更改的名称之外,如果更改类字节码偏移和源行号之间的关联,则恢复原始exception堆栈跟踪可能会变得困难。
然后,可以select混淆原始的Java源代码。 但从根本上讲,这也会导致类似的问题。 encryption,而不是混淆?
也许上面的内容让你想:“好吧,如果不是操作字节码,我会在编译后encryption所有的类,并在JVM中对它们进行解密(这可以使用自定义的类加载器来完成)?然后,JVM执行我的原始的字节码,但没有任何反编译或反向工程,对不对?
不幸的是,你会错误的,既认为你是第一个想出这个想法,并认为它实际上工作。 原因与您的encryptionscheme的优势无关。