Linux 下使用软件包

 作者:高玉涵
 时间:2022.4.13 19:42
 博客:blog.csdn.net/cg_i

学习这些知识纯粹是一种乐趣

 在我的日常工作中,我努力做到了每天花一些时间学习新知识,有很多次我学习了一种工具但最终却证明这种工具是没有用的,这促使我后来试图找寻立刻使用它的方法。这也成为我不断学习的强大动力。

1.1 使用软件包

 很多 Linux 的新版本为了让用户操作起来更简便,在运行 Linux 的时候不需要考虑后台的软件包管理器。但是,如果打算在系统提供的试运安全区之外进行操作,就需要知道这些工具是如何工作的。当出现问题时,有必要知道一些关于软件包管理工具的知识。软件包管理器的基本功能包括:

  • 安装新软件
  • 移除(卸载)系统中的软件
  • 验证——确保安装过的文件未被破坏
  • 升级已安装软件的版本
  • 查询已安装的软件(例如“这个文件安装了什么软件包”)
  • 提取——安装前检查软件包的内容
1.2 关于安全性和软件包

 相信每位计算机用户都曾遭遇过恶意软件(malware),Linux 用户一定收到过使用 Windows 系统的朋友发来的莫明其妙的电子邮件。这就是最近微软病毒大量散布于因特网的结果。

 恶意软件不仅包括电子邮件病毒,还包括未经允许便进入系统并自行运行的软件。它用要包括能够自行进入每的病毒、间谍软件和其他破坏性的软件。微软公司的 Windws 拥挤者争辩说 Windows 之所以成为恶意软件的攻击对象,是因为使用 Windows 系统的用户远远超过使用 Linux 的用户。即使可能是事实,但 Windows 是一个更容易遭受攻击的对象也是事实。以前 Windows 98、Windows Me 还有家庭版的 Windows XP 的致命弱点是,任何用户都能接触到任何文件并在系统级别上进行操作。一个没有经验的 Windows 使用者只要点击电子邮件中的附件,就能把一台电脑变成分布式 DoS(denial-of-service,拒绝服务)攻击程序的部落中的一员,或删除 C 系统盘的全部内容。

 恶意软件的动机各不相同,从有组织的犯罪报复到普通的破坏性行为。不要想当然地认为自己不会成为攻击的目标。

 Linux 的用户会认为他们的系统对恶意软件具有免疫力,这不是绝对的。例如,JBellzMP3 就是一款针对 Linux 开源 MP3 播放器的 mpg123 程序缺陷而开发的特洛伊木马程序。在这个实例中,恶意软件甚至不是一个可执行文件,而只是一个 MP3 格式的音乐文件。当用户试图在不同的程序中播放该文件时,它就像是一个受损的文件一样无法运行。事实上,这是一款巧妙地攻击 mpg123 程序特定缺陷的恶意程序。mpg123 包含一个溢出缓冲区,因此一个受损的 MP3 文件包含了可执行的任意脚本。在这个特殊实例中,作者认为最明知的做法是删除用户 home 目录下的内容。

 即使 Linux 机器并不会像微软公司的 Windows 一样大规模地传播病毒,但它还是存有缺陷。当 JBellz 特洛伊木马进入系统时,不会出现任何异常,所以用户所能做的就是注意安全警报并给予足够重视。在 JBellz 案例中,损害只局限于单个用户,至少没有危害到整个系统,当然如果这个用户是超级用户,也有可能危及到整个系统的安全。

 还有一些恶意程序潜伏在应用广泛的软件包源码中。其中一个实例就是 OpenSSH 源码。在这个例子中,主机站点上的 OpenSSH 源码遭受破坏,利用源码编译者权限,为入侵者开辟了秘密通道。所以,如果用户下载了 OpenSSH 受损的源码,创建后安装,那么一个秘密通道就会打开,使得入侵者使用用户的权限执行操作。

 Linux 并没有类似反病毒的程序去扫描病毒;相反,它依赖于信任和验证机制。这就是在面对病毒威胁时积极的和被动不同。Windows 的范例当然是被动的,但其中也包括大量的信任机制。当下载一个 Windows 应用程序时,确信自己的病毒定义是最新的,而且并不是第一个遭遇新病毒的用户。相反,Linux 的方法是“信任并核实”,使用验证机制和被信赖的第三方。

 一个好的安全机制的优点在于,Linux 不允许没有权限的用户安装系统软件。当在系统上安装软件时,必须具有超级用户的权限,也就是说要以超级用户的身份登录或使用类似 sudo 的程序,此时系统最易受到攻击,因为在安装和移除软件时,大多数程序需要执行脚本。无论你是否意识到了,你给予了软件包提供者高度的信任,认为那些脚本不会破坏系统的安全。确保软件的合法最关键的是验证软件包的创建者。

