0x00 什么是字节码
0x01 URLClassLoader
1 2 3 4 5 6 7 8 9
| public class CalcTest { static { try { Runtime.getRuntime().exec("calc"); } catch (IOException e) { throw new RuntimeException(e); } } }
|
file://协议
1 2 3 4 5 6 7
| public class LoadClassTest { public static void main(String[] args) throws Exception { URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file:///F:\\tmp\\classes\\")}); Class<?> c = urlClassLoader.loadClass("CalcTest"); c.newInstance(); } }
|
http://协议
在**.class**文件对应的文件目录下起一个HTTP服务
1
| python -m http.server 9999
|
尝试访问
1 2 3 4 5 6 7
| public class LoadClassTest { public static void main(String[] args) throws Exception { URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("http://localhost:9999/")}); Class<?> c = urlClassLoader.loadClass("CalcTest"); c.newInstance(); } }
|
jar://协议
0x02 ClassLoader.defineClass
1 2 3 4 5 6 7 8 9 10
| public class LoadClassTest { public static void main(String[] args) throws Exception { ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); defineClassMethod.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("F:\\tmp\\classes\\CalcTest.class")); Class c = (Class) defineClassMethod.invoke(systemClassLoader, "CalcTest", code, 0, code.length); c.newInstance(); } }
|
0x03 Unsafe.defineClass
- 字节码加载动态类
- public,但是类不能直接生成
- Spring里面可以直接生成
1 2 3 4 5 6 7 8 9 10 11
| public class LoadClassTest { public static void main(String[] args) throws Exception { ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); Class<Unsafe> unsafeClass = Unsafe.class; Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); Class<?> c = unsafe.defineClass("CalcTest", code, 0, code.length, systemClassLoader, null); c.newInstance(); } }
|
0x04 Template