Modify the jar in the class: the killing minaret modify Tutorial

origin

As a program ape, the game is naturally standard. Since the killings steeple pit, several years after another to play hundreds of hours. However, the achievements so far no steam brushing, the dealer and the brightest in the bottom in mobs against me. In the first n n {n^n} After leading advanced three times died mobs hands of 20, I felt the renunciation ofanger.
So I decided to use technicalhateit.

Thinking

Killing minaret is java development, its main program is a .jar file. Now we want to modify armored warrior foundation card: blow.
Here Insert Picture Description
Base damage hit is 6, the goal is to change it to 60.

  1. Use Java Decompiler decompile the .jar file, find the target class file and object code.
  2. Use jclasslib of byecode viewer or plug-analysis target class file, locate the code on the target.
  3. Create a java project, introduced jclasslib jar package, load the target class file and make changes.
  4. It will eventually replace the generated .jar file to the new class in the main program.

analysis

Java Decompiler decompile

Open the game directory, you can see a Desktop-1.0.jar . This is the main game.
The first to use Java Decompiler decompile. Open jd-gui, the desktop-1.0.jar dragged come:
Here Insert Picture Description
As above, go to the directory:

desktop-1.0\com\megacrit\cardcrawl\cards\red\

This is a card catalog, red that is red, which is armored warrior red card.
The first file called Anger.class , is angry. We look down, you can find the file to Strike_Red.class , from the name of view, which is looking for a fight.
Here Insert Picture Description
After selecting the right you can see the source, which has this constructor line of code:

this.baseDamage = 6;

This line of code sets the base damage hit is 6. Our goal is to modify it to 60.
However, Java Decompiler can only see the results after the decompiled class files, and can not be modified.
And because the class file importa number of libraries, can not directly use the javac command to compile a single file. So we need the help of jclasslib.

jclasslib byecode viewer analysis class file

Use winrar to game directory desktop-1.0.jar decompress.
Here Insert Picture Description
As already positioned Strike_Red.class path. In the decompression desktop-1.0.jar find the folder in which the generated class file, open jclasslib byecode viewer, drag the class room.
Here Insert Picture Description
You can see here is the structure of the Java Virtual Machine to view the class file. This part can refer to the "Java Virtual Machine Specification."
The left Constatnt Pool i.e. constant pool, Methods i.e. methods.
By the previous analysis, the content is located to modify the constructor.
Then open the Methods , under the element number 0 <init> i.e. constructor.
Here Insert Picture Description
Note that the right side of the above information, contains two important elements:

  • Name: <init>
  • Description: () V

Open <init>, the number 0 is its property Code (very important) , which is the code for the constructor. Click Code , you can view the specific implementation in the right panel:
Here Insert Picture Description

Similarly, Generic info upper right side contains an important message:

  • Attribute name index: cp_info #58

Wherein # 58 refers to the index position number 58 in the constant pool. Its name is called the Attribute name index .
Below right is the virtual machine code constructor. Inside the instruction stack means and the variable and constant Scale Table various operations. We need to care about what behavior is variable assignment 6.
Obviously, the code can be seen as follows:

27 aload_0
28 bipush 6
30 putfield #11 <com/megacrit/cardcrawl/cards/red/Strike_Red.baseDamage>

The key is in the middle of 28 bipush 6. The meaning of this line of code is:

  • The start instruction code from the index No. 28.
  • Drawing instructions to an int.
  • Drawing 6 is an int.

At the same time be clear:

  • code is a byte as a unit.
  • Each one byte instruction, such as here bipush.
  • Referring next line of code, the apparent line 2 bytes, i.e., 28 and 29.

Will be treated as a byte array code, i.e. code index 28 [28], the contents of bipushthe instruction. code [29] is pushed onto the stack 6 int value.
Thus, if we can get the code [29], and can be modified as 60.
Note that only the value pushed onto the stack 1 byte int, and unsigned number, and therefore it should not exceed 127
byecode viewer can only be viewed, can not be modified.

modify

To modify the class files in two ways:

  1. With binary file modification tool.
  2. Create a java project, the use of third-party libraries.

For Embodiment 1, it appears to be simple, direct analysis of the actual needs of the hexadecimal value of the code, and taking into account the alignment byte file encryption and so on.
For Mode 2, requires the use of third-party libraries. The third-party libraries must be integrated into java use. Therefore we need to create a java project.

