Using the java.rmi.server.codebase Property

从原理到实战:深入解析Fastjson反序列化漏洞与安全防御 JSON序列化与反序列化是现代Web应用数据交换的核心技术,其原理是将对象状态转换为可传输的字符串格式,并在接收端还原。然而,当反序列化过程允许用户控制被还原的类时,就可能触发不安全的反序列化漏洞,这是Java安全领域一个经典且高危的攻击面。该漏洞的技术价值在于,攻击者可以构造恶意数据,利用应用依赖的库中存在的危险方法链(Gadget Chain),在目标服务器上执行任意代码,实现远程控制。其应用场景广泛,常见于接收JSON格式用户输入的API接口、微服务间的数据传输以及配置文件解析等环节。本文聚焦于业界广 阅读详情

Dynamic code downloading using Java RMI

Dynamic code downloading using JavaTM RMI
(Using the java.rmi.server.codebase Property)


This tutorial is organized as follows:

  1. Starting out
  2. What is a codebase?
  3. How does it work?
  4. Using codebase in Java RMI for more than just stub downloading
  5. Command-line examples
  6. Troubleshooting tips

1.0 Starting out

One of the most significant capabilities of the JavaTM platform is the ability to dynamically download Java software from any Uniform Resource Locator (URL) to a virtual machine (VM) running in a separate process, usually on a different physical system. The result is that a remote system can run a program, for example an applet, which has never been installed on its disk. For the first few sections of this document, codebase with regard to applets will be discussed in order to help describe codebase with regard to Java Remote Method Invocation (Java RMI).

For example, a VM running from within a web browser can download the bytecodes for subclasses of java.applet.Applet and any other classes needed by that applet. The system on which the browser is running has most likely never run this applet before, nor installed it on its disk. Once all the necessary classes have been downloaded from the server, the browser can start the execution of the applet program using the local resources of the system on which the client browser is running.

Java RMI takes advantage of this capability to download and execute classes and on systems where those classes have never been installed on disk. Using the Java RMI API any VM, not only those in browsers, can download any Java class file including specialized Java RMI stub classes, which enable the execution of method calls on a remote server using the server system's resources.

The notion of a codebase originates from the use of ClassLoader s in the Java programming language. When a Java program uses a ClassLoader , that class loader needs to know the location(s) from which it should be allowed to load classes. Usually, a class loader is used in conjunction with an HTTP server that is serving up compiled classes for the Java platform. Most likely, the first ClassLoader /codebase pairing that you came into contact with was the AppletClassLoader , and the "codebase" part of the <applet> HTML tag, so this tutorial will assume that you have some experience with Java RMI programming, as well as writing HTML files that contain applet tags. For example, the HTML source will contain something like:

<applet height=100 width=100 codebase="myclasses/" code="My.class">
	<param name="ticker">
</applet>

2.0 What is a codebase?

A codebase can be defined as a source, or a place, from which to load classes into a virtual machine. For example, if you invited a new friend over for dinner, you would need to give that friend directions to the place where you lived, so that he or she could locate your house. Similarly, you can think of a codebase as the directions that you give to a VM, so it can find your [potentially remote] classes.

You can think of your CLASSPATH as a "local codebase", because it is the list of places on disk from which you load local classes. When loading classes from a local disk-based source, your CLASSPATH variable is consulted. Your CLASSPATH can be set to take either relative or absolute path names to directories and/or archives of class files. So just as CLASSPATH is a kind of "local codebase", the codebase used by applets and remote objects can be thought of as a "remote codebase".

3.0 How does it work?

3.1 How codebase is used in applets

To interact with an applet, that applet and any classes that it needs to run must be accessible by remote clients. While applets can be accessed from "ftp:// " or local "file:/// " URLs, they are usually accessed from a remote HTTP server.

  1. The client browser requests an applet class that is not found in the client's CLASSPATH
  2. The class definition of the applet (and any other class(es) that it needs) is downloaded from the server to the client using HTTP
  3. The applet executes on the client
