在Java字节码(jar)中修改一个字符串

3

我想修改一个硬编码在Java应用程序中(没有源代码的jar)的连接字符串。

我猜想可以反编译jar,然后更改源代码并重新编译成新的jar,但有没有更快的方法?

编辑:

  • 这是一个独立的应用程序,不是我从自己的代码中加载的jar
  • 我怀疑它没有被混淆:它是一个小众科学应用程序,作者失踪了。
  • 一种在应用程序运行时“内存中”修改字符串的解决方案也可以满足要求,但不是理想的方法。
5个回答

10
在使用该jar的应用程序中,您可以使用反射来设置连接字符串。(即使是私有setter方法也可以使用反射)。
显然,如果setter是公共的,您可以直接调用它而无需使用反射。

1
我同意Bruno的观点,反射可能是解决这个问题最好的方法。你需要知道setter方法或成员变量,但如果你正在反编译或编辑字节码,那么你显然需要知道这些信息。 - bguiz
这是一个独立的应用程序,因此编程修改并不是我正在寻找的。 - pufferfish
1
请注意,使用反射修改字段可能不可靠。例如,如果该字段为public static final String,则编译器可能已将其作为常量内联。我不确定会发生什么,但这可能会发生... - sleske
2
关于这个问题,JavaSpecialists上有一个有趣的帖子(“疯狂的字符串”):http://www.javaspecialists.eu/archive/Issue014.html;另请参阅http://www.javaspecialists.eu/archive/Issue096.html(“'final'不再是最终版本”)。 - rhu

4
我认为反编译可能是最快的方法,前提是代码没有被混淆,以至于反编译/编译往返不可能。无论如何,您都需要反编译代码才能找到连接字符串,因此您已经完成了一半。
更重要的是,您可以利用这种方法将连接字符串提取到属性文件中,因此(希望)只需执行一次反编译操作!

哪个比特 - 查找字符串还是应用代码更改以从属性文件中读取?如果字符串容易获取(即未分段或混淆),则我认为从属性文件中读取不会很困难。 - Brian Agnew
我指的是反编译和重新编译。我记得一些混淆器使用像“new”、“class”等受保护的名称作为方法和字段名称。 - Stroboskop
@Stroboskop - 很有趣。我不知道那个。是的 - 上面的内容取决于能够往返。 - Brian Agnew
我认为这不是一个可行的解决方案... 我们不应该这样想。反思才是正确的方法。 - Suraj Chandran
@Suraj - 鉴于问题中的信息,为什么这不可行? - Brian Agnew

0

由于Jars经常不被压缩,因此地址以纯文本形式可见的可能性很小。您可以尝试使用一个不惧怕二进制数据的编辑器(我使用vim)来编辑Jar,并搜索和更改文本,前提是旧地址和新地址使用相同数量的字符。这是原始但非常简单的方法。

如果不起作用,您将需要其他方法。

当然,如果这种方法失败了,您会想要保留Jar的备份副本。


无论 Jar 文件是否被压缩,都没有关系;它只是 ZIP 压缩,只需使用任何 ZIP 工具解压缩并重新压缩即可。 - sleske

0

由于jar文件只是具有特定结构的ZIP文件,因此您可以使用zip工具(WinZip等)提取类文件;然后使用十六进制编辑器修改类文件(如果新连接字符串与旧连接字符串具有相同的长度,则不应太困难);之后,将其压缩回jar文件。

当然,当上述所有其他可能性都无法解决问题时,这应该只是您的最后一招。


0
我假设你已经考虑过这个问题了,但也许你可以简单地使用继承,如果.jar文件中编译的方法看起来像这样:

public String getConnectionString(){...

那么只需扩展该类,覆盖该方法以返回您的新字符串并使用您的类即可。显然,这仅在超类不是final、该方法不是final且它是public或protected(如果您可以使用相同的包名称)时才有效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接