反射基本使用
0x01 Preface
Java作为一门静态语言,编译时变量的数据类型已经确定。反射给Java带来了一定的动态性。
“以铜为镜,可以正衣冠”
以反射为镜,照之对象可得类,照之类可得属性方法,皆可访达
0x02 Basic Usage Of Reflect
现有一类Person:
package com.demo;
public class Person {
public String name;
private Integer age;
public Person(){}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
private void action(String move) {
System.out.println(move + ' ' +this.age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}获取类
欲获java.lang.Class对象,如下三法:
Class.forName:传之类名,无需importobj.getClass():上下文该类实例存矣Person.class:类已加载,直捣class属性
三者hashCode无异,同一Class对象也
获取属性和方法
既获之类,进而获之属性与方法,实例之。
getMethod获当前类的public方法(包括从父类继承的方法)getDeclaredMethod获当前类实打实定义的方法,包括private方法(不包括从父类继承的方法)
getField、getDeclaredField同理。若加上s 表示获取所有的方法或属性
getMethod(String name, Class<?>... parameterTypes)面向对象支持重载机制,因此获取方法的时候不仅要指定方法名,还得指定参数的类型
...表示可变长参数,Java底层会将其封装为一个数组 这边可以传多个参数,也可以直接传数组 如new Class[]{A.class, B.class}
method.invoke(Object obj, Object... args)若method是一个普通方法,则第一个参数是类对象 若method是一个静态方法,则第一个参数是类或null 第二个参数也是可变长参数,传入method所需的参数
修改常量
思路很简单,就是修改modifier,modifier是Field类的属性
成功打印success,不存在Serial VersionID的问题
0x03 Best Practice
下面利用反射来实现命令执行
java.lang.Runtime
java.lang.Runtime这个类是设计为单例模式的。 在Web开发中,数据库只需连接一次,下次需要用到数据库时,为避免重复连接,只要拿到数据库连接对象即可,所以数据库连接类或许是下面这样的(单例模式)
这样类在初始化的时候就执行会建立连接,执行构造函数,我们通过getDBConnector 获取数据库连接对象,避免多次进行连接。
java.lang.Runtime的构造方法是私有的,但是却有一个公开方法getRuntime()来获取Runtime对象。
也可以获取Runtime的私有构造器去构造Runtime对象
java.lang.ProcessBuilder
java.lang.ProcessBuilder除了Runtime.exec(),ProcessBuilder.start()是另外一种命令执行的方式。
java.lang.ProcessBuilder有两个构造函数
public ProcessBuilder(List command)
public ProcessBuilder(String... command)
由于newInstance接受的是一个可变长的Object类型参数,可以传入无限个参数或者只传一个数组,因此第二个构造中,传入的是new String[][]{{"calc"}},如果传的是new String[]{"calc"},经过newInstance的这层解析后,传入start的就是字符串calc。可以理解为前者传的是new Object[]{new String[]{"calc"}}
0x04 Summary
本文介绍了反射的如下使用
动态实例化对象
动态调用方法
操作类内部私有属性和方法
修饰常量
还提到了java.lang.Runtime的单例设计模式,类对象会在类初始化时创建,类对外提供getXxx的静态方法来获取类对象,因此每次获取到的对象都为同一个,故名为单例模式。并通过反射来调用的Runtime和ProcessBuilder的命令执行方法。
反射在反序列化漏洞中的应用
通过invoke调用除了同名函数以外的函数
创建对象,引入不能序列化的类(比如传入Runtime.class)
Last updated
Was this helpful?