java安全学习篇-2-反射

文章发布时间:

最后更新时间:

参考文章:代码审计知识星球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)//获取单个 public 的属性

getDeclaredField(String name)//获取单个在当前类中声明的任意属性(包括 private)

getMethod(String name, Class<?>... parameterTypes)//获取单个 public 的方法

getDeclaredMethod(String name, Class<?>... parameterTypes)//获取单个在当前类中声明的任意方法(包括 private)



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;

// 获取 age 的属性
Field ageField = personClass.getDeclaredField("age");
System.out.println(ageField.getName());

// 获取 tellSecret 的方法
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();

// 2. 获取私有方法
Method secretMethod = personClass.getDeclaredMethod("saySecret");

// 必须设置否则无法调用 private 方法
secretMethod.setAccessible(true);

// 4. 在指定实例上调用此方法
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");

笨笨的脑袋未响应了