IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java中javassist、ClassPool、CtClass、Apache CC2链学习 -> 正文阅读

[Java知识库]java中javassist、ClassPool、CtClass、Apache CC2链学习

1. 什么是javassist

javassist是一个处理Java字节码的jar包,里面有很多类。

2. 什么是ClassPool

可以想象成一个容器,里面放着指定路径下的class文件,使用javassist对类进行操作的时候,必须先创建一个ClassPool。

它也可以暂时存放我们编辑的class文件,等写完后再拿出来放到指定的位置。我们对class文件的操作是在ClassPool中的进行的。

假如我们想获取一个Class文件进行修改,如果ClassPool的路径中没有它,那么我们是找不到的,必须使用insertClassPath();函数将class文件路径导入ClassPool中才可以。

如果我们不自定义路径,那么它的类的搜索路径包括平台库、扩展库以及由-classpath选项或CLASSPATH环境变量指定的搜索路径。

3. 什么是CtClass

CtClass是javassist中的一个类文件,它的对象可以理解成一个class文件的抽象表示。

一个CtClass对象可以用来修改一个class文件。

4. 写一个Class文件test.class

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

import java.io.FileOutputStream;

public class JavasistTest {

    public static void main(String[] args) throws Exception{
        //默认的类搜索路径
        ClassPool pool = ClassPool.getDefault();

        //获取一个ctClass对象
        CtClass ctClass = pool.makeClass("Test");
        try {
            //添加age属性
            ctClass.addField(CtField.make("private int age;", ctClass));
            //添加setAge方法
            ctClass.addMethod(CtMethod.make("public void setAge(int age){this.age = age;}", ctClass));
            //添加getAge方法
            ctClass.addMethod(CtMethod.make("public int getAge(){return this.age;}", ctClass));
            //将ctClass生成字节数组,并写入文件
            byte[] byteArray = ctClass.toBytecode();
            FileOutputStream output = new FileOutputStream("/Users/zhujiayu/IdeaProjects/untitled/out/production/untitled/Test.class");
            output.write(byteArray);
            output.close();
            System.out.println("文件写入成功!!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
}
}

新创建好的test文件如图所示:
在这里插入图片描述

5. 修改这个写好了的test.class

我们先将test文件挪到桌面然后执行下面的代码,发现报错,找不到名为Test的class文件:
在这里插入图片描述

import javassist.ClassPool;
import javassist.CtClass;

public class Javassisttest2 {

    public static void main(String[] args) {
        ClassPool pool = ClassPool.getDefault();
        try {
            //pool.insertClassPath("/Users/zhujiayu/Desktop/");
            CtClass ctClass = pool.get("Test");
            System.out.println(ctClass.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DsGDABRF-1636626723011)(/Users/zhujiayu/Library/Application Support/typora-user-images/image-20211111183007259.png)]

然后我们将注释取消掉,再执行一遍,发现已经不报错了:

在这里插入图片描述


完整的修改代码:

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;

import java.io.FileOutputStream;

public class Javassisttest2 {

    public static void main(String[] args) {
        ClassPool pool = ClassPool.getDefault();
        try {
            pool.insertClassPath("/Users/zhujiayu/Desktop/");
            CtClass ctClass = pool.get("Test");
            System.out.println(ctClass.getName());


            if (ctClass.isFrozen()) {
                ctClass.defrost();
            }
            ctClass.addField(CtField.make("private String sex;", ctClass));
            ctClass.addField(CtField.make("private String name;", ctClass));
            //修改test.class的父类,可以理解成修改test.class的继承关系,下面是将AbstractTranslet类指定为test的父类
            ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName()));

            byte[] byteArray = ctClass.toBytecode();
            FileOutputStream output = new FileOutputStream("/Users/zhujiayu/IdeaProjects/untitled/out/production/untitled/Test.class");
            output.write(byteArray);
            output.close();
//
            System.out.println("文件修改成功!!!!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

修改后我们打开test.class查看发现代码确实被修改了
在这里插入图片描述

6. 加载类并获取类中的私有变量

import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;

public class Javassisttest2 {

    public static void main(String[] args) throws NotFoundException {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath("/Users/zhujiayu/Desktop/");
        try {
            CtClass ctClass = pool.get("Test");
            Class<?> c = ctClass.toClass(); //相当于执行了Classloader,执行后会将上一行指定的Test.class加载到JVM中
            //生成实例instance
            Object qq = c.newInstance();
            //利用反射调用实例中的函数
            System.out.println("通过getage函数获取的age的数据为:"+c.getDeclaredMethod("getAge",null).invoke(qq,null));
            //利用反射获取实例中的私有变量
            System.out.println("通过getDeclaredField函数获取的age的数据为:"+c.getDeclaredField("age").get(qq));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

7. 利用原始ClassLoader的方式配合javassist加载class文件

 import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;

import java.lang.reflect.Method;

public class Javassisttest2 {

    public static void main(String[] args) throws NotFoundException {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath("/Users/zhujiayu/Desktop/");
        try {
            CtClass ctClass = pool.get("Test");

            Class<?> clas = Class.forName("java.lang.ClassLoader");
            Method defineclass = clas.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
            defineclass.setAccessible(true);
            byte[] b = ctClass.toBytecode();
            Class c = (Class)defineclass.invoke(ClassLoader.getSystemClassLoader(), "Test", b, 0, b.length);
            //上面这5行就等于 Class<?> c = ctClass.toClass();

            Object qq = c.newInstance();


            System.out.println("通过getage函数获取的age的数据为:"+c.getDeclaredMethod("getAge",![在这里插入图片描述](https://img-blog.csdnimg.cn/59225d0d76304fd38ba381182b3fe962.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAU2hhbmZlbmdsYW43,size_20,color_FFFFFF,t_70,g_se,x_16)
null).invoke(qq,null));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

9. apache CC2链逻辑

  1. 利用javassist写恶意的class文件,恶意代码在这个class文件的构造函数下,并将其class文件转化为byte的格式。
  2. 通过创建一个TemplatesImpl对象,并给其中传入恶意参数,分别是将_bytecodes设置为恶意的class文件的byte数据,_name设置为name,_class设置为null。_tfactory设置为new TransformerFactoryImpl()。如果触发了TemplatesImpl对象的newTransformer方法会触发getTransletInstance(),getTransletInstance()方法会将class文件实例化,即可触发恶意的class文件中的构造函数,进而触发rce。
  3. 然后用反射创建一个InvokerTransformer对象,这个InvokerTransformer对象构造函数中的值是newTransformer,如果我们调用了invokerTransformer的transform函数,就会触发指定类的newTransformer函数,指定类是可控的
  4. 然后将InvokerTransformer对象传入TransformingComparator对象中,这个对象会变成TransformingComparator的tranformer参数的值。TransformingComparator的tranformer的transform函数会在执行TransformingComparatorcompare时被触发,compare函数的参数会被传给transform,接着被传给newTransformer接着会被传给getTransletInstance函数。综上,只要触发TransformingComparator的compara函数,就能触发rce。
  5. PriorityQueue类的readobject函数中有一个heapify函数,heapify函数中有一个siftdown函数,siftdown函数函数中有一个siftDownUsingComparator函数。siftDownUsingComparator函数中会调用PriorityQueue类中一个comparator对象的compare方法,compare方法的参数是PriorityQueue类的queue对象中的值。
  6. PriorityQueue类中的comparator的值,我们可以控制,PriorityQueue类的queue对象中的值我们也可以控制。
  7. 综上,我们创建一个PriorityQueue类的对象,并将TransformingComparator传给comparator,将恶意TemplatesImpl对象按照特定格式传给queue,然后将这个PriorityQueue对象进行序列化,传送给服务端等待被反序列化,反序列化时就会触发RCE攻击。

8. 参考文章

ClassPool CtClass浅析
Java动态编程初探——Javassist
Java反序列化-CommonsCollections2分析

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-12 19:27:07  更:2021-11-12 19:29:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:54:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码