LearnJavaMemshellFromZero
【三万字原创】完全零基础从0到1掌握Java内存马,公众号:追梦信安
Install / Use
/learn @W01fh4cker/LearnJavaMemshellFromZeroREADME
本文目录:
- 一、前言
- 二、前置知识
- 2.1 Servlet容器与Engine、Host、Context和Wrapper
- 2.2 编写一个简单的servlet
- 2.3 从代码层面看servlet初始化与装载流程
- 2.4 Filter容器与FilterDefs、FilterConfigs、FilterMaps、FilterChain
- 2.5 编写一个简单的Filter
- 2.6 从代码层面分析Filter运行的整体流程
- 2.7 Listener简单介绍
- 2.8 编写一个简单的Listener(ServletRequestListener)
- 2.9 从代码层面分析Listener运行的整体流程
- 2.10 简单的spring项目搭建
- 2.11 Spring MVC介绍
- 2.12 Spring WebFlux介绍与代码调试分析
- 2.13 Tomcat Valve介绍与运行过程分析
- 2.14 Tomcat Upgrade介绍与打入内存马思路分析
- 2.15 Tomcat Executor内存马介绍与打入内存马思路分析
- 三、传统Web型内存马
- 四、Spring MVC框架型内存马
- 五、中间件型内存马
- 六、致谢
一、前言
之前写的零基础学Fastjson的文章反响很不错,很多师傅在公众号后台和我的微信私聊我表示感谢,其实也没啥,大家都是零基础过来的。网上的文章多而杂,并且只有少部分文章是配图清楚、文字描述清晰的,很多时候新手学着学着可能就因为作者的某一个地方没有描述清楚而不知其所指,非常痛苦;亦或是文章面向对象不同,前置知识不扎实导致很多东西无法理解,这些痛点我都曾经历过。但是随着看过的代码逐渐增多,见识逐渐丰富,调试的次数越多,对各种问题的处理就会越得心应手。
本文所讨论的Java内存马是Java安全中的一个不可或缺的板块,它内容丰富绮丽,研究起来让人着迷,沉沦其中流连忘返。我参考了su18师傅一年多以前发表在Goby社区的这篇文章(https://nosec.org/home/detail/5049.html)中给出的分类方式,把整个零基础掌握java内存马系列分成了以下几个部分:传统web型、spring系列框架型、中间件型、其他内存马(Websocket/Jsp/线程型/RMI)、Agent型内存马、实战内存马打入(Jetty/Weblogic/Shiro/Struts2/GlassFish/xxl-job...)和内存马。
好了,让我们闲话少叙,就此开始。
二、前置知识
本篇文章除特殊说明外,使用的是jdk1.8.0_202+ tomcat 9.0.85,后者下载地址为:
https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.85/bin/apache-tomcat-9.0.85-windows-x64.zip
2.1 Servlet容器与Engine、Host、Context和Wrapper
这部分我找了好久,终于在一大堆高深/垃圾的文章中邂逅了一篇写的还算简明扼要易于理解的文章。
原文地址:https://www.maishuren.top/posts/tomcat/2-tomcat中sevlet容器的设计原理
这里组合引用其原文,简单概括,就是:
Tomcat设计了四种容器,分别是Engine、Host、Context和Wrapper,其关系如下:

这一点可以从Tomcat的配置文件server.xml中看出来。
此时,设想这样一个场景:我们此时要访问https://manage.xxx.com:8080/user/list,那tomcat是如何实现请求定位到具体的servlet的呢?为此tomcat设计了Mapper,其中保存了容器组件与访问路径的映射关系。
然后就开始四步走:
-
根据协议和端口号选定
Service和Engine。我们知道
Tomcat的每个连接器都监听不同的端口,比如Tomcat默认的HTTP连接器监听8080端口、默认的AJP连接器监听8009端口。上面例子中的URL访问的是8080端口,因此这个请求会被HTTP连接器接收,而一个连接器是属于一个Service组件的,这样Service组件就确定了。我们还知道一个Service组件里除了有多个连接器,还有一个容器组件,具体来说就是一个Engine容器,因此Service确定了也就意味着Engine也确定了。 -
根据域名选定
Host。Service和Engine确定后,Mapper组件通过url中的域名去查找相应的Host容器,比如例子中的url访问的域名是manage.xxx.com,因此Mapper会找到Host1这个容器。 -
根据
url路径找到Context组件。Host确定以后,Mapper根据url的路径来匹配相应的Web应用的路径,比如例子中访问的是/user,因此找到了Context1这个Context容器。 -
根据
url路径找到Wrapper(Servlet)。Context确定后,Mapper再根据web.xml中配置的Servlet映射路径来找到具体的Wrapper和Servlet,例如这里的Wrapper1的/list。

这里的Context翻译过来就是上下文,它包括servlet运行的基本环境;这里的Wrapper翻译过来就是包装器,它负责管理一个servlet,包括其装载、初始化、执行和资源回收。
关于上图中的连接器的设计,可以继续参考该作者的博文:
https://www.maishuren.top/posts/tomcat/1-tomcat中的连接器是如何设计的
写到后面之后我又发现了一篇写的极佳的文章,贴在这儿供大家参考,讲的是关于tomcat架构的原理解析:
https://blog.nowcoder.net/n/0c4b545949344aa0b313f22df9ac2c09
2.2 编写一个简单的servlet
pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>servletMemoryShell</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
</project>
同步下依赖:

TestServlet.java代码如下:
package org.example;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.getWriter().write("hello world");
}
}
然后配置项目运行所需的tomcat环境:



然后配置artifacts,直接点击fix:




然后添加web模块:



运行之后,访问http://localhost:8080/testServlet/test:

2.3 从代码层面看servlet初始化与装载流程
主要参考文章:
https://longlone.top/安全/java/java安全/内存马/Tomcat-Servlet型/
我们这里不采用我们下载的tomcat来运行我们的项目,我们使用嵌入式tomcat也就是所谓的tomcat-embed-core。关于动态调试,我是图省事,直接用tomcat-embed-core,你当然也可以调试直接调试tomcat源码,环境搭建方法可以参考Skay师傅的文章:
https://mp.weixin.qq.com/s/DMVcqtiNG9gMdrBUyCRCgw
我们重开一个项目,文件代码如下:
Security Score
Audited on Mar 19, 2026
