【创宇小课堂】代码审计-Javassist

  • A+
所属分类:代码审计

Javassist是一个开源的、用于分析、编辑和创建Java字节码的类库




Javassist的使用



Maven

<dependency>
 <groupId>org.javassist</groupId>

 <artifactId>javassist</artifactId>

 <version>3.25.0-GA</version>

</dependency>


jar

https://gitee.com/mirrors/Javassist.git





核心的类


ClassPool


含义如其名:Javassist的类池,使用ClassPool类可以跟踪和控制所操作的类,工作方式与JVM类装载器类似


该容器的键为类名称,值为CtClass对象


常用方法

static ClassPool getDefault()
// 返回默认的类池

ClassPath insertClassPath(java.lang.String pathname)

// 在搜索路径的开头插入目录或jar(或zip)文件

ClassPath insertClassPath(ClassPath cp)

// ClassPath在搜索路径的开头插入一个对象

java.lang.ClassLoader getClassLoader()

// 获取类加载器toClass(),getAnnotations()在 CtClass等

CtClass get(java.lang.String classname)

// 从源中读取类文件,并返回对CtClass 表示该类文件的对象的引用

ClassPath appendClassPath(ClassPath cp)

// 将ClassPath对象附加到搜索路径的末尾

CtClass makeClass(java.lang.String classname)

// 创建一个新的public类

CtClass


CtClass提供了对类的操作,如在类中添加新字段、方法和构造函数,改变父类和接口的方法等


一般一个CtClass类用于处理一个class文件,CtClass对象可以从ClassPool获得


常用方法

void setSuperclass(CtClass clazz)
// 更改超类,除非此对象表示接口

java.lang.Class<?> toClass(java.lang.invoke.MethodHandles.Lookup lookup)

// 将此类转换为java.lang.Class对象

byte[] toBytecode()

// 将该类转换为类文件

void writeFile()

// 将由此CtClass对象表示的类文件写入当前目录

void writeFile(java.lang.String directoryName)

// 将由此CtClass对象表示的类文件写入本地磁盘

CtConstructor makeClassInitializer()

// 制作一个空的类初始化程序(静态构造函数)

CtField



类的属性

通过该类可以修改类的属性,给类创建新的属性,还可以修改访问控制符等


常用方法

// 获取已知类的属性
CtField ctField = ctClass.getDeclaredField("name");

// 构建新的类的成员变量

CtField ctFieldNew = new CtField(CtClass.intType,"age",ctClass);

// 设置类的访问修饰符为public

ctFieldNew.setModifiers(Modifier.PUBLIC);

// 将属性添加到类中

ctClass.addField(ctFieldNew);

CtMethod



类的方法

通过该类可以修改类中的方法,给类创建新的方法,修改访问控制符,甚至还可以修改方法体的内容


常用方法

// 获取已有方法
// 创建新的方法, 参数1:方法的返回类型,参数2:名称,参数3:方法的参数,参数4:方法所属的类
CtMethod ctMethod = new CtMethod(CtClass.intType, "calc", new CtClass[] {CtClass.intType,CtClass.intType}, tClass);
// 设置方法的访问修饰
ctMethod.setModifiers(Modifier.PUBLIC);
// 将新建的方法添加到类中
ctClass.addMethod(ctMethod);
// 方法体内容代码 $1代表第一个参数,$2代表第二个参数
ctMethod.setBody("return $1 + $2;");

CtConstructor


类的构造方法,与CtMethod类似

ClassClassPath



获取类文件的搜索路径





测试类



编写一个测试类

javassistTest.java

package com.audit;
import javassist.ClassPool;

import javassist.CtClass;


import javassist.CtMethod;

import javassist.CtField;

import javassist.Modifier;

import javassist.CtNewMethod;

import javassist.CtConstructor;

public class javassistTest {

   public static void createt4rrega() throws Exception {

       // 创建一个ClassPool对象,用于后续创建类、字段、构造方法等

       ClassPool pool = ClassPool.getDefault();

       // 创建一个空类,makeClass的值为全类名

       CtClass ctClass = pool.makeClass("com.javassist.t4rrega");

       // 新增一个字段 private String name;

       // 字段名为name

       CtField param = new CtField(pool.get("java.lang.String"), "name", ctClass);

       // 修饰符是 private

       param.setModifiers(Modifier.PRIVATE);

       // 初始值是 "t4rrega"

       ctClass.addField(param, CtField.Initializer.constant("t4rrega"));

       // 生成 param参数的getter&setter方法

       ctClass.addMethod(CtNewMethod.setter("setName", param));

       ctClass.addMethod(CtNewMethod.getter("getName", param));

       // 添加类的无参的构造函数

       CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, ctClass);

       ctConstructor.setBody("{name = "t4rrega";}");

       ctClass.addConstructor(ctConstructor);

       // 添加有参的构造函数

       ctConstructor = new CtConstructor(new CtClass[]{pool.get("java.lang.String")}, ctClass);

       // $0=this / $1,$2,$3代表方法参数

       ctConstructor.setBody("{$0.name = $1;}");

       ctClass.addConstructor(ctConstructor);

       // 创建一个名为printName方法,无参数,无返回值,输出name值

       CtMethod ctMethod = new CtMethod(CtClass.voidType, "printName", new CtClass[]{}, ctClass);

       ctMethod.setModifiers(Modifier.PUBLIC);

       ctMethod.setBody("{System.out.println(name);}");

       ctClass.addMethod(ctMethod);

       // 将该类编译为class文件到指定目录下

       ctClass.writeFile("./");

   }

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

           createt4rrega();

   }

}


编译运行,生成的字节码文件如下

【创宇小课堂】代码审计-Javassist

【创宇小课堂】代码审计-Javassist

【创宇小课堂】代码审计-Javassist

原文始发于微信公众号(安全宇宙):【创宇小课堂】代码审计-Javassist

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: