参考文章:代码审计知识星球 phithon 的文章(java 安全漫谈 - 02.反射篇(2))
上文补充:
在评论区看到了一位师傅说:
ClassLoader.getSystemClassLoader().loadClass(“java.lang.Runtime”) 类似的利用类加载机制,也可以获取 Class 对象,但用这个方法不会像使用 forName 一样初始化 ,目前没发现有什么特殊用处。唯一想到的可能是绕沙盒能用?
始:
关于$符号 :用于查找内部类,我们知道java的类中可以定义内部类,简单来说我们可以把内部类视为另一个类,通过forName(class1$class2)来获取内部类
我们可以继续反射获取属性、方法:
1 2 3 4 5 6 7
| getField(String name)
getDeclaredField(String name)
getMethod(String name, Class<?>... parameterTypes)
getDeclaredMethod(String name, Class<?>... parameterTypes)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import java.lang.reflect.Field; import java.lang.reflect.Method;
public class Person { private int age;
private void tellSecret() { } }
public class Demo { public static void main(String[] args) {
Class<?> personClass = Person.class;
Field ageField = personClass.getDeclaredField("age"); System.out.println(ageField.getName());
Method secretMethod = personClass.getDeclaredMethod("tellSecret"); System.out.println(secretMethod.getName()); } }
|
还有通过实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import java.lang.reflect.Method;
public class Demo { public static void main(String[] args) {
Class<?> personClass = Person.class;
Object personInstance = personClass.newInstance();
Method secretMethod = personClass.getDeclaredMethod("saySecret");
secretMethod.setAccessible(true);
secretMethod.invoke(personInstance);
} }
|
class.newInstance()是调用无参构造方法,我们也可以 personClass.getDeclaredConstructor().newInstance();来选择构造方法
注意:直接 class.newInstance()可能会失败,原因有二,使用的类没有无参构造方法或其构造方法为私有
对于没有无参构造方法的类,我们可以使用 getDeclaredConstructor()获取其有参构造方法,例如例如 getDeclaredConstructor(String.class, int.class)
对于构造方法私有,那我们得使用类中的方法来获取对象
p 牛用 Runtime 做例子
1 2 3
| Class clazz = Class.forName("java.lang.Runtime"); clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz), "calc.exe");
|
method.invoke([1], [2], [3], [4]…)
invoke 方法中,第一个参数是类(静态方法)或者类对象(普通方法)
上面代码拆开后就是
1 2 3 4 5
| Class clazz = Class.forName("java.lang.Runtime"); Method execMethod = clazz.getMethod("exec", String.class); Method getRuntimeMethod = clazz.getMethod("getRuntime"); Object runtime = getRuntimeMethod.invoke(clazz); execMethod.invoke(runtime, "calc.exe");
|
笨笨的脑袋未响应了
正文