2016-06-24 15 views
5

Tôi đang cố gắng sửa đổi một mod minecraft (gravisuite) đặt "Gravitation Engine OFF/ON" bất cứ khi nào tôi nhấn F, tuy nhiên tôi muốn thay đổi chuỗi này, tôi bắt đầu thay thế "Gravitation Engine OFF "with" Gravitation Engine Turn OFF "bằng cách sử dụng một trình soạn thảo hex nhưng tập tin không còn hợp lệ sau đó:/Tôi đã cố gắng sử dụng các công cụ như jbe và cjbe và rej và chuỗi đó nằm trong nhóm không đổi nhưng nó sẽ chỉ cho phép tôi xóa nó ...Java .Class thay đổi tập tin chuỗi

Có cách nào để thay đổi chuỗi trong lớp java đã biên dịch mà không phá hủy nó không?

Cảm ơn

+0

Tôi muốn bắt đầu tìm thông số về định dạng nhị phân của tệp .class và hiểu cách chuỗi được biểu diễn, có thể là trường có kích thước trước chuỗi thực tế, có lẽ ...? – Adam

+1

Thử "Grav Engine Turn OFF/ON" = cùng số byte (chế độ ghi đè). –

+0

@ user265889 Có câu trả lời nào của chúng tôi giải quyết được sự cố của bạn không? – Adam

Trả lời

2

tôi biên soạn cùng lớp hai lần với một tinh chỉnh nhỏ, trước hết là với "foo" và sau đó với "foo-bar"

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

Với "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       |........| 

Với "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    |............| 

Dường như độ dài cũng được mã hóa trong cấu trúc. Lưu ý 3 và 7 ... Có more information on this structure

Và với một chuỗi gồm 300 ký tự, hai byte trước đó là 01 2c.

Vì vậy, đã cho "Gravitation Engine Turn OFF" dài 29 ký tự, tôi đảm bảo bạn thay đổi byte ngay trước chuỗi thành 1D, hiện tại là 19 (25 ký tự cho "Gravitation Engine OFF/ON")

0

Tệp jar là tệp zip của các lớp, tôi đoán bạn đã tìm ra điều đó. Tốt nhất của bạn là để tải lên một java IDE với một addon decompiler (khá chắc chắn Intellij đã được xây dựng trong này). Khi bạn đã giải mã xong, bạn có thể thay đổi nguồn được tạo và biên dịch lại.

Đây không phải là công cụ java tầm thường, nhưng nó cũng không quá phức tạp. Nếu bạn đã thực hiện một số dự án phát triển java trước khi nó không quá khó.

0

Có checksums cho các tập tin:

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 
0

Bạn có thể có một cái nhìn tại Apache BCEL (ByteCode Engineering Library). Nó chứa một lớp học mạnh mẽ đáng chú ý được gọi là BCELifier. Nó là một lớp có thể lấy một lớp đầu vào, và, khi được thực hiện, tạo ra một lớp, khi được biên dịch và thực thi, tạo ra lớp đầu vào.

Cái gì?

Có. Vì vậy, hãy tưởng tượng bạn có một lớp có chứa một số chuỗi, như thế này:

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

Bây giờ, bạn có thể biên dịch này, để có được những tập tin ClassContainingStrings.class. Tập tin này có thể được đưa vào BCELifier, như thế này:

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(); 
    } 
} 

Nó sẽ tạo ra một tập tin gọi ClassContainingStringsCreator.java. Đối với ví dụ đã cho, điều này sẽ trông giống như sau:

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")); 
    } 
} 

(vâng, có vẻ khủng khiếp, nhưng điều đó không quan trọng quá nhiều).Điều quan trọng là các chuỗi từ lớp gốc, cụ thể là chuỗi "Some string""Printed string" có thể được tìm thấy trong đó. Bây giờ, bạn có thể thay đổi các chuỗi này, sau đó biên dịch và thực thi lớp người tạo này.

Nó sẽ tạo một ClassContainingStrings.class mới, với các chuỗi đã sửa đổi.

Các vấn đề liên quan