illustrates three steps above

Figure 1: Downloading applets

The applet's codebase is always relative to the URL of the HTML page in which the <applet> tag is contained.

3.2 How codebase is used in Java RMI

Using Java RMI, applications can create remote objects that accept method calls from clients in other VMs. In order for a client to call methods on a remote object, the client must have a way to communicate with the remote object. Rather than having to program the client to speak the remote object's protocol, Java RMI uses special classes called stubs that can be downloaded to the client that are used to communicate with (make method calls on) the remote object. The java.rmi.server.codebase property value represents one or more URL locations from which these stubs (and any classes needed by the stubs) can be downloaded.

Like applets, the classes needed to execute remote method calls can be downloaded from "file:/// " URLs, but like applets, a "file:/// " URL generally requires that the client and the server reside on the same physical host, unless the file system referred to by the URL is made available using some other protocol, such as NFS.

Generally, the classes needed to execute remote method calls should be made accessible from a network resource, such as an HTTP or FTP server.

 

illustrates the first 5 steps of the stub downloadling process, as listed below

Figure 2: Downloading Java RMI stubs

  1. The remote object's codebase is specified by the remote object's server by setting the java.rmi.server.codebase property. The Java RMI server registers a remote object, bound to a name, with the Java RMI registry. The codebase set on the server VM is annotated to the remote object reference in the Java RMI registry.

     

  2. The Java RMI client requests a reference to a named remote object. The reference (the remote object's stub instance) is what the client will use to make remote method calls to the remote object.

     

  3. The Java RMI registry returns a reference (the stub instance) to the requested class. If the class definition for the stub instance can be found locally in the client's CLASSPATH , which is always searched before the codebase, the client will load the class locally. However, if the definition for the stub is not found in the client's CLASSPATH , the client will attempt to retrieve the class definition from the remote object's codebase.

     

  4. The client requests the class definition from the codebase. The codebase the client uses is the URL that was annotated to the stub instance when the stub class was loaded by the registry. Back in step 1, the annotated stub for the exported object was then registered with the Java RMI registry bound to a name.

     

  5. The class definition for the stub (and any other class(es) that it needs) is downloaded to the client.
    Note: Steps 4 and 5 are the sames steps that the registry took to load the remote object class, when the remote object was bound to a name in (registered with) the Java RMI registry. When the registry attempted to load the remote object's stub class, it requested the class definition from the codebase associated with that remote object.
  6. Now the client has all the information that it needs to invoke remote methods on the remote object. The stub instance acts as a proxy to the remote object that exists on the server; so unlike the applet which uses a codebase to execute code in its local VM, the Java RMI client uses the remote object's codebase to execute code in another, potentially remote VM, as illustrated in Figure 3:
illustrates the final step of the above procedure

Figure 3: Java RMI client making a remote method call

4.0 Using codebase in Java RMI for more than just stub downloading

In addition to downloading stubs and their associated classes to clients, the java.rmi.server.codebase property can be used to specify a location from which any class, not only stubs, can be downloaded.

When a client makes a method call to a remote object, the method that it calls could be written to accept no arguments or a number of arguments. There are three distinct cases that may occur, based on the data type(s) of the method argument(s).

In the first case, all of the method parameters (and return value) are primitive data types, so the remote object knows how to interpret them as method parameters, and there is no need to check its CLASSPATH or any codebase.

In the second case, at least one remote method parameter or the return value is an object, for which the remote object can find the class definition locally in its CLASSPATH .

In the third case (shown as Step 6, in Figure 4), the remote method receives an object instance, for which the remote object cannot find the class definition locally in its CLASSPATH . This type of remote method call is illustrated in Figure 4. The class of the object sent by the client will be a subtype of the declared parameter type. A subtype is either:

  • An implementation of the interface that is declared as the method parameter (or return) type

     

  • A subclass of the class that is declared as the method parameter (or return) type
Illustrates passing an unknown
 subtype as a method parameter, as described above and below.

Figure 4: Java RMI client making a remote method call, passing an unknown subtype as a method parameter

7. Like the applet's codebase, the client-specified codebase is used to download Remote classes, non-remote classes, and interfaces to other VMs. If the codebase property is set on the client application, then that codebase is annotated to the subtype instance when the subtype class is loaded by the client. If the codebase is not set on the client, the remote object will mistakenly use its own codebase.

5.0 Command-line examples

In the case of an applet, the applet codebase value is embedded in an HTML page, as we saw in the HTML example in the first section of this tutorial.

In the case of Java RMI codebase, rather than having a reference to the class embedded in an HTML page, the client first contacts the Java RMI registry for a reference to the remote object. Because the remote object's codebase can refer to any URL, not just one that is relative to a known URL, the value of the Java RMI codebase must be an absolute URL to the location of the stub class and any other classes needed by the stub class. This value of the codebase property can refer to:

  • The URL of a directory in which the classes are organized in package-named sub-directories

     

  • The URL of a JAR file in which the classes are organized in package-named directories

     

  • A space-delimited string containing multiple instances of JAR files and/or directories that meet the criteria above

Note: When the codebase property value is set to the URL of a directory , the value must be terminated by a "/".

Examples

If the location of your downloadable classes is on an HTTP server named "webvector", in the directory "export" (under the web root), your codebase property setting might look like this:

	-Djava.rmi.server.codebase=http://webvector/export/

If the location of your downloadable classes is on an HTTP server named "webline", in a JAR file named "mystuff.jar", in the directory "public" (under the web root), your codebase property setting might look like this:

	-Djava.rmi.server.codebase=http://webline/public/mystuff.jar

Now let's suppose that the location of your downloadable classes has been split between two JAR files, "myStuff.jar" and "myOtherStuff.jar". If these JAR files are located on different servers (named "webfront" and "webwave"), your codebase property setting might look like this:

	-Djava.rmi.server.codebase="http://webfront/myStuff.jar http://webwave/myOtherStuff.jar"

6.0 Troubleshooting tips

Any serializable class, including Java RMI stubs, can be downloaded if your Java RMI programs are configured properly. Here are the conditions under which dynamic stub downloading will work:

  1. The stub class and any of the classes that the stub relies on are served up from a URL reachable from the client.

     

  2. The java.rmi.server.codebase property has been set on the server program (or in the case of activation, the "setup" program) that makes the call to bind or rebind , such that:

     

    • The value of the codebase property is the URL in step A

      and

       

    • If the URL specified as the value of the codebase property is a directory, it must end in a trailing "/"

  3. The rmiregistry cannot find the stub class or any of the classes that the stub relies on in its CLASSPATH . This is so the codebase gets annotated to the stub when the registry does its class load of the stub, as a result of calls to bind or rebind in the server or setup code.

     

  4. The client has installed a SecurityManager that allows the stub to be downloaded. In the Java 2 SDK, Standard Edition, v1.2 and later, this means that the client must also have a properly configured security policy file.

There are two common problems associated with the java.rmi.server.codebase property, which are discussed next.

6.1 If you encounter a problem running your Java RMI server

The first problem you might encounter is the receipt of a ClassNotFoundException when attempting to bind or rebind a remote object to a name in the registry. This exception is usually due to a malformed codebase property, resulting in the registry not being able to locate the remote object's stubs or other classes needed by the stub.

It is important to note that the remote object's stub implements all the same interfaces as the remote object itself, so those interfaces, as well as any other custom classes declared as method parameters or return values, must also be available for download from the specified codebase.

Most frequently, this exception is thrown as a result of omitting the trailing slash from the URL value of the property. Other reasons would include: the value of the property is not a URL; the path to the classes specified in the URL is incorrect or misspelled; the stub class or any other necessary classes are not all available from the specified URL.

The exception that you may encounter in such a case would look like this:

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
	java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
	java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub
	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Compiled Code)
	at sun.rmi.transport.StreamRemoteCall.executeCall(Compiled Code)
	at sun.rmi.server.UnicastRef.invoke(Compiled Code)
	at sun.rmi.registry.RegistryImpl_Stub.rebind(Compiled Code)
	at java.rmi.Naming.rebind(Compiled Code)
	at examples.callback.MessageReceiverImpl.main(Compiled Code)