1.3 验证的必要性

 安全性不仅仅是指所运行的程序本身,还包括运行过程的安全性。一位 Linux 用户可以创建他希望创建的任何恶意程序,但如果没有超级用户的特权,他就无法危及到整个计算机的安全。在安装和移除软件过程中,软件包格式允许软件包文件包含可执行脚本,知道这一点是非常重要的。典型的实例是 Bourne Shell 以超级用户权限执行脚本,几乎可以进行任何操作。这种脚本是木马软件包中恶意软件潜在的稳身之处,这也是为什么在安装之前先验证软件而不是等到运行前才验证的原因。

 你也许不愿意使用必须有超级用户权限才能使用的工具,但软件包管理器是个例外。软件包数据库是一个典型版本的中心枢纽,同样地,只有超级用户才能访问。其中有一些验证软件包的方法,例如 rpm 上具,内置了验证特性。其他工具如 Debian,需要独立验证。

1.4 软件包的基本认证

 软件包使用哈希函数作为最基本的验证形式。它和校验和的思想类似,校验和通过数据的各个位之和唯一确定数据,然而单凭文件中所有位的校验和是不足以保障其安全的,很多不同的数据集可能会有相同的校验和,而且当保存校验和时,很容易处理数据。简单的校验和从来不会应用于验证软件包,因为很容易依靠签名。

 哈希函数产生的值是散列值(hash)。与验证和一样,散列值可借助单个定长的数据来描述任意大的数据集,但不同于验证和的是,散列值的输出是不可预知的,这使得很难修改数据并获得相同的散列值。大多数哈希算法使用长的键值(例如 128 位),所以产生相同的散列值的几率微乎其微,根本不需花费时间去尝试。如果下载了一个不明息源的文件,但其散列值与一受信任的信息源相同,那么可以相信以下两点:

  • 修改后的文件具有相同散列值的概率很小。
  • 恶意软件程序编写者随意修改文件,产生相同散列值的概率是无穷小。

 md5sum 是一个用来生成散列值的流行工具,它基于 MD5 算法,能够生成 128 位的散列值。md5sum 程序可产生或验证散列值。你需要在命令行中详细列出文件名才能产生相应散列值,然后这个程序分别列出散列值和其对应的文件名:

md5sum 499834134_nb2-1-80.flv 
4e5d3484f5f81f90c89a6a7651e196df  499834134_nb2-1-80.flv

 可以使用相同的数据作为 md5sum 程序的输入来验证散列值:

md5sum 499834134_nb2-1-80.flv > md5.sum
md5sum --check md5.sum 
499834134_nb2-1-80.flv: OK

 每个散列值用一个 32 位的十六进制表示(每个十六进制数是 4 位)。可以通过受信任的信息源所公布的散列值来验证数据是否正确。如果和 MD5 散列值相匹配,就可以确定从创建 MD5 散列值开始还未修改过该文件,唯一需要明白的问题是,你是否信任所验证的 MD5 散列值。理想的情况是从一个受信任的站点得到的 MD5sum,而从另一个地方下载软件包。假如你的文件是从一个危险站点下载的木马,则可以确信这个站点的任何 MD5 散列值都已被修改过。

1.5 数字签名的软件包验证机制

 数字签名是另一种类似 MD5 的散列值,只是不需要了解待验证数据的任何特定信息。用户所要验证的数字签名来自要验证的个人或组织的公共密钥。有了这个公共密钥,就可以验证由那个人签署的任何数据,即使那个人的签名各不相同,但只要有这个公共密钥,就可以验证任何由他签署的数据。

 签署数据的人要产生一对密钥:一个公共的,一个私有的。这些密钥基于密钥拥有者设定的口令。密钥拥有者保存该私有密钥,并对口令保密,而公共密钥可以公开给想要知道它的人。如果私有密钥或数据发生改变,那么验证就会失败。生成一个相同公共密钥的有效签名的几率是极小的,但是不同的私有密钥和口令却相距甚远。为一个合法的公共密钥伪造一个私有密钥的可能性更是微乎其微的。

 这种方法基于信任机制。用户相信某些个人或组织不会为已被恶意软件所破坏的数据签名,相信他们会为私有密钥和口令的保密而采取一切措施,还不得不相信自己所使用的公共密钥的信息源,假如自己信任的是对的,就可以确信公共密钥验证的数据是可今信赖的。

 GPG Privacy Guard(GPG)是开源代码通常使用的数字签名软件,GPG 签名过程如图 1-1 所示。
在这里插入图片描述

1.6 RPM 格式的 GPG 签名

 RPM 包允许使用 GPG 签名进行验证。RPM 格式的文件也使用包括 MD5 在内的其他散列值。这些散例值可用来验证 RPM 在传输中未受破坏,进而确定那些文件自安装以来也未受损,但它们并不提供验证机制。只有 GPG 签名验证 RPM 格式。当然,也可以选择手动地验证 RPM,使用受信任信息源提供的该软件包文件的 MD5 散列值。

 rpm 有一个 --checksig 标志。遗憾的是,它把所有的散列值都列在一行中。所以如果一个文件没有 GPG 签名, rpm 仍会显示它有正确的 MD5sum。假如它有 GPG 签名,在输出行会显示附加的 gpg OK。考虑下面输出:
在这里插入图片描述

 注意,在列出的 5 个 RPM 软件包文件中,只有 firefox 和 dpkg 软件包有 GPG 签名,这里只有 firefox 的公共密钥而没有 dpkg 的,因此,firefox 是该组中唯一一个可被认为是通过验证的软件包,但 rpm 并未以任何方式高亮显示这一点。非常糟糕,dpkg 有 GPG 签名,我却没有它的公共密钥。所以,即使它已被签署,我依然无法知道签名是否正确。在该例中,至少 rpm 生成了一条不好的警告。

 上述 firefox 软件包的签名是通过验证的,因为它由 Red Hat 签署,而且我在 Fedora 上已经运行过。Fedora 发行版本包括一些 Red Hat 签署软件包用到的公共密钥,当安装这个版本时,这些就会复制到硬盘驱动器上。如果下载一个 RPM,其中一个密钥又可以验证签名,就可以确信这个包确实是由 Red Hat 提供,并且未遭到任何恶意软件的破坏。这里没有 dpkg RPM 的公共密钥,因为它来自 Mandrake 发行版,所以在我的 Fedora 安装版上是不能用的,我需要自己寻找密钥。

 假如下载的软件包具有一个无效签名或者需要未知公共密钥,正如上面提到的 dpkg 软件包,当安装时,rpm 就会发出警告。遗憾的是,rpm4.3.2 版甚至会不加阻挠地安装一个签名未经验证的软件包。这是不幸的,因为在使用超级用户的身份运行这些脚本的安装过程中,系统极易受到攻击。GPG 未区别伪造的密钥和丢失的公共密钥,对此它无能为力。就像现实世界的签名,两个人可能会重名,但绝不会有相同的签名,当然这不包括其中一个是伪造的情况。同样地,两个同名的人具有同一公共密钥,当 GPG 不能验证签名时,它只能告诉用户它没有公共密钥。

1.7 查看软件包

 在安装软件包前后需要查看软件包。安装前,需要检查软件包文件,其中可能有 Linux 合法的文件名,这个文件名通常——但不总是——来自官方软件包的名称,更确切地说,当安装完成后,这个名称将会出现在软件包的数据库中。软件包名称在软件包文件中编码,并且在软件包文件基本查询中应该是可见的。即使软件包的创建者细心地把它作为文件名的一部分,也不要认为文件名和软件包名称是相同的。当软件包安装过后,它只能通过软件包文件中指定的名称被引用,所以用它正式的官方名称来查询应该是不错的首选查询方法。例如,在安装一个 PRM 格式的 gcc 编译器时,因为某种原因,因为某种原因,文件名是 openssl-devel-1.0.2k-25.el7_9.x86_64.rpm,可以按如下方式查询 RPM 文件的内容:

rpm -qip openssl-devel-1.0.2k-25.el7_9.x86_64.rpm
Name        : openssl-devel
Epoch       : 1
Version     : 1.0.2k
Release     : 25.el7_9
Architecture: x86_64
Install Date: (not installed)
Group       : Development/Libraries
Size        : 3269306
License     : OpenSSL
Signature   : RSA/SHA256, 2022年03月29日 星期二 03时53分51秒, Key ID 24c6a8a7f4a80eb5
Source RPM  : openssl-1.0.2k-25.el7_9.src.rpm
Build Date  : 2022年03月28日 星期一 23时43分15秒
Build Host  : x86-01.bsys.centos.org
Relocations : (not relocatable)
Packager    : CentOS BuildSystem <http://bugs.centos.org>
Vendor      : CentOS
URL         : http://www.openssl.org/
Summary     : Files for development of applications which will use OpenSSL
Description :
OpenSSL is a toolkit for supporting cryptography. The openssl-devel
package contains include files needed to develop applications which
support various cryptographic algorithms and protocols.

 但当安装过后,同样的查询变为:

rpm -qi openssl-devel
Name        : openssl-devel
Epoch       : 1
Version     : 1.0.2k
Release     : 19.el7
Architecture: x86_64
Install Date: 2020年06月03日 星期三 11时52分33秒
Group       : Development/Libraries
Size        : 3268775
License     : OpenSSL
Signature   : RSA/SHA256, 2019年08月23日 星期五 05时37分32秒, Key ID 24c6a8a7f4a80eb5
Source RPM  : openssl-1.0.2k-19.el7.src.rpm
Build Date  : 2019年08月09日 星期五 09时40分02秒
Build Host  : x86-02.bsys.centos.org
Relocations : (not relocatable)
Packager    : CentOS BuildSystem <http://bugs.centos.org>
Vendor      : CentOS
URL         : http://www.openssl.org/
Summary     : Files for development of applications which will use OpenSSL
Description :
OpenSSL is a toolkit for supporting cryptography. The openssl-devel
package contains include files needed to develop applications which
support various cryptographic algorithms and protocols.

 rpm 命令通常用来查询 RPM 数据库,-p 选项指明查询目标是软件包文件。同样的软件包可以有任意的文件名,但当将它安装在数据库中后,就只有一个名称了。

 正如所提到的那样,软件包中的基本信息包括它的名称、版本、作者、版权和附加信息。附加信息包括安装文件的列表,安装和移除时运行的脚本。在安装软件包之前通知会对这些比较感兴趣。表 1-1 列出了 RPM 和 Debian 软件包文件的基本查询。

表 1-1 软件包文件的基本查询
查询RPMDebian
基本信息rpm -qpi 文件名dpkg -s 文件名
列出已安装文件rpm -qpl 文件名dpkg -L 文件名
清除安装/卸载脚本rpm -qp -scripts 文件名dpkg -e
确认验证信息rpm --checksig 文件名不可用
显示该软件包需要的其他包rpm -qp --requires 文件名dpkg -I
显示该文件提供的软件包(例如,它们出现在数据库中的名称和脚本)rpm -qp --provides 文件名dpkg -I

 之所以查询软件包数据库或许是因为想知道系统中已安装的软件包,或者想知道某些已安装的特定软件包的版本。一个有效的方法就是验证一个已安装的软件包的目录,以确保自安装以来没有文件遭到破坏。查询已安装的软件包的格式同查询软件包文件会有略微的改动。表 1-2 列出了一些列子。

表 1-2 已安装软件包的基本查询
查询RPMDebian
关于特定软件包的基本信息rpm -qi 名称dpkg -s 名称
列出已安装的所有软件包rpm -qadpkg -list
列出一个特定软件安装的所有文件rpm -ql 名称dpkg -L 名称
确认一个特定软件安装的的文件rpm -V 名称cd /;
md5sum -c < /var/lib/kpkg/info/name.md5sums
该文件属于哪个软件包?rpm -qf 文件名dpkg -S 文件名
当前安装的软件包 X 的版本是什么?rpm -qXdpkg-query -w X
1.8 深入理解 RPM 软件包

 RPM 是 Linux 中最详细的软件包格式之一。一个 RPM 型的软件包包含大量的信息,但却很难从中提取信息。rpm 工具的 --queryformat 选项(简写为 --qf)能帮用户获取附属数据。帮助手册中没有记录 --qf 选项使用的大多数标记,但可以通过输入下面命令获取它的列表:

rpm --querytags
ARCH
ARCHIVESIZE
BASENAMES
BUGURL
BUILDARCHS
BUILDHOST
BUILDTIME
C
CHANGELOGNAME
CHANGELOGTEXT
CHANGELOGTIME
......

 注意,尽管 rpm 列表输出格式是大写的,但查询标记对大小写并不敏感。例如,假设想知道版本中软件包的提供者,可以尝试以下查询:

rpm -qa --qf '%{vendor}'|sort|uniq -c

 另一种有用的查询是检查 RPM 软件包自带的安装脚本。如下所示:

rpm -qp --scripts openssl-devel-1.0.2k-25.el7_9.x86_64.rpm 

 输出中包含表明却本用途(后置安装等)和脚本类型(例如,/bin/sh)的一行信息。这些信息可以让用户在执行之前切实地查看这些脚本。

 使用 rpm2cpio 命令可以获取 RPM 格式的存档文件的目录。该命令将任意 RPM 软件包文件转换成 cpio 存档文件,这也是实际上使用的 RPM 格式。cpio 是一种类似 tar 的存档格式,只是语法有些不同。rpm2cpio 的输出默认是标准输出,不同于 tar,这是 cpio 通常工作的方法。使用下面的命令把 RPM 的文件提取到当前未安装软件包时的目录下:

rpm2cpio openssl-devel-1.0.2k-25.el7_9.x86_64.rpm | cpio -i --no-absolute-filenames

 注意,使用 --no-absolute-filenames 选项可以确保不会破坏任何有价值的系统文件。实际上, cpio 存档文件中的 RPM 软件包不使用绝对文件名。无论如何,都不是绝对安全的。

1.9 深入理解 Debian 软件包

 Debian 具有比 RPM 更为简单的格式,而且 dpkg 工具也缺少 rpm 所拥有的许多特性。因此,在检查这类软件包时,需要付出更多的努力。一个 Debian 软件包的文件名通常具有 .deb 扩展名,而实际上它是由 ar 程序创建的一个存档文件。可以使用 ar 命令来查看 Debian 软件包的目录,但它不会提供太多信息。例如:

ar -t zsh-common_5.8.1-1_all.deb 
debian-binary
control.tar.xz
data.tar.xz

 文件 debian-binary 包含一行 ASCII 文本,表示该软件包所使用的格式版本。文件 control.tar.xz 是一个 tar 存档文件,它包含了安装脚本和一些其他有用的信息。文件 data.tar.xz 同样是 tar 存档文件,包含程序安装文件。为了进一步查看这些文件,使用下面的 ar 命令:

ar -x filename.deb

 文件 control.tar.gz 包括软件包的安装、移除和维护所需的更多的文件。可以通过 dpkg 命令的 -e 选项来提取这些文件,例如:

dpkg -e zsh-common_5.8.1-1_all.deb 
ls ./DEBIAN/*
-rw-r--r--  1 kali kali    117 Feb 12 17:00 conffiles
-rw-r--r--  1 kali kali    883 Feb 12 17:00 control
-rw-r--r--  1 kali kali 109057 Feb 12 17:00 md5sums
-rwxr-xr-x  1 kali kali   1179 Feb 12 17:00 postinst
-rwxr-xr-x  1 kali kali    413 Feb 12 17:00 postrm
-rwxr-xr-x  1 kali kali    180 Feb 12 17:00 preinst
-rwxr-xr-x  1 kali kali    391 Feb 12 17:00 prerm

 正如所推测的那样,文件 preinst 和文件 postinst 是预安装和后置安装的脚本。同样,文件 prerm 和文件 postrm 分别是预卸载和兵团卸载的脚本。

 文件 md5sums 包含 MD5 散列值的列表,可以用来检查文件 data.tar.gz 的完整性。这个文件也可以作为 md5sums 程序的输入,但这些散列值是核实——而非验证。可以用 md5sums 文件来验证软件包在安装前未受到破坏,以及安装后的文件也没有受到破坏,但它无法提供有关文件信息源的任何准确信息。不过,定期用 md5sums 核实安装好的软件包的内容仍然是个不错的主意。

 md5sums 文件并未包含已安装的所有文件,因为一个软件包通常在安装后修改配置文件。假设安装后这些文件将不匹配原始目录,这样的文件就会被排队在检查范围之外,而自行成为 conffiles 文件。当检验安装的完整性时,就会忽略 conffiles 中列出的任何文件。

1.10 软件包更新

 软件包更新器(package updater)用于帮助用户找到需要的软件包文件和它们各自的附属信息。如果想安装 X 软件包,它要求先安装另外 3 个软件包,而这 3 个软件包还没安装。在你能够安装 X 软件包之前需要先安装这 3 个软件包,但是也可能这些软件包的安装还要其他未安装的软件包的安装为前提,然而它们也还需要其他软件包的安装为前提,以此类推。

 这就用到了软件包更新器。使用软件更新器,只需要软件包 X,这个工具会测定用户还需要安装其他哪些软件包,然后下载并安装它们。

1.11 Apt:高级软件包工具

 Apt 是 Debian 发行版本中较为成熟的软件包管理工具之一,而且现在也能用于 RPM 版本。Apt 不同于基本的 dpkg 工具,其优势在于,Apt 可以自动验证具有 GPG 签名的软件包。记住,RPM 也曾支持 GPG 签名。此外,Apt 还会在安装未经验证的软件包之前提醒你,所以不必担心贮存库受到损坏或者下载了木马软件包。

 同 dpkg 一样,Apt 不是一个单独的命令,而是一个命令集。两个最常用的 Apt 命令是 apt-get 和 apt-cache。刚开始,你很可能会对 apt-get 命令感兴趣,它主要用来检索和安装软件包。apt-cache 命令允许用户查询那些已下载到本地高速缓存的可用软件包列表。这比重复查询因特网上的贮存库要快得多。这个列表包括所有可用的软件包,还包括未安装的已安装过的更新信息。

 apt-key 命令允许把来自可靠信息源的公共密钥添加到数据库中,并且检查已拥有的密钥,它允许验证由该信息源签署的软件包。当查找软件包时,命令 apt-setup 允许指定 Apt 优先搜索的贮存库。在我的 Ubuntu 版本中,apt-setup 只允许查询 Ubuntu 的镜像站点,而不能查询 Debian 的贮存库。在本例中,仍然可以手动编辑 /etc/apt/sources.list 文件,使它包括更多的贮存库。/etc/apt/sources.list 可以指向因特网上的站点或者定位系统或局域网上的目录。Apt 唯一的要求是文件必须通过 URL 来获得。

1.12 Yum:Yellowdong 修订版更新

 Yum 是基于 RPM 系统的当前可选的工具。它是一种非常类似于 Apt 的命令行工具。与 Apt 相同的是,Yum 将可用软件包的信息保存到调整缓存中。而与 Apt 不同的是,yum 运行时默认查询贮存库。比起使用高速缓存,它耗费了更多的时间。

 yum 命令用来安装、查询和更新软件包。-C 选项表示 yum 为初始化请求使用高速缓存。如果 yum 决定安装基于该请求的软件,它就会在这之前更新高速缓存。

 使用 Yum,通过 GPG 签名验证是可选的,它通过 /etc/yum.conf 和 /etc/yum.repos.d 下的配置文件来控制每个贮存库。如果已经设置了标记 gpgcheck = 1,命令 yum 就不会安装任何未经验证的软件包。同 Apt 一样,可以在任何能由 URL 访问的目录下创建自己的贮存库。

 yum 命令的选项都是相当直观的。例如,显示当前已安装的并可更新的所有软件包,命令如下:

yum list updates

 这就生成了一个可更新的软件包列表。与 Apt 功能等价却不够直观的是 apt-get --dry-run-u dist-upgrade 选项,它会生成许多杂乱的额外输出。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值