Java .Class文件更改字符串

时间:2016-06-24 13:31:14

标签: java

我试图修改一个将#Gra;引力引擎关闭/打开的Minecraft mod(gravisuite)"每当我按F键,但是我想改变这个字符串,我开始更换" Gravitation Engine OFF"随着"引力引擎关闭"通过使用十六进制编辑器,但之后文件不再有效:/我尝试使用像jbe和cjbe和rej这样的工具,并且该字符串在常量池中,但它只会让我删除它...

有没有办法在不破坏它的情况下更改已编译的java类中的字符串?

由于

4 个答案:

答案 0 :(得分:2)

我通过一次小调整编译了同一个班级,首先是“foo”,然后是“foo-bar”

public class HelloWorld {
   public static final String HELLO = "foo-bar";
}

用“foo”

000000b0  74 01 00 **03** 66 6f 6f 00  21 00 02 00 03 00 00 00  |t...foo.!.......|
000000c0  01 00 19 00 04 00 05 00  01 00 06 00 00 00 02 00  |................|
000000d0  07 00 01 00 01 00 08 00  09 00 01 00 0a 00 00 00  |................|
000000e0  1d 00 01 00 01 00 00 00  05 2a b7 00 01 b1 00 00  |.........*......|
000000f0  00 01 00 0b 00 00 00 06  00 01 00 00 00 01 00 01  |................|
00000100  00 0c 00 00 00 02 00 0d                           |........|

用“foo-bar”

000000b0  74 01 00 **07** 66 6f 6f 2d  62 61 72 00 21 00 02 00  |t...foo-bar.!...|
000000c0  03 00 00 00 01 00 19 00  04 00 05 00 01 00 06 00  |................|
000000d0  00 00 02 00 07 00 01 00  01 00 08 00 09 00 01 00  |................|
000000e0  0a 00 00 00 1d 00 01 00  01 00 00 00 05 2a b7 00  |.............*..|
000000f0  01 b1 00 00 00 01 00 0b  00 00 00 06 00 01 00 00  |................|
00000100  00 01 00 01 00 0c 00 00  00 02 00 0d              |............|

似乎长度也在结构中编码。请注意3和7 ......有more information on this structure

如果字符串为300个字符,则前两个字节为01 2c。

所以鉴于“万有引力关闭”是29个字符长,我确保你把字符串前面的字节改为1D,它当前应该是19(“引力引擎关闭/开启”时为25个字符)< / p>

答案 1 :(得分:1)

您可以查看Apache BCEL (ByteCode Engineering Library)。它包含一个非常强大的类BCELifier。它是一个可以接受输入类的类,并且在执行时创建一个类,在编译和执行时,它创建输入类。

什么?

是。所以假设你有一个包含一些字符串的类,如下所示:

public class ClassContainingStrings
{
    private String someString = "Some string";
    public void call()
    {
        System.out.println("Printed string");
        System.out.println(someString);
    }
}

现在,您可以编译它,以获取ClassContainingStrings.class文件。此文件可以输入BCELifier,如下所示:

import java.io.FileOutputStream;

import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.util.BCELifier;


public class ChangeStringInClassFile
{
    public static void main(String[] args) throws Exception
    {
        String classFileName = "ClassContainingStrings.class";
        JavaClass c = new ClassParser(classFileName).parse();
        BCELifier b = new BCELifier(c, 
            new FileOutputStream("ClassContainingStringsCreator.java"));
        b.start();
    }
}

它将创建一个名为ClassContainingStringsCreator.java的文件。对于给定的示例,这将如下所示:

import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.*;
import java.io.*;

public class ClassContainingStringsCreator implements Constants {
  private InstructionFactory _factory;
  private ConstantPoolGen    _cp;
  private ClassGen           _cg;

  public ClassContainingStringsCreator() {
    _cg = new ClassGen("ClassContainingStrings", "java.lang.Object", "ClassContainingStrings.java", ACC_PUBLIC | ACC_SUPER, new String[] {  });

    _cp = _cg.getConstantPool();
    _factory = new InstructionFactory(_cg, _cp);
  }

  public void create(OutputStream out) throws IOException {
    createFields();
    createMethod_0();
    createMethod_1();
    _cg.getJavaClass().dump(out);
  }

  private void createFields() {
    FieldGen field;

    field = new FieldGen(ACC_PRIVATE, Type.STRING, "someString", _cp);
    _cg.addField(field.getField());
  }

  private void createMethod_0() {
    InstructionList il = new InstructionList();
    MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[] {  }, "<init>", "ClassContainingStrings", il, _cp);

    InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
    il.append(_factory.createInvoke("java.lang.Object", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
    InstructionHandle ih_4 = il.append(_factory.createLoad(Type.OBJECT, 0));
    il.append(new PUSH(_cp, "Some string"));
    il.append(_factory.createFieldAccess("ClassContainingStrings", "someString", Type.STRING, Constants.PUTFIELD));
    InstructionHandle ih_10 = il.append(_factory.createReturn(Type.VOID));
    method.setMaxStack();
    method.setMaxLocals();
    _cg.addMethod(method.getMethod());
    il.dispose();
  }

  private void createMethod_1() {
    InstructionList il = new InstructionList();
    MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[] {  }, "call", "ClassContainingStrings", il, _cp);

    InstructionHandle ih_0 = il.append(_factory.createFieldAccess("java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
    il.append(new PUSH(_cp, "Printed string"));
    il.append(_factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
    InstructionHandle ih_8 = il.append(_factory.createFieldAccess("java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
    il.append(_factory.createLoad(Type.OBJECT, 0));
    il.append(_factory.createFieldAccess("ClassContainingStrings", "someString", Type.STRING, Constants.GETFIELD));
    il.append(_factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
    InstructionHandle ih_18 = il.append(_factory.createReturn(Type.VOID));
    method.setMaxStack();
    method.setMaxLocals();
    _cg.addMethod(method.getMethod());
    il.dispose();
  }

  public static void main(String[] args) throws Exception {
    ClassContainingStringsCreator creator = new ClassContainingStringsCreator();
    creator.create(new FileOutputStream("ClassContainingStrings.class"));
  }
}

(是的,它看起来很可怕,但这不应该太重要)。重要的是,原始类中的字符串,即字符串"Some string""Printed string"可以在那里找到。现在,您可以更改这些字符串,然后编译并执行此创建者类。

它将使用修改后的字符串创建一个新的ClassContainingStrings.class

答案 2 :(得分:0)

一个jar文件是一个类的zip文件,我猜你已经知道了。你最好的方法是加载一个带有反编译器插件的java IDE(非常确定Intellij内置了这个)。一旦进行了反编译,您就可以更改生成的源并重新编译它。

这不是简单的java东西,但它也不是那么复杂。如果你之前做过一些java项目开发并不那么难。

答案 3 :(得分:0)

文件有校验和:

Archive:  dvt-utils.jar
Length   Method    Size  Ratio   Date   Time   CRC-32    Name
--------  ------  ------- -----   ----   ----   ------    ----
332  Defl:N      226  32%  11.05.31 19:41  a745ad09  META-INF/MANIFEST.MF