参考文章:代码审计知识星球phithon的文章(java安全漫谈 - 02.反射篇(2))
java安全学习篇-2-反射
上文补充:
在评论区看到了一位师傅说:
ClassLoader.getSystemClassLoader().loadClass("java.lang.Runtime")
类似的利用类加载机制,也可以获取 Class 对象,但用这个方法不会像使用forName
一样初始化 ,目前没发现有什么特殊用处。唯一想到的可能是绕沙盒能用?
正文:
关于$符号 :用于查找内部类,我们知道java的类中可以定义内部类,简单来说我们可以把内部类视为另一个类,通过forName(class1$class2)
来获取内部类
我们可以继续反射获取属性、方法:
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 28 29 30 31 32 33 34 35 36 37 38 39 40
| getField(String name)
getDeclaredField(String name)
getMethod(String name, Class<?>... parameterTypes)
getDeclaredMethod(String name, Class<?>... parameterTypes)
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) throws Exception {
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 21
| import java.lang.reflect.Method;
public class Demo { public static void main(String[] args) throws Exception {
Class<?> personClass = Person.class; Object personInstance = personClass.newInstance(); Method secretMethod = personClass.getDeclaredMethod("saySecret"); secretMethod.setAccessible(true); secretMethod.invoke(personInstance); }
}
|
class.newInstance()
是调用无参构造方法,我们也可以class.getDeclaredConstructor().newInstance();
来选择构造方法
注意:直接class.newInstance()
可能会失败,原因有二,使用的类没有无参构造方法或其构造方法为私有
对于没有无参构造方法的类,我们可以使用getDeclaredConstructor()
获取其有参构造方法,例如 getDeclaredConstructor(String.class, int.class)
对于构造方法私有,那我们得使用类中的方法来获取对象
p牛用Runtime做例子
1 2 3 4 5
| 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");
|
笨笨的脑袋未响应了