RemoteException occurred in server thread; nested exception is:
	java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: examples.callback.MessageReceiverImpl_Stub

6.2 If you encounter a problem running your Java RMI client

The second problem you could encounter is the receipt of a ClassNotFoundException when attempting to lookup a remote object in the registry. If you receive this exception in a stacktrace resulting from an attempt to run your Java RMI client code, then your problem is the CLASSPATH with which your Java RMI registry was started. See requirement C in section 6.0 . Here is what the exception will look like:

java.rmi.UnmarshalException: Return value class not found; nested exception is:
	java.lang.ClassNotFoundException: MyImpl_Stub
	at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:109
	at java.rmi.Naming.lookup(Naming.java:60)
	at RmiClient.main(MyClient.java:28)

Other resources

If you your codebase questions are still unanswered, please take a look through the archives of the rmi-users email list first.

You may wish to subscribe to the rmi-users email list .


Copyright © 2006 Sun Microsystems, Inc. All Rights Reserved.

Please send comments to: rmi-comments@java.sun.com
Sun
Java Software

项目计划书、规划文档模板 项目计划书、规划文档模板 最近通过项目实践经历,整理出的一套项目计划书(仅供自己参考梳理思路使用) 有喜欢的文末加VX 辛苦码字如有转载请标明出处谢谢!——木研 更新的简版项目规划文档! 原版文件请+vx :baierfa ... 阅读详情

相关推荐

十五天学会Autodesk Inventor,看完这一系列就够了(七),工程图纸

不管哪种绘图软件,二维或三维绘图,最终均需要转换成工程图纸,才能交给现场人员进行制作,这是任一产品图都要经历的过程。那本章开始,我们一起看一下Inventor是如何实现工程图纸?

Crazydoubao的博客 4908

spring rmi 客户端调用出错

java.rmi.UnmarshalException: error unmarshalling return; nested exception is: at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source) at 缺少 springframework spring-remoting 1....

k0yang的专栏 241

告别Visual Studio!用MSYS2+GCC+CMake在Windows上打造Linux式C++开发环境(保姆级避坑)

本文详细介绍了如何在Windows上使用MSYS2+GCC+CMake搭建Linux式C++开发环境,替代Visual Studio。从MSYS2的安装配置、MinGW-w64 GCC工具链的部署,到CMake项目的创建与构建,提供了保姆级教程和常见问题解决方案,帮助开发者高效过渡到命令行开发模式。

weixin_30298497的博客 325

rmi远程代码执行漏洞_JavaRMI服务远程方法调用漏洞如何修复lin

展开全部背景要求:62616964757a686964616fe58685e5aeb931333433623135定时监控远程主机上mongodb数据库内存使用的情况,当内存使用过大时暂停逻辑处理线程后启动内存空间的释放处理线程,释放完成后再启动逻辑处理线程。操作系统:CentOS64bit(Linux)步骤(代码省略):1.创建Socket远程服务器2.创建客户端配置:#查找对象stub端口RM...

weixin_39872893的博客 1762

QGC二次开发实战指南(一):从零构建自定义地面站界面

本文详细介绍了QGC二次开发实战指南,从零开始构建自定义地面站界面。通过QT和QML技术结合MAVLINK协议,开发者可以打造适合特定业务场景的无人机监控系统,提升操作效率与用户体验。文章包含环境搭建、界面设计、数据绑定等完整开发流程,是QGC二次开发的实用教程。

weixin_28693683的博客 496

NVMe-MI --- Message Servicing Model(消息服务模型)

本文主要介绍NVMe-MI消息服务模型,两个主要类别是请求消息和响应消息。并介绍带外机制消息服务状态机。

