java反序列化工具_Java反序列化过程深究

No.1

声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。

雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

No.2

概述

互联网上大家针对Java反序列化的讨论有很多了,但是这里我还是想聊聊,这里仅仅记录一下自己的学习笔记,之前我在Java 反序列化深究中讨论了为什么,通过重写 readObject 方法会导致反序列化的问题,当然后续整个过程我们也没继续,当然现在继续回来讨论这个事情。

No.3

反序列化过程

这里需要配合我们的反序列化字节流里面的数据来看。

9ca1eff28d0f39ce3ad93405f2bc61a5.png

而下面是整个过程的调用栈,我们一点点来看。

exec:347, Runtime (java.lang)

readObject:11, ObjectCalcinvoke0:-1,

NativeMethodAccessorImpl (sun.reflect)invoke:62,

NativeMethodAccessorImpl (sun.reflect)invoke:43,

DelegatingMethodAccessorImpl (sun.reflect)invoke:497,

Method (java.lang.reflect)invokeReadObject:1017,

ObjectStreamClass (java.io)readSerialData:1896,

ObjectInputStream (java.io)readOrdinaryObject:1801,

ObjectInputStream (java.io)readObject0:1351,

ObjectInputStream (java.io)readObject:371,

ObjectInputStream (java.io)main:11, unSerializableCalc

在 ObjectInputStream#readObject0 ,会根据 tc 的 byte 值进入 switch 中,选择相关的 case 进行下一步操作。回到之前反序列化字节流中,我们可以看到这里的 TC_OBJECT 为 0x73,所以这里会进入 case 为 TC_OBJECT 中 readOrdinaryObject 的进行字节流的处理。

STREAM_MAGIC - 0xac ed

STREAM_VERSION - 0x00 05Contents

TC_OBJECT - 0x73

TC_CLASSDESC - 0x72

className

Length - 10 - 0x00 0a

Value - ObjectCalc - 0x4f626a65637443616c63

serialVersionUID - 0x33 73 1c 20 ac f0 18 3b

newHandle 0x00 7e 00 00

classDescFlags - 0x02 - SC_SERIALIZABLE

fieldCount - 0 - 0x00 00

classAnnotations

TC_ENDBLOCKDATA - 0x78

superClassDesc

TC_ - 0x70

newHandle 0x00 7e 00 01

classdata

ObjectCalc

values

84905a307fda88095a7b20f3c338ae81.png

跟进 readOrdinaryObject ,在 readOrdinaryObject 中会根据字节流中的下一个关键字 TC_CLASSDESC 进行相关处理,这个 TC_CLASSDESC 是一个 类描述符标识 ,我们可以看到 TC_CLASSDESC 中的 classname 的value正是我们前面测试代码中的 ObjectCalc 这个类名字。

TC_CLASSDESC - 0x72

className

Length - 10 - 0x00 0a

Value - ObjectCalc - 0x4f626a65637443616c63

而处理上述这些东西的方法自然是 readClassDesc ,这里画个重点,下面反序列化的一些修复方法其实和这个里面的一些有关系,当然这里面还有个 TC_PROXYCLASSDESC 引起了我的注意,这个 TC_PROXYCLASSDESC 是 代理类描述符 ,看到代理类这三个字相信熟悉反序列化的朋友们可能不会陌生,当然不太熟悉的朋友可以了解一下 ysoserial 这个项目,这个项目中大量使用了动态代理方式,这种方式反序列化利用本次不会深入探讨,所以话说回来。

//ObjectInputStream#readOrdinaryObjectprivate Object readOrdinaryObject(boolean unshared)

throws IOException { if (bin.readByte != TC_OBJECT) { throw new InternalError;

}

ObjectStreamClass desc = readClassDesc(false);

desc.checkDeserialize;//ObjectInputStream#readClassDescprivate ObjectStreamClass readClassDesc(boolean unshared)

throws IOException { byte tc = bin.peekByte; switch (tc) { case TC_: return (ObjectStreamClass) read; case TC_REFERENCE: return (ObjectStreamClass) readHandle(unshared); case TC_PROXYCLASSDESC: return readProxyDesc(unshared); case TC_CLASSDESC: return readNonProxyDesc(unshared); default: throw new StreamCorruptedException(

String.format("invalid type code: %02X

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值