views:

502

answers:

5

I need to modify a connection string that's hard-coded into a Java application (jar without source).

I presume it's possible to decompile the jar, then change the source and recompile to a new jar, but is there perhaps a quicker way to do this?

EDIT:

  • It's a standalone application, not a jar I'm loading from my own code
  • I doubt it will have been obfuscated: scientific application, author AWOL.
  • A solution that entails modifying the string "in memory" while the app is running would also suffice, but is not ideal
+4  A: 

I think decompilation is probably the quickest way, provided the code hasn't been obfuscated such that a decompilation/compilation round-trip is not possible. You're going to have to decompile the code anyway to find the connection string, so you're half-way there already.

More importantly, you can take advantage of this method to pull the connection string out into a properties file, and hence (hopefully) only perform the decompilation once!

Brian Agnew
Unless of course the code was obfuscated.
Stroboskop
Which bit - finding the string or applying a code change to read from a properties file ? If the string is easily available (i.e. not fragmented or obfuscated) then I don't think reading from a properties file will be difficult.
Brian Agnew
I was referring to decompiling and re-compiling. I remember some obfuscators using protected names like "new", "class", etc. for method and field names.
Stroboskop
@Stroboskop - interesting. Wasn't aware of that. Yes - the above is dependent on being able to round trip
Brian Agnew
I think this is not a viable solutoin.... We should not think this way. Reflection is the way to go
Suraj Chandran
@Suraj - why isn't this viable, given the information in the question ?
Brian Agnew
The link to BCEL is informative, might want to leave it in
pufferfish
+8  A: 

In your application that uses that jar, you could use reflection to set the connection String. (Reflection can be used even with private setters).

Obviously, if the setter is public, you could just call it without reflection.

Bruno Rothgiesser
I agree with Bruno, reflection is possiblity the best solution there is to this problem. You would need to know the setter method or member variable, but you obv. need to know that anyway if you are decompiling or editing the bytecode.
bguiz
It's a standalone app, so programmatic modification is not quite what I'm looking for
pufferfish
Beware that reflection to modify fields may not work reliably. E.g. if the field is a `public static final String`, it may have been inlined as a constant by the compiler. I'm not sure it happens, but it might...
sleske
There's an interest post ('Insane Strings') on JavaSpecialists regarding this: http://www.javaspecialists.eu/archive/Issue014.html;Also see http://www.javaspecialists.eu/archive/Issue096.html ('"final" is not final anymore').
rhu
A: 

Since Jars are often not compressed, there's a small chance that the address will be visible as plain text in the Jar. You could try editing the Jar with an editor that's not afraid of binary data (I use vim) and just search for and change the text, provided the old address and the new use the same number of characters. That's primitive but very simple.

If it doesn't work, you'll need one of the other approaches.

Of course you'll want to keep a backup copy of the jar in case this approach fails.

Carl Smotricz
sleske
A: 

Since jar files are simply ZIP-Files with a certain structure, you can use a zip tool (WinZip etc.) to extract the class files; then you use a hex editor to modfiy the class files (should not be too difficult if the new connection string has the same length like the old one); after that, you zip it back into the jar file.

Of course this should only be your last-ditch attempt when all the other possibilities described above don't work.

ammoQ
A: 

I assume you already thought of this, but maybe you could simply use inheritance, if the compiled method in the .jar file looks something like this:

public String getConnectionString(){...

then just extend the class, override the method to return your new string and use your class instead. Obviously this only works if the super class is not final, the method is not final, and it's public or protected (if you can use the same package name).

zuki