智小星的博客 2014

sun.rmi.registry.RegistryImpl_Stub RMIC

报错信息: [code="java"] java.net.ConnectException: Connection refused: connect at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:574) at sun.rmi.transport.tcp.TCPChannel.createConnecti...

peijunlin2008 1633

基于图像分割的LIDC-IDRI 数据集预处理之数据下载篇

近期接触到了一个关于图像分割实验项目,关于数据预处理部分在此予以记录,和大家分享。

qq_67696694的博客 1904

java代码题 穿过隧道_使用隧道的Java RMI - 一个例外

当我们完成调试步骤时,这个问题变得很长。我将把这些留给那些有问题的未来用户,但是这里有一个简短的版本:简短版使用putty,而不是使用&#34; Dynamic&#34;这意味着它使用SOCKS,你应该使用&#34; local&#34;连接到SSH服务器。更改此项修复了以下异常:java.rmi.ConnectIOException: error during JRMP connection e...

weixin_39938331的博客 617

5G MBS(组播广播服务)深度解析:从标准架构到商用实践

5G MBS(组播广播服务)深度解析:从标准架构到商用实践

大家好,我是码农老gou,一名专注于编程技术的程序员。在这个博客中,我将与大家分享我在工作和学习中的经验、见解以及一些实用的技术干货。 1082

IBM AC922 8335-GTW 安装linux,CentOS,ubuntu,RHEL各种坑

AC922

u011970286的专栏 894

java rmi 防火墙_java – Spring:无法从防火墙后面使用RMI连接到JMX Server

我的Spring应用程序运行在NAT防火墙(pfSense)后面的机器上.机器的内部IP是a.b.c.d,NAT IP是w.x.y.zSpring配置的serviceUrl在端口1100上设置为我的内部IP(a.b.c.d),当我启动应用程序时,我提供以下开关:-Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dc...

weixin_39526872的博客 325

MiniMax H3 + ComfyUI 工作流搭建指南:从整合包到视频生成

AI视频生成正成为内容创作的新基础设施,而ComfyUI作为可视化工作流引擎,将复杂的模型推理过程拆解为节点与连线,让本地视频生成变得可复用、可批量。理解这一原理后,用户无需编写代码,只需掌握模型加载、提示词控制、采样与解码的基本链路,即可搭建出稳定的视频生产管线。MiniMax H3作为前沿视频生成模型,在ComfyUI中通过权重文件和自定义节点落地,配合整合包可大幅降低环境配置门槛。从硬件评估、目录结构到节点连接与参数调优,本文系统性梳理了从零跑通一条视频生成工作流的完整路径,帮助用户在批量素材生成、风

weixin_29057065的博客 414

java.rmi.server.codebase Property介绍

在使用RMI编程的时候,有时会出现如下的错误: java.rmi.ServerException: RemoteException occurred in server thread; nested excption is:        java.rmi.UnmarshalException: error unmarshalling arguments; nested excetion is

6288

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

java.rmi.server.codebase Property

原文: http://blog.csdn.net/jackiezhw/archive/2007/05/30/1631846.aspx 在使用RMI编程的时候,有时会出现如下的错误: java.rmi.ServerException: RemoteException occurred in server thread; nested excption is: java...

javavsnet 236

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

ref 能否注入为null_如何绕过高版本JDK限制进行JNDI注入利用

//写在前面//Java JNDI注入有很多种不同的利用方式,而这些利用方式的Payload分别有一些限制。在之前《深入理解JNDI注入与Java反序列化漏洞利用》中,我们主要讨论的是通过RMI服务返回 JNDI Naming Reference Payload 的攻击手法,除此之外还有 RMI Remote Object Payload、LDAP Naming Reference Pa...

weixin_39783633的博客 953

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

工作中使用到的单词(软件开发)

