java安全必学之Javassist 学习

Javassist 学习

环境搭建

这个非常简单,只需要你自己加一个依赖

<!-- https://mvnrepository.com/artifact/javassist/javassist -->
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.12.1.GA</version>
        </dependency>

简单了解

Java programming ASSISTant,Java编程助手。是Java中编辑字节码的类库,它使Java程序能够在运行时定义一个新类,并在JVM加载时修改类文件。

Java中所有的类都被编译为class文件来运行,在编译完class文件之后,类不能再被显示修改,而Javassist就是用来处理编译后的class文件,它可以用来修改方法或者新增方法,并且不需要深入了解字节码,还可以生成一个新的类对象。

ClassPool这个类是javassist的核心组件之一。ClassPool是CtClass对象容器,CtClass对象必须从该对象获得。

一些基础的语法

从上文的demo中可以看到部分使用方法,在javassist中CtClass代表的就是类class,ClassPool就是CtClass的容器,ClassPool维护了所有创建的CtClass对象,需要注意的是当CtClass数量过大会占用大量内存,需要调用CtClass.detach()释放内存。

ClassPool重点有以下几个方法:

  1. getDefault() 单例获取ClassPool
  2. appendClassPath() 将目录添加到ClassPath
  3. insertClassPath() 在ClassPath插入jar
  4. get() 根据名称获取CtClass对象
  5. toClass() 将CtClass转为Class 一旦被转换则不能修改
  6. makeClass() 创建新的类或接口

更多移步官方文档:http://www.javassist.org/html/javassist/ClassPool.html

CtClass需要关注的方法:

  1. addConstructor() 添加构造函数
  2. addField() 添加字段
  3. addInterface() 添加接口
  4. addMethod() 添加方法
  5. freeze() 冻结类使其不能被修改
  6. defrost() 解冻使其能被修改
  7. detach() 从ClassPool中删除类
  8. toBytecode() 转字节码
  9. toClass() 转Class对象
  10. writeFile() 写入.class文件
  11. setModifiers() 设置修饰符

移步:http://www.javassist.org/html/javassist/CtClass.html

CtMethod继承CtBehavior,需要关注的方法:

  1. insertBefore 在方法的起始位置插入代码
  2. insterAfter 在方法的所有 return 语句前插入代码
  3. insertAt 在指定的位置插入代码
  4. setBody 将方法的内容设置为要写入的代码,当方法被 abstract修饰时,该修饰符被移除
  5. make 创建一个新的方法

简单使用

创建class

package javassist;

import java.io.IOException;

public class Create {
    public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException {
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.makeClass("javassist.Person");

        // 添加字段
        CtField name = new CtField(pool.get("java.lang.String"), "name", cc);
        name.setModifiers(Modifier.PRIVATE);
        cc.addField(name, CtField.Initializer.constant("LJL"));

        CtField age = new CtField(pool.get("int"), "age", cc);
        age.setModifiers(Modifier.PRIVATE);
        cc.addField(age, CtField.Initializer.constant(18));

        // 添加getter和setter方法
        cc.addMethod(CtNewMethod.getter("getName", name));
        cc.addMethod(CtNewMethod.getter("getAge", age));
        cc.addMethod(CtNewMethod.setter("setName", name));
        cc.addMethod(CtNewMethod.setter("setAge", age));

        // 添加构造函数
        CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);
        cons.setBody("{name = \"nn0nkey\";}");
        cc.addConstructor(cons);

        CtConstructor cons1 = new CtConstructor(new CtClass[]{pool.get("java.lang.String"), pool.get("int")}, cc);
        cons1.setBody("{name = $1; age = $2;}");
        cc.addConstructor(cons1);

        // 添加toString方法
        CtMethod toString = new CtMethod(pool.get("java.lang.String"), "toString", new CtClass[]{}, cc);
        toString.setModifiers(Modifier.PUBLIC);
        toString.setBody("{return \"name: \" + name + \", age: \" + age;}");
        cc.addMethod(toString);

        // 将类写入文件
        cc.writeFile("F:\\IntelliJ IDEA 2023.3.2\\java脚本\\CC1_5_6_7\\target\\classes");
    }
}

需要注意的是在setBody()中我们使用了$符号代表参数

// $0代表this $1代表第一个传入的参数 类推
printName.setBody("{System.out.println($0.name);}");

body中代码该怎么写就怎么写

我们运行就可以生成我们的class文件

image-20240624164859703

还是非常完美的

使用CtClass对象

这里一共有三种方法

反射调用
public class Useit {
    public static void main(String[] args) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
		ClassPool classPool=ClassPool.getDefault();
        CtClass cc=classPool.get("javassist.Person");
        Object person = cc.toClass().newInstance();
        Method setName=person.getClass().getDeclaredMethod("setName",String.class);
        setName.setAccessible(true);
        setName.invoke(person,"k1n9");
        Method tostring=person.getClass().getMethod("toString");
        Object result = tostring.invoke(person);
        System.out.println(result);
    }
}

看代码就很容易看明白就是获取class后实例化,然后步骤就和反射一样了

加载class文件

这个和上面只能说大差不差,就是修改了获取class的方法

