rmi中采用的局部过滤
我们之前是调试过rmi的各种利用的,但是这里补充一个新的点(其实应该也能发现,有些地方比如SAC的确正是如此):rmi中的registerImpl也就是注册中心并不是必须的,参考:深入理解rmi原理 - 简书 (jianshu.com)
RMIRegistry 是必须的吗?
No,RMIRegistry 起到的作用只是为了方便client获取到stub对象,如果还有其他的方法让client拿到stub就不需要RMIRegistry 了,因为client一旦拿到了stub就不需要RMIRegistry 了
作者:春天里的布谷鸟
链接:https://www.jianshu.com/p/2c78554a3f36
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我们熟知的bind, lookup, rebind 等等方法实际上是在操作registerImpl
可以看到有四个实现的接口

bind

bind,unbind

list

这个成员变量到底是什么呢

客户端调用的 bind , lookup,list 等操作,实际上是操作 RegistryImpl 的 bindings 这个 Hashtable。
不信的话可以复现一下,小调一波
老样子我们调试一下,在这里lookup断点

一路进去,见到Lookup就进去



然后到registerImpl_stub这里果然就进不去了,验证刚刚的说法,实际上那么多个lookup要操作的就只是registerImpl_stub

然后可以看到下面就是典型的readObject啥的,原生反序列化
这里我们之所以称RegistryImpl 是一个特殊的对象,是因为 `RegistryImpl 导出过程中生成 Target 对象是一个“定制”的 Target 对象,具体体现在:
1.这个Target 中 id 的 objNum 是固定的,为 ObjID.REGISTRY_ID ,也就是 0 。
2.这个Target 中 disp 是 filter 为 RegisryImpl::RegistryFilter ,skel 为 RegsitryImpl_skel 的 UnicastServerRef 对象。
3.这个Target 中 stub 为 RegistryImpl_stub。
这里我也想调试的,但是没办法

装插件也没用:(52条消息) IDEA 如何进入.class文件上打的的debug断点_idea 怎么断点到class文件里面去_jiuqijack的博客-CSDN博客
这个地方不是在lookup触发的。

找了半天,原来是在创建这个对象的时候触发的

从setup进去,

可以看到,这里的id的objNum= 0
下面的 impl 是 这个RegistryImpl对象
disp的filter不为null (其实是RegistryImpl::RegistryFilter),skel为RegistryImpl_skel的UnicastServerRef
stub为registryImpl_stub
对比普通对象导出的过程中生成的Target, (以下是网图)

具体导出过程:
首先LocateRegistry.createRegistry

强制进去

进去,调用了一些静态方法后,来到这个地方

注意到LiveRef这个地方的id是0

还有一处细节,我上面用的是jdk8u313,就是没有JEP290的,而你看下面

这个是有JEP290限制的
所以整份代码读下来就是
new RegistryImpl(port)中会 new 一个UnicastServerRef对象,将 RegistryImpl 的 id(OBJID.REGISTRY_ID,也就是 0 ) 存入到 LiveRef 对象,随后 LiveRef对象赋值到 UnicastServerRef 对象中的 ref 字段,并且将 RegsitryImpl::registryFilter 赋值给这个 UnicastServerRef 对象的 filter 字段:
随后我们单步进入this.setup(new UnicastServerRef(var2, RegistryImpl::registryFilter));
循规蹈矩的赋值

注意filter
出来后,进入setup,可以看到马上exportObject

然后就又来到刚刚前面分析过的地方

1.这个Target 中 id 的 objNum 是固定的,为 ObjID.REGISTRY_ID ,也就是 0 。
2.这个Target 中 disp 是 filter 为 RegisryImpl::RegistryFilter ,skel 为 RegsitryImpl_skel 的 UnicastServerRef 对象。
3.这个Target 中 stub 为 RegistryImpl_stub。
exportObject

会调用 TCPEndpoint.export

再跟进

这里调用的就是前面的exportObject

服务端处理请求过程
这里不调了,调了一晚上调了个寂寞,根本找不到! 带带我5555555
处理请求是在 Transport#serviceCall,首先从输入流中读取 id , 匹配到 RegistryImpl 对象对应的 Target 。

随后调用 UnicastServerRef.dispatch:

在 UnicastServerRef#dispatch 中,由于 UnicastServerRef.skel 不为 null ,所以会调用 UnicastServerRef#oldDispatch 方法:

oldDispatch 中会先调用 unmarshalCustomCallData(in) 方法,再调用 RegistryImpl_skel.dispatch 方法。

unmarshalCustomCallData 方法中会进行判断,如果 UnicastServerRef.filter 不为 null ,就会设置 ConnectionInputStream的 serialFilter 字段值为 UnicastServerRef.filter (设置单个 ObjectInputStream 的 serialFilter 属性,局部过滤的体现):

再看 RegistryImpl_skel.dispatch :

我们以 bind 为例来讲解:
