Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change string constant in a compiled class

I need to change a string constant in a deployed Java program, i.e. the value inside the compiled .class-files. It can be restarted, but not easily recompiled (though it's an inconvenient option if this question yields no answers). Is this possible?

Update: I just looked at the file with a hex editor and it looks like I can easily change the string there. Would that work, i.e. won't that invalidate some kind of signature of the file? The old and new string are both alphanumeric, and can be the same length if needed.

Update 2: I fixed it. Because the specific class I needed to change is very small and didn't change in the new version of the project, I could just compile that and take the new class from there. Still interested in an answer that doesn't involve compilation though, for educational purposes.

like image 259
Bart van Heukelom Avatar asked May 21 '12 08:05

Bart van Heukelom


People also ask

How do you resolve a constant string too long?

The best way is to store our string in a separate file instead of in a declared variable or constant. Of course, we could also introduce concatenation with our string, but such isn't recommended. If we have such a long string, our Java files are likely not the best home for it anyway.

How do you declare a string constant in C++?

To define a string constant in C++, you have to include the string header library, then create the string constant using this class and the const keyword.

How do you declare a string a constant in Java?

Syntax to assign a constant value in java:static final datatype identifier_name = constant; The static modifier causes the variable to be available without an instance of it's defining class being loaded. The final modifier makes the variable unchangeable.

Can a string be constant?

A String Literal, also known as a string constant or constant string, is a string of characters enclosed in double quotes, such as "To err is human - To really foul things up requires a computer." String literals are stored in C as an array of chars, terminted by a null byte.


2 Answers

If you have the sources for this class, then my approach is:

  • Get the JAR file
  • Get the source for the single class
  • Compile the source with the JAR on the classpath (that way, you don't have to compile anything else; it doesn't hurt that the JAR already contains the binary). You can use the latest Java version for this; just downgrade the compiler using -source and -target.
  • Replace the class file in the JAR with the new one using jar u or an Ant task

Example for an Ant task:

        <jar destfile="${jar}"
            compress="true" update="true" duplicate="preserve" index="true"
            manifest="tmp/META-INF/MANIFEST.MF"
        >
            <fileset dir="build/classes">
                <filter />
            </fileset>
            <zipfileset src="${origJar}">
                <exclude name="META-INF/*"/>
            </zipfileset>
        </jar>

Here I also update the manifest. Put the new classes first and then add all the files from the original JAR. duplicate="preserve" will make sure that the new code will not be overwritten.

If the code isn't signed, you can also try to replace the bytes if the new string has the exact same length as the old one. Java does some checks on the code but there is no checksum in the .class files.

You must preserve the length; otherwise the class loader will get confused.

like image 76
Aaron Digulla Avatar answered Oct 26 '22 22:10

Aaron Digulla


The only extra data required when modifying a string (technically a Utf8 item) in the constant pool is the length field (2 bytes big endian preceding the data). There are no additional checksums or offsets that require modification.

There are two caveats:

  • The string may be used in other places. For example "Code" is used for a method code attribute, so changing it would break the file.
  • The string is stored in Modified Utf8 format. So null bytes and unicode characters outside the basic plane are encoded differently. The length field is the number of bytes, not characters, and is limited to 65535.

If you plan to do this a lot, it's better to get a class file editor tool, but the hex editor is useful for quick changes.

like image 28
Antimony Avatar answered Oct 26 '22 22:10

Antimony