ClassPool pool = ClassPool.getDefault();
        pool.appendClassPath("F:\\IntelliJ IDEA 2023.3.2\\java脚本\\CC1_5_6_7\\target\\classes");
// 获取上面生成的类
        CtClass ctClass = pool.get("javassist.Person");
Object person = ctClass.toClass().newInstance();
//  ...... 下面和通过反射的方式一样去使用

需要注意的点是appendClassPath中填入目录,不要具体的文件

通过接口的方式

这个方法是最方便的,因为反射确实太麻烦;我们考虑为该类写一个接口

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package javassist;

public interface PersonI {
    void setName(String var1);

    void setAge(int var1);

    String getName();

    int getAge();

    String toString();
}

然后我们只需要为我们的类实现这个接口,就可以直接调用这个方法了

ClassPool pool = ClassPool.getDefault();
        pool.appendClassPath("F:\\IntelliJ IDEA 2023.3.2\\java脚本\\CC1_5_6_7\\target\\classes");


// 获取接口
        CtClass codeClassI = pool.get("javassist.PersonI");
// 获取上面生成的类
        CtClass ctClass = pool.get("javassist.Person");
// 使代码生成的类,实现 PersonI 接口
        ctClass.setInterfaces(new CtClass[]{codeClassI});

// 以下通过接口直接调用 强转
        PersonI person = (PersonI)ctClass.toClass().newInstance();
        System.out.println(person.getName());
        person.setName("llll");
        System.out.println(person.toString());

需要注意的就是一定要强转

修改现有的类对象

这个也是我们在实战中比较好用的一个方法

比如我们修改我们的toString方法

package javassist;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.CannotCompileException;

import java.io.IOException;

public class Refresh {
    public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException {
        ClassPool pool = ClassPool.getDefault();
        // 获取 Person 类
        CtClass person = pool.getCtClass("javassist.Person");

        // 获取 toString 方法
        CtMethod toString =new CtMethod(pool.get("java.lang.String"), "toString", new CtClass[]{}, person);

        // 修改 toString 方法的函数体
        toString.setBody("{return \"Are you joker?\";}");

        // 将修改后的类写入文件(可选)
        person.writeFile("F:\\IntelliJ IDEA 2023.3.2\\java脚本\\CC1_5_6_7\\target\\classes");
    }
}

image-20240624171244614

也是成功了好吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/740444.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

光伏能源圈

2021年&#xff0c;新型电力系统之下&#xff0c;中国已形成了两网五大六小的电力新格局&#xff1a; 两大电网&#xff1a;国家电网、南方电网 五大电力央企&#xff1a;国家能源投资集团、中国华能集团、中国华电集团、中国大唐集团、国家电力投资集团。 六小豪门&#xf…

使用Leaflet和瓦片地图实现离线地图的技术指南

引言 在现代的Web应用中&#xff0c;地图服务扮演着越来越重要的角色。然而&#xff0c;在一些特殊环境下&#xff0c;如偏远地区或网络环境不稳定的情况下&#xff0c;依赖在线地图服务可能会受到限制。因此&#xff0c;实现离线地图功能成为了一个重要的需求。本文将介绍如何…

MoonBit 周报 Vol.46:支持32位无符号整数!

MoonBit 更新 支持了 32 位无符号整数 let num 100U // 32位无符号整数的字面量需要后缀U在 wasm 后端导出返回值类型为 Unit 的函数时&#xff0c;之前导出函数的类型中会有 (result i32)&#xff0c;现在 MoonBit 编译器会自动生成一个没有返回值 wrapper 函数&#xff0c…

【漏洞复现】通天星CMSV6车载定位监控平台 point_manage/merge SQL注入致RCE

0x01 产品简介 通天星CMSV6车载定位监控平台拥有以位置服务、无线3G14G视频传输、云存储服务为核心的研发团队&#xff0c;专注于为定位、无线视频终端产品提供平台服务&#xff0c;通天星CMSV6产品覆盖车载录像机、单兵录像机、网络监控摄像机、行驶记录仪等产品的视频综合平…

创建和探索VGG16模型

PyTorch在torchvision库中提供了一组训练好的模型。这些模型大多数接受一个称为 pretrained 的参数&#xff0c;当这个参数为True 时&#xff0c;它会下载为ImageNet 分类问题调整好的权重。让我们看一下创建 VGG16模型的代码片段&#xff1a; from torchvision import models…

猫头虎分享已解决Bug:Array Index Out of Bounds Exception

&#x1f42f; 猫头虎分享已解决Bug&#xff1a;Array Index Out of Bounds Exception &#x1f42f; 摘要 大家好&#xff0c;我是猫头虎&#xff0c;今天我们要聊聊后端开发中经常遇到的一个问题&#xff1a;Array Index Out of Bounds Exception&#xff0c;即 java.lang.…

计算机系统基础知识(上)

目录 计算机系统的概述 计算机的硬件 处理器 存储器 总线 接口 外部设备 计算机的软件 操作系统 数据库 文件系统 计算机系统的概述 如图所示计算机系统分为软件和硬件&#xff1a;硬件包括&#xff1a;输入输出设备、存储器&#xff0c;处理器 软件则包括系统软件和…

