#How to replace a string at runtime in a compiled .jar
44 messages · Page 1 of 1 (latest)
⌛ This post has been reserved for your question.
Hey @oblique dock! Please use
/closeor theClose Postbutton above when you're finished. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.
For example, when I try this:
import java.io.*;
import java.util.*;
import java.util.jar.*;
public class PlaceholderReplacer {
public static void main(String[] args) {
String inputJarPath = "path/to/input.jar";
String outputJarPath = "path/to/output.jar";
String placeholder = "your_placeholder";
String replacement = "your_replacement";
try {
replacePlaceholderInJar(inputJarPath, outputJarPath, placeholder, replacement);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void replacePlaceholderInJar(String inputJarPath, String outputJarPath, String placeholder, String replacement) throws IOException {
try (JarInputStream jarInputStream = new JarInputStream(new FileInputStream(inputJarPath));
JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(outputJarPath))) {
byte[] buffer = new byte[4096];
JarEntry entry;
while ((entry = jarInputStream.getNextJarEntry()) != null) {
String entryName = entry.getName();
if (entryName.endsWith(".class")) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bytesRead;
while ((bytesRead = jarInputStream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
byte[] classBytes = baos.toByteArray();
String modifiedContent = new String(classBytes).replace(placeholder, replacement);
byte[] modifiedBytes = modifiedContent.getBytes();
JarEntry modifiedEntry = new JarEntry(entryName);
modifiedEntry.setSize(modifiedBytes.length);
jarOutputStream.putNextEntry(modifiedEntry);
jarOutputStream.write(modifiedBytes);
jarOutputStream.closeEntry();
} else {
jarOutputStream.putNextEntry(entry);
int bytesRead;
while ((bytesRead = jarInputStream.read(buffer)) != -1) {
jarOutputStream.write(buffer, 0, bytesRead);
}
jarOutputStream.closeEntry();
}
}
}
}
}
My class that got replaced is now when I try to decompile: "java.lang.IllegalStateException: Wrong magic number: 3216895935
at com.strobel.assembler.metadata.ClassFileReader.readClass(ClassFileReader.java:338)
at com.strobel.assembler.metadata.MetadataSystem.resolveType(MetadataSystem.java:129)
at com.strobel.assembler.metadata.MetadataSystem.lookupTypeCore(MetadataSystem.java:86)
at com.strobel.assembler.metadata.MetadataResolver.lookupType(MetadataResolver.java:46)
at us.deathmarine.luyten.Model.openEntryByTreePath(Model.java:338)
at us.deathmarine.luyten.Model$TreeListener$1.run(Model.java:266)
"
consider using https://github.com/Col-E/Recaf/tree/dev3
Ias there any wiki or smth like that? Also not sure if I made clear, probably I should had specified, basically I have a compiled .jar and then i want to be able at runtime pick that .jar and replace (or inject a string/placeholder) into it, like an identifier
Not sure if the repo you are sending me will do that but let me know
oh so you want to do it programmatically
as in, load the jar into your program, modify the class, spit it back out
instead of modifying it manually
Oh yeah, like a script
thats right
Basically people will download from my website
the link i sent is to a bytecode manipulation tool, that you can use to modify it manually, among other things
I will inject their identifier
yeah I was trying stuff with that
the problem is that he is changing the size of the files
So it is actually replacing
but the file get corrupted or smth
because when I tried he gets me error and there are other files losing some bytes
usage is a bit complicated and i wont be able to explain it all, so all i can really do is link you to https://asm.ow2.io/ and wish you good luck
🥹 🥲
tho i do see what you did here and i can confidently say that it was a bad idea
strings are funny, especially so with encodings
Yeah I know, in that case actually I was doing new String() without nothing
class files are practically random bytes, the chance that an invalid utf8 sequence got into there is not small
But when I mention "ISO-8859-1"
it seems it preserves the actual size
but can't replace nothing on the file
you should replace it on the byte array directly itself
and even then, the size of the string is stored along with it
if you change the length of the string in this way, the resulting file will be invalid
yeah but I already mentioned, I'm getting an error, let me get the code