Here use 2. Therefore first open Intellij IDEA, create a new JBoss project.

Dependent libraries installation

java commonly used to modify the contents of the file class library has two: jclasslib and javassist.

  • jclasslib: to assemble a virtual machine by way of class to see the contents of the file, and can be modified to provide a jar file to class.
  • javassist: commonly used in dynamic programming.

Mounting two libraries follows. Benpian using jclasslib be modified.

Installation jclasslib

Download and install

Open jclasslib official github for download:

https://github.com/ingokegel/jclasslib/releases

Here select install exe version. Install after downloading.
Here Insert Picture Description

After installation, lib directory jar package necessary for all, the need to clip into the project file as modified class-dependent.

Import dependence to the project

Open:
File→Project Structure...
the left selection Modules, selecting the right Dependencies tab ** + ** rightmost point number, select JARs or Directories ... , in a pop-up window select jclasslib lib installation directory under the file folder.
Here Insert Picture Description

Installation javassist

Download and install

Open the official github javassist download:

http://www.javassist.org/

After downloading a zip archive, unzip and copy to the specified directory.

Import dependence to the project

Open:
File→Project Structure...
Left Selection Modules, on the right select the Dependencies tab rightmost point + number, select JARs Directories ... or , in the pop-up window, select the directory under javassist javassist.jar file.

Modify class

Ready to work

  1. Create a Test folder on the desktop, and Strike_Red.class copy here.
  2. Create a Change folder to store generated after modification in the Test folder Strike_Red.class file.

Programming is changed and saved

Implementation code:

import org.gjt.jclasslib.io.ClassFileWriter;
import org.gjt.jclasslib.structures.AttributeInfo;
import org.gjt.jclasslib.structures.ClassFile;
import org.gjt.jclasslib.structures.MethodInfo;
import org.gjt.jclasslib.structures.attributes.CodeAttribute;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        String filePath = "C:\\Users\\Administrator\\Desktop\\Test\\Strike_Red.class";
        FileInputStream fis = new FileInputStream(filePath);
        DataInput di = new DataInputStream(fis);

        ClassFile cf = new ClassFile();
        cf.read(di); // 载入类文件数据

        // 获取构造函数
        MethodInfo mi = cf.getMethod("<init>", "()V");
        // 方法的所有属性
        AttributeInfo[] attributes = mi.getAttributes();
        // 0号属性为Code
        CodeAttribute codeAttribute = (CodeAttribute)attributes[0];

        byte[] code = codeAttribute.getCode();  // 获取Code的二进制内容
        code[29] = 60;  // 修改29号索引内容
        codeAttribute.setCode(code);    // 重设方法的Code内容

        fis.close();
        // 保存修改后的ClassFile
        File f = new File("C:\\Users\\Administrator\\Desktop\\Test\\Change\\Strike_Red.class");
        ClassFileWriter.writeToFile(f, cf);
    }
}

The whole idea is:

  1. Create a ClassFile, will come loaded class files.
  2. 获取构造函数,存放到一个MethodInfo对象中。这里用到的参数为构造函数的NameDescriptor,前面的分析已经得知这两个值。
  3. 获取构造函数所有的属性。0号属性即为Code,前面已经分析过。将获取到的0号属性转换为CodeAttribute
  4. 获取Code的二进制内容,是一个byte数组。要修改的内容位于29号索引,将其修改为60。这里若修改为>127的值IDEA会提示错误。
  5. 将修改后的Code设置回构造函数的属性中。于是构造函数内容被修改,也就是当前ClassFile被修改。
  6. 将修改后的ClassFile保存在Test/Change下。

运行后,即会在Test/Change下生成Strike_Red.class文件。
将这个生成的文件拖入到Byecode viewer中,查看构造函数的Code,可以看到baseDamage已经修改为60:
Here Insert Picture Description

替换

Now we need to Strike_Red.class replace back Desktop-1.0.jar .
First Java Decompiler and Byecode viewer are closed to prevent the file being opened for modification.
Then open with WinRar Desktop-1.0.jar (not open decompression), find Strike_Red.class path where:
COM \ megacrit \ cardcrawl \ Cards \ Red
will be modified in the previous step generated Strike_Red.class direct drag in, replaced.
This amendment is complete. Run the game look:
Here Insert Picture Description

It’s Hammer Time!

Published 215 original articles · won praise 51 · views 160 000 +

Guess you like

Origin blog.csdn.net/fyyyr/article/details/102380590