北邮《计算机网络》MAC子层笔记

文章目录 缩写复习MAC层所在层次动态分配信道算法们的简要介绍信道的五条基本假设多路访问的协议&#xff08;理论上的协议&#xff09;aloha协议CSMA协议其他冲突避免协议无线局域网协议 &#xff0c;MACA 以太网协议802.3&#xff08;实际协议&#xff0c;刚刚是理论&#xf…

C++ 内存分配可视化

GitHub - archibate/mallocvis: allocation visualization in svg graph 正常连续内存分配 #include <vector>int main() {// 堆mallocstd::vector<int> memory;for (int i 0; i < 1000; i) {memory.emplace_back(i*10);}return 0; } 主动内存分配释放 #in…

计算机组成原理 | CPU子系统(1)基本概述

基本结构模型 运算与缓存部件 数据寄存部件 PSW不是很清楚 存储器是什么&#xff1f;属于那个结构里&#xff1f; 时序处理部件 cpu是大脑&#xff0c;控制器是神经元 ①通过硬件产生控制信号 ②通过软件产生控制信号 外频&#xff08;系统时钟信号&#xff09;&#xff0c;…

Modbus协议在工业自动化中的应用

Modbus协议介绍 Modbus是一种常用的工业现场总线通信协议,被广泛应用于工业自动化领域。它是一种简单、易实现的主从式通信协议,具有高度的可靠性和通用性。本文将从Modbus协议的基本概念、通信模式、数据格式、常见应用场景等方面进行全面介绍,并通过图文并茂的方式帮助读者更…

Linux运行jar包:Invalid or corrupt jarfile

你们好&#xff0c;我是金金金。 场景 maven打包springboot项目得到一个jar包&#xff0c;我通过xshell上传到虚拟机环境里面&#xff0c;试图运行它&#xff0c;结果Invalid or corrupt jarfile&#xff1a;jar 文件无效或损坏 排查 jdk版本是否一致&#xff1f;结果&#xf…

C++精解【6】

文章目录 eigenMatrix基础例编译时固定尺寸运行指定大小 OpenCV概述 eigen Matrix 基础 所有矩阵和向量都是Matrix模板类的对象。向量也是矩阵&#xff0c;单行或单列。Matrix模板类6个参数&#xff0c;常用就3个参数&#xff0c;其它3个参数有默认值。 Matrix<typename…

【uniapp】uniapp开发微信小程序入门教程

HBuilderx中uniapp开发微信小程序入门教程 一、 环境搭建 1. HBuilderx下载安装 HBuilderx下载安装地址 2. 微信开发者工具下载安装 微信开发者工地址具下载安装 二、创建uniapp项目 选择&#xff1a;文件>新建>项目>uni-app 输入项目名称>选择默认模板>…

2024 CISCN 华东北分区赛-Ahisec

Ahisec战队 WEB python-1 break 源码如下&#xff1a; # -*- coding: UTF-8 -*-from flask import Flask, request,render_template,render_template_stringapp Flask(__name__)def blacklist(name):blacklists ["print","cat","flag",&q…

通过高德api查询所有店铺地址信息

通过高德api查询所有店铺地址电话信息 需求&#xff1a;通过高德api查询所有店铺地址信息需求分析具体实现1、申请高德appkey2、下载types city 字典值3、具体代码调用 需求&#xff1a;通过高德api查询所有店铺地址信息 需求分析 查询现有高德api发现现有接口关键字搜索API服…

ai智能写作一键生成的软件盘点,4款宝藏!

在信息爆炸的时代&#xff0c;内容创作已成为各行各业的刚需。然而&#xff0c;对于许多创作者来说&#xff0c;如何高效、高质量地输出内容却是一个不小的挑战。幸运的是&#xff0c;随着人工智能技术的飞速发展&#xff0c;AI智能写作软件应运而生&#xff0c;它们凭借一键生…

在Vue表单中设置缺省值

有个需求&#xff0c;在新增记录的时候&#xff0c;打开新增页面&#xff0c;员工姓名处获取到当前登录用户的用户名&#xff0c;并将其设置为缺省值。 /** 新增按钮操作 */handleAdd() {this.reset();this.open true;// this.form.employeeName this.$store.state.user.name…

【Spine学习15】变换约束

变换约束&#xff1a;能让一个骨骼受另一个骨骼的变化影响。 1、选择m创建一个变换约束&#xff1a; 2、点击这个约束&#xff0c; 将移动数值拉的越满&#xff0c;m越接近s骨骼 当约束为0也就是默认的时候&#xff0c;m骨骼将不会受影响&#xff0c;变换约束可有可无。 tips…

基于Pytorch框架构建AlexNet模型

Pytorch 一、判断环境1.导入必要的库2.判断环境 二、定义字典1.定义字典 三、处理图像数据集1.导入必要的模块2.定义变量3.删除隐藏文件/文件夹 四、加载数据集1.加载训练数据集2.加载测试数据集3.定义训练数据集和测试集路径4.加载训练集和测试集5.创建训练集和测试集数据加载…