1.エイリアス   alias 别名 powershell使用 get-help 命令时,会得到与此命令 相关(别名)的命令 2.プロキシ proxy 代 理 3.プロモート   promote 促进,提升   开发的系统新功能上线发布,有时会使用到这个词,比如 STプロモート 还有使用リリース这个词的。比如STリリース。个人认为两者含义相同。 4.見逃し み................................................................

sun0322 6万+

rmi,端口冲突

最近在给客户的应用软件中,有个模块一直报错,而别的模块都能正常使用,这个模块与别的模块不一样地方就是:这个模块使用了rmi技术调用,只要调用这个模块就报错误,信息如下:   2010-06-01 15:08:47 [ERROR] com.nstrong.itop.web.action.knowledge.KnowledgeAction {KnowledgeAction.java:601} - ...

qingfeng200468的博客 763

java/jmx:java.rmi.server.codebase不支持嵌套的jar

根据java官方说明: 《Dynamic code downloading using Java™ RMI(Using the java.rmi.server.codebase Property)》 https://docs.oracle.com/javase/7/docs/technotes/guides/rmi/codebase.html java.rmi.server.codebase 指定的类加载位置URL可以是jar包,也可以是‘/’结尾的类路径,但不可以是嵌套式的fat-jar包中的jar.比如

10km的专栏 379

Java rmi-codebase记录

不得不承认能学会这么多利用姿势全靠站在巨人的肩膀上8u191后的JNDI注入利用:这篇文章介绍的RMI攻击方法在低版本比较适用搞懂RMI、JRMP、JNDI-终结篇:三梦师傅的文章,更侧重代码调试和RMI的原理,写文章的思路也是针对JNDI利用,按照不同的jdk版本介绍相应的攻击手法。Java RMI远程利用分析:长亭师傅写的文章,主要在死磕rmi服务这块给了不少思路,缺点是代码和命令贴的不是很全一次攻击内网rmi服务的深思bsmali4师傅写的,关于如何绕JEP290写的相当详细。

AsagiRiAsagi的博客 1131

Java——RMI详解

RMI 是 Java 提供的一个完善的简单易用的远程方法调用框架,采用客户/服务器通信方式,在服务器上部署了提供各种服务的远程对象,客户端请求访问服务器上远程对象的方法,它要求客户端与服务器端都是 Java 程序。RMI 框架采用代理来负责客户与远程对象之间通过 Socket 进行通信的细节。RMI 框架为远程对象分别生成了客户端代理和服务器端代理。位于客户端的代理必被称为存根(Stub),位于服务器端的代理类被称为骨架(Skeleton)。

吴声子夜歌的博客 9039

java 动态rmi_java rmi 动态加载远程代码

一、rmi为什么要加载远程代码rmi在进行远程方法调用的时候需要客户端和服务端都准备好各自所需的类文件,当有很多个客户端对服务端代码进行远程调用的时候就需要维护每个客户端的本地类文件,非常的繁琐。通过rmi的远程加载代码可以简化这个过程,我们将类文件集中存在注册服务的某个路径或者某个网址下,然后通过-Djava.rmi.server.codebase 属性配置远程加载的代码路径,当客户端调用时可...

weixin_33532301的博客 508

Jini和RMI开发中的codebase问题

google_ad_client = "pub-8800625213955058";/* 336x280, 创建于 07-11-21 */google_ad_slot = "0989131976";google_ad_width = 336;google_ad_height = 280;//<script type="text/java

java专栏 542

Java 调用rmi_Java RMI调用远程程序抛出异常

展开全部背景要求:定时监e69da5e887aa3231313335323631343130323136353331333361303561控远程主机上mongodb数据库内存使用的情况,当内存使用过大时暂停逻辑处理线程后启动内存空间的释放处理线程,释放完成后再启动逻辑处理线程。操作系统:CentOS 64bit (Linux)步骤(代码省略):1.创建Socket远程服务器2.创建客户端配置:#...

weixin_31487521的博客 544
上一篇: CheckedInputStream&CheckedOutputStream
下一篇: XJL:XML文件处理
jackoo
博客等级 码龄18年 5粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值