0x00 前言 最近在学习Java 反序列化漏洞时,发现需要用到反射的知识,所以根据网上师傅们的文章,简单总结下反射的简单利用方法
0x01 什么是反射
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 public class Person { public String name; private int age; public Person () { System.out.println("调用了无参构造器" ); } private Person (String name, int age) { this .name = name; this .age = age; System.out.println("有参构造器执行了" ); } public String getName () { return name; } public int getAge () { return age; } public void setName (String name) { this .name = name; } public void setAge (int age) { this .age = age; } @Override public String toString () { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}' ; } }
0x02 获取Class类的方法
加载类,获取类的字节码,其实就是操作类的Class对象。
获取Class的方法 类名.class
1 Class<Person> personClass1 = Person.class;
Class.forName(“类名完整路径”)
1 Class<?> pensonClass2 = Class.forName("org.example.Person" );
对象.getClass()
1 2 Person person = new Person ();Class<? extends Person > personClass3 = person.getClass();
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Reflection01 { public static void main (String[] args) throws Exception { Class<Person> personClass1 = Person.class; System.out.println("personClass1 ---> " + personClass1); Class<?> pensonClass2 = Class.forName("org.example.Person" ); System.out.println("pensonClass2 ---> " + pensonClass2); Person person = new Person (); Class<? extends Person > personClass3 = person.getClass(); System.out.println("personClass3 ---> " + personClass3); } }
输出结果:
1 2 3 personClass1 ---> class org .example.Person pensonClass2 ---> class org .example.Person personClass3 ---> class org .example.Person
0x03 获取类的构造器 获取某个构造器 getConstructor()
1 Constructor<Person> constructor1 = personClass.getConstructor();
getDeclaredConstructor()
1 2 Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class, int .class); declaredConstructor.setAccessible(true );
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Reflection02 { @Test public void testReflection02 () throws Exception { Class<Person> personClass = Person.class; System.out.println("----------------------getConstructor-------------------------------------------" ); Constructor<Person> constructor = personClass.getConstructor(); System.out.println(constructor + "--->" + constructor.getParameterCount()); System.out.println("----------------------getDeclaredConstructor-----------------------------------" ); Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class, int .class); declaredConstructor.setAccessible(true ); System.out.println(declaredConstructor + "--->" + declaredConstructor.getParameterCount()); } }
1 2 3 4 ----------------------getConstructor------------------------------------------- public org.example.Person()--->0 ----------------------getDeclaredConstructor----------------------------------- private org.example.Person(java.lang.String,int )--->2
获取全部构造器 getConstructors()
1 Constructor<?>[] constructors = personClass.getConstructors();
getDeclaredConstructors()
1 Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
代码 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 public class Reflection02 { @Test public void testReflection02 () throws Exception { Class<Person> personClass = Person.class; System.out.println("----------------------getConstructors------------------------------------------" ); Constructor<?>[] constructors = personClass.getConstructors(); for (Constructor<?> constructor1 : constructors) { System.out.println(constructor1 + "--->" + constructor1.getParameterCount()); } System.out.println("----------------------getDeclaredConstructors----------------------------------" ); Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors(); for (Constructor<?> declaredConstructor1 : declaredConstructors) { System.out.println(declaredConstructor1 + "--->" + declaredConstructor1.getParameterCount()); } } }
1 2 3 4 5 ----------------------getConstructors------------------------------------------ public org.example.Person()--->0 ----------------------getDeclaredConstructors---------------------------------- public org.example.Person()--->0 private org.example.Person(java.lang.String,int )--->2
初始化对象 newInstance()
class.newInstance() 只能反射无参构造器,且构造器是可见的
constructor.newInstance() 没有限制
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 public class Reflection03 { @Test public void testReflection () throws Exception { Class<Person> personClass = Person.class; System.out.println("----------------------getConstructor-------------------------------------------" ); Constructor<Person> constructor1 = personClass.getConstructor(); System.out.println(constructor1 + "--->" + constructor1.getParameterCount()); Person person = constructor1.newInstance(); System.out.println(person); System.out.println("----------------------getDeclaredConstructor-----------------------------------" ); Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class, int .class); declaredConstructor.setAccessible(true ); System.out.println(declaredConstructor + "--->" + declaredConstructor.getParameterCount()); Person person1 = declaredConstructor.newInstance("小明" , 12 ); System.out.println(person1); } }
1 2 3 4 5 6 7 8 ----------------------getConstructor------------------------------------------- public org.example.Person()--->0 调用了无参构造器 Person{name='null' , age=0 } ----------------------getDeclaredConstructor----------------------------------- private org.example.Person(java.lang.String,int )--->2 有参构造器执行了 Person{name='小明' , age=12 }
0x04 获取成员变量 获取某个成员变量 getField()
1 Field field = personClass.getField("name" );
getDeclaredField()
1 2 Field declaredField = personClass.getDeclaredField("age" );declaredField.setAccessible(true );
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Reflection04 { @Test public void testReflection () throws Exception { Class<Person> personClass = Person.class; System.out.println("----------------------getField-------------------------------------------" ); Field field = personClass.getField("name" ); System.out.println(field); System.out.println("----------------------getDeclaredField-------------------------------------------" ); Field declaredField = personClass.getDeclaredField("age" ); declaredField.setAccessible(true ); System.out.println(declaredField); } }
1 2 3 4 ----------------------getField------------------------------------------- public java.lang.String org.example.Person.name----------------------getDeclaredField------------------------------------------- private int org.example.Person.age
获取全部成员变量 getFields()
1 Field[] fields = personClass.getFields();
getDeclaredFields()
1 Field[] declaredFields = personClass.getDeclaredFields();
代码 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 public class Reflection04 { @Test public void testReflection () throws Exception { Class<Person> personClass = Person.class; System.out.println("----------------------getFields-------------------------------------------" ); Field[] fields = personClass.getFields(); for (Field field1 : fields) { System.out.println(field1); } System.out.println("----------------------getDeclaredFields-------------------------------------------" ); Field[] declaredFields = personClass.getDeclaredFields(); for (Field declaredField1 : declaredFields) { System.out.println(declaredField1); } } }
1 2 3 4 5 ----------------------getFields------------------------------------------- public java.lang.String org.example.Person.name----------------------getDeclaredFields------------------------------------------- public java.lang.String org.example.Person.nameprivate int org.example.Person.age
赋值和取值
set(Object obj, Object value)
get(Object obj)
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 public class Reflection05 { @Test public void testReflection () throws Exception { Class<Person> personClass = Person.class; Field name = personClass.getField("name" ); Field age = personClass.getDeclaredField("age" ); age.setAccessible(true ); Person person = new Person (); name.set(person,"小明" ); age.set(person,12 ); age.setAccessible(true ); System.out.println(person); Object name1 = name.get(person); System.out.println(name1); Object age1 = age.get(person); System.out.println(age1); } }
1 2 3 4 调用了无参构造器 Person{name='小明' , age=12 } 小明 12
0x05 获取成员方法
1 2 3 4 5 6 7 private void run () { System.out.println("喜欢跑步" ); } public String eat (String foodname) { return "喜欢吃" + foodname ; }
获取某个方法 getMethod()
getDeclaredMethod()
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Reflection06 { @Test public void testReflction () throws Exception { Class<Person> personClass = Person.class; System.out.println("----------------------getMethod---------------------------------------------------" ); Method eat = personClass.getMethod("eat" ,String.class); System.out.println(eat); System.out.println("----------------------getDeclaredMethod-------------------------------------------" ); Method run = personClass.getDeclaredMethod("run" ); System.out.println(run); } }
1 2 3 4 ----------------------getMethod--------------------------------------------------- public java.lang.String org.example.Person.eat(java.lang.String)----------------------getDeclaredMethod------------------------------------------- private void org.example.Person.run()
获取全部方法 getMethods()
getDeclaredMethods()
代码 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 public class Reflection06 { @Test public void testReflction () throws Exception { Class<Person> personClass = Person.class; System.out.println("----------------------getMethods--------------------------------------------------" ); Method[] methods = personClass.getMethods(); for (Method method : methods) { System.out.println(method); } System.out.println("----------------------getDeclaredMethods------------------------------------------" ); Method[] declaredMethods = personClass.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ----------------------getMethods-------------------------------------------------- public java.lang.String org.example.Person.toString()public java.lang.String org.example.Person.getName()public void org.example.Person.setName(java.lang.String)public java.lang.String org.example.Person.eat(java.lang.String)public int org.example.Person.getAge()public void org.example.Person.setAge(int )public final void java.lang.Object.wait() throws java.lang.InterruptedExceptionpublic final void java.lang.Object.wait(long ,int ) throws java.lang.InterruptedExceptionpublic final native void java.lang.Object.wait(long ) throws java.lang.InterruptedExceptionpublic boolean java.lang.Object.equals(java.lang.Object)public native int java.lang.Object.hashCode()public final native java.lang.Class java.lang.Object.getClass()public final native void java.lang.Object.notify()public final native void java.lang.Object.notifyAll()----------------------getDeclaredMethods------------------------------------------ private void org.example.Person.run()public java.lang.String org.example.Person.toString()public java.lang.String org.example.Person.getName()public void org.example.Person.setName(java.lang.String)public java.lang.String org.example.Person.eat(java.lang.String)public int org.example.Person.getAge()public void org.example.Person.setAge(int )
执行成员方法 invoke()
调用某个类中的方法
如果这个方法是一个普通 方法,那么第一个参数是类对象
如果这个方法是一个静态 方法,那么第一个参数是类
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 public class Reflection07 { @Test public void testReflction () throws Exception { Class<Person> personClass = Person.class; Method eat = personClass.getMethod("eat" ,String.class); Method run = personClass.getDeclaredMethod("run" ); Person person = new Person (); run.setAccessible(true ); Object run1 = run.invoke(person,null ); System.out.println(run1); Object eat1 = (Object) eat.invoke(person, "鱼" ); System.out.println(eat1); } }
0x06 Runtime命令执行 普通调用 1 2 3 4 5 6 7 public class Exec { public static void main (String[] args) throws Exception { Runtime.getRuntime().exec("calc" ); } }
反射调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Exec { public static void main (String[] args) throws Exception { Class<?> runtimeClass = Class.forName("java.lang.Runtime" ); Method getRuntime = runtimeClass.getMethod("getRuntime" ); Object Runtime = getRuntime.invoke(runtimeClass); Method exec = runtimeClass.getMethod("exec" , String.class); exec.invoke(Runtime,"calc.exe" ); } }
0x07 ProcessBuilder命令调用 普通调用 1 2 3 4 5 6 7 8 9 public class ProcessBuilder { public static void main (String[] args) throws Exception { java.lang.ProcessBuilder processBuilder = new java .lang.ProcessBuilder("calc.exe" ); Process start = processBuilder.start(); } }
反射调用
ProcessBuilder(List command)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class ProcessBuilder { public static void main (String[] args) throws Exception { Class<?> ProcessBuilder = Class.forName("java.lang.ProcessBuilder" ); Constructor<?> constructor = ProcessBuilder.getConstructor(List.class); Object calc = constructor.newInstance(Arrays.asList("calc" )); Method start = ProcessBuilder.getMethod("start" ); start.invoke(calc); } }
public ProcessBuilder(String… command)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class ProcessBuilder { public static void main (String[] args) throws Exception { Class<?> processBuilder = Class.forName("java.lang.ProcessBuilder" ); Constructor<?> constructor = processBuilder.getConstructor(String[].class); Object calc = constructor.newInstance(new String [][]{{"calc" }}); Method start = processBuilder.getMethod("start" ); start.invoke(calc); } }