Dynamically generated classes of Java reverse foundation

Why is there such a thing? On the one hand, it is needed by the AOP framework, and on the other hand, it increases the difficulty of software reverse engineering

The technology of dynamically generating classes is generally divided into two categories at present, one is realized by operating bytecode framework such as cglib/ Javassist, and the other is JNI method, which calls dll/so library and restores dynamically in memory. Both methods can implement hidden classes

See an example of Javassist dynamically generating classes

package com.vvvtimes;

import java.lang.reflect.Modifier;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;

public class DynamicGenerateClass {

	public static void main(String[] args) throws Exception {

		// ClassPool: container for CtClass objects
		ClassPool pool = ClassPool.getDefault();

		// Generate a new public class Employee.java through ClassPool
		CtClass ctClass = pool.makeClass("com.vvvtimes.bean.Employee");

		// add fields
		// First add the field private String ename
		CtField enameField = new CtField(pool.getCtClass("java.lang.String"), "ename", ctClass);
		enameField.setModifiers(Modifier.PRIVATE);
		ctClass.addField(enameField);

		// Next, add the field privtae int eage
		CtField eageField = new CtField(pool.getCtClass("int"), "eage", ctClass);
		eageField.setModifiers(Modifier.PRIVATE);
		ctClass.addField(eageField);

		// Next, add the field privtae int eage
		CtField esexField = new CtField(pool.getCtClass("int"), "esex", ctClass);
		esexField.setModifiers(Modifier.PRIVATE);
		ctClass.addField(esexField);

		// Add getter and setter methods for fields ename and eno
		ctClass.addMethod(CtNewMethod.getter("getEname", enameField));
		ctClass.addMethod(CtNewMethod.setter("setEname", enameField));
		ctClass.addMethod(CtNewMethod.getter("getEage", eageField));
		ctClass.addMethod(CtNewMethod.setter("setEage", eageField));
		ctClass.addMethod(CtNewMethod.getter("getSex", esexField));
		ctClass.addMethod(CtNewMethod.setter("setSex", esexField));

		// add constructor
		CtConstructor ctConstructor = new CtConstructor(new CtClass[] {}, ctClass);
		// set the function body for the constructor
		StringBuffer buffer = new StringBuffer();
		buffer.append("{\n").append("ename=\"gsls200808\";\n").append("eage=25;\n").append("esex=1;\n}");
		ctConstructor.setBody(buffer.toString());
		// add the constructor to the new class
		ctClass.addConstructor(ctConstructor);

		// add custom method
		CtMethod ctMethod = new CtMethod(CtClass.voidType, "printInfo", new CtClass[] {}, ctClass);
		// set the modifier for the custom method
		ctMethod.setModifiers(Modifier.PUBLIC);
		// Set the function body for the custom method
		StringBuffer buffer2 = new StringBuffer();
		buffer2.append("{\n").append("System.out.println(\"begin!\");\n")
				.append("System.out.println(\"name=\"+ename);\n").append("System.out.println(\"age=\"+eage);\n")
				.append("System.out.println(\"sex=\"+esex);\n").append("System.out.println(\"end!\");\n").append("}");
		ctMethod.setBody(buffer2.toString());
		ctClass.addMethod(ctMethod);

		// In order to verify the effect, the following uses reflection to execute the method printInfo
		Class<?> clazz = ctClass.toClass();
		Object obj = clazz.newInstance();
		obj.getClass().getMethod("printInfo", new Class[] {}).invoke(obj, new Object[] {});

	}
}

Third-party jars that need to be referenced: javassist-3.20.0-GA.jar

operation result

begin!
name=gsls200808
age=25
sex=1
end!

The meaning of the code is equivalent to creating a class named com.vvvtimes.bean.Employee in memory, and calling the printInfo method for output through reflection.


The content of this class is roughly as follows, but we are dynamically generated above

package com.vvvtimes.bean;

import java.io.PrintStream;

public class Employee
{
  private String ename = "gsls200808";
  private int eage = 25;
  private int esex = 1;
  
  public String getEname()
  {
    return this.ename;
  }
  
  public void setEname(String paramString)
  {
    this.ename = paramString;
  }
  
  public int getEage()
  {
    return this.eage;
  }
  
  public void setEage(int paramInt)
  {
    this.eage = paramInt;
  }
  
  public int getSex()
  {
    return this.esex;
  }
  
  public void setSex(int paramInt)
  {
    this.esex = paramInt;
  }
  
  public void printInfo()
  {
    System.out.println("begin!");
    System.out.println("name=" + this.ename);
    System.out.println("age=" + this.eage);
    System.out.println("sex=" + this.esex);
    System.out.println("end!");
  }
}

In a follow-up article we will talk about how to get the class in memory

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324718793&siteId=291194637