反射
一、获取反射对象(反射入口)
Class ===>三种方法:
1.Class.forName()
2.XX.Class
3.对象.getClass
package com.fanshe.demoClass;
import com.fanshe.demoClass.demoClass;
public class fanshe {
public static void main(String[] args) throws ClassNotFoundException {
// 1.Class.forName(全类名)
Class<?> democlass = Class.forName("com.fanshe.demoClass.demoClass");
System.out.println(democlass);
// 2.类名.class
Class<?> democlass2 = com.fanshe.demoClass.demoClass.class;
System.out.println(democlass2);
// 3.对象.getclass
demoClass democlass3 = new demoClass();
Class<?> democlass4 = democlass3.getClass();
System.out.println(democlass4);
}
}
2.获取方法
1.获取所有公共方法(本类和父类所有符合访问修饰符的方法(static))
public static void demo2() throws ClassNotFoundException{
Class<?> demo = Class.forName("com.fanshe.demoClass.demoClass");
// 获取所有公共方法(本类和父类所有符合访问修饰符的方法(static))
Method[] methods = demo.getMethods();
for(Method method:methods){
System.out.println(method);
}
}
2.获取当前类的所有接口
public static void demo3() throws ClassNotFoundException{
Class<?> demo = Class.forName("com.fanshe.demoClass.demoClass");
Class<?>[] interfaces = demo.getInterfaces();
for(Class<?> inter:interfaces){
System.out.println(inter);
}
}
3.获取所有父类
// 获取所有父类
public static void demo4() throws ClassNotFoundException{
Class<?> demo = Class.forName("com.fanshe.demoClass.demoClass");
Class<?> superclass = demo.getSuperclass();
System.out.println(superclass);
}
4.获取所有构造方法
Constructor<?>[] constructors = demo.getConstructors();
5.获取所有公共属性
Field[ ] fields = demo.getFields();
6.获取当前类都所有方法
Method[] methods = demo.getDeclaredMethods();
7.获取当前类所有属性
Field[ ] DeclaredField= demo.getDeclaredField();
8.创建新实例
Object instance = demo.newInstance();
(fanshe)instance;
二、操作反射对象
1.获取对象都实例,并操作对象
public static void demo5() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class<?> demo = Class.forName("com.fanshe.demoClass.demoClass");
demoClass demos = (demoClass)demo.newInstance();
demos.setName("zs");
demos.setId(1);
System.out.println(demos.getName());
}
2.操作属性
public static void demo6() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class<?> demo = Class.forName("com.fanshe.demoClass.demoClass");
demoClass demos = (demoClass)demo.newInstance();
Field id = demo.getDeclaredField("id");
// 访问private修饰的属性则需要加下面的代码,修改访问权限
id.setAccessible(true);
id.set(demos,1);
System.out.println(demos.getId());
}
3.其他
其他的和上面都差不多,只是使用的方法不同。
反序列化
一、java序列化与反序列化
1.概念
Java 序列化是指把 Java 对象转换为字节序列的过程便于保存在内存、文件、数据库中,ObjectOutputStream类的 writeObject() 方法可以实现序列化。
Java 反序列化是指把字节序列恢复为 Java 对象的过程,ObjectInputStream 类的 readObject() 方法用于反序列化
2.必备条件
1⃣️.使用此方法进行序列化的对象必须实现Serializable接口,不然在进行序列化时会抛出NotSerializableException异常。
2⃣️.该类的所有属性必须是可序列化的。
3.例子
package serlize;
import java.io.*;
public class serialzaTest {
private test objectFromDisk;
public static void main(String[] args) throws Exception {
test Test = new test();
Test.name="zs";
//创建一个包含对象进行反序列化信息的”object”数据文件
FileOutputStream fos = new FileOutputStream("object");
ObjectOutputStream os = new ObjectOutputStream(fos);
//writeObject()方法将myObj对象写入object文件
os.writeObject(Test);
os.close();
//从文件中反序列化obj对象
FileInputStream fis = new FileInputStream("object");
ObjectInputStream ois = new ObjectInputStream(fis);
//恢复对象
test objectFromDisk = (test) ois.readObject();
System.out.println(objectFromDisk.name);
ois.close();
}
}
class test implements Serializable{
public String name;
}
上诉例子中,通过new一个新的tes对象,并且test对象是实现了Serializable接口的,然后通过writeObject方法序列化对象,然后存入object文件中,然后在通过readObject方法来反序列化对象,然后将其强转为test对象,我们可以直接输出反序列化后得到对象的name属性,得到"zs"。
4.反序列化rcedemo
package serlize;
import java.io.*;
public class serialzaTest {
private test objectFromDisk;
public static void main(String[] args) throws Exception {
test Test = new test();
Test.name="zs";
//创建一个包含对象进行反序列化信息的”object”数据文件
FileOutputStream fos = new FileOutputStream("object");
ObjectOutputStream os = new ObjectOutputStream(fos);
//writeObject()方法将myObj对象写入object文件
os.writeObject(Test);
os.close();
//从文件中反序列化obj对象
FileInputStream fis = new FileInputStream("object");
ObjectInputStream ois = new ObjectInputStream(fis);
//恢复对象
test objectFromDisk = (test) ois.readObject();
System.out.println(objectFromDisk);
ois.close();
}
}
class test implements Serializable{
public String name;
private void readObject (java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
Runtime.getRuntime().exec("open /System/Applications/Calculator.app/");
}
@Override
public String toString() {
return this.name;
}
}
因为凡序列化时会使用到readobject这个方法,这个方法不管我们写不写java都需要去调用,才能成功反序列化,那么我们重写这个方法就可以达到反序列化rce的效果。