CSAPP Lab2--Defusing a Binary Bomb

实验材料:http://download.csdn.net/detail/u010560443/9458899
GDB教程:
http://heather.cs.ucdavis.edu/~matloff/UnixAndC/CLanguage/Debug.html
http://www.gnu.org/software/gdb/
x86手册:https://sourceware.org/binutils/docs/as/

phase_2

//read_line读取到的字符串地址在ebp+8处
//答案:1 6 11 16 21 26
//要求:read_six_numbers拆分字符串为六个数字并存到phase_2但局部数组中,
//phase_2+51处要求数组中后一个元素必须比前一个元素大5
Dump of assembler code for function phase_2:
   0x08048ba4 <+0>: push   %ebp   
   0x08048ba5 <+1>: mov    %esp,%ebp
   0x08048ba7 <+3>: sub    $0x28,%esp  #esp=esp-40
   0x08048baa <+6>: lea    -0x1c(%ebp),%eax #eax=ebp-28
   0x08048bad <+9>: mov    %eax,0x4(%esp)  ##arg2 of read_six_numbers
   0x08048bb1 <+13>:    mov    0x8(%ebp),%eax  #eax=*(ebp+8) input string addr
   0x08048bb4 <+16>:    mov    %eax,(%esp)  #arg1=input string addr
   0x08048bb7 <+19>:    call   0x8048fcc <read_six_numbers>
   0x08048bbc <+24>:    movl   $0x1,-0x4(%ebp)   #local i=1
   0x08048bc3 <+31>:    jmp    0x8048be3 <phase_2+63>   
   0x08048bc5 <+33>:    mov    -0x4(%ebp),%eax   #eax=i
   0x08048bc8 <+36>:    mov    -0x1c(%ebp,%eax,4),%edx  #edx=a[1]
   0x08048bcc <+40>:    mov    -0x4(%ebp),%eax #eax=i
   0x08048bcf <+43>:    dec    %eax #eax=eax-1
   0x08048bd0 <+44>:    mov    -0x1c(%ebp,%eax,4),%eax #eax=a[0]
   0x08048bd4 <+48>:    add    $0x5,%eax  #eax=a[0]+5
   0x08048bd7 <+51>:    cmp    %eax,%edx   #if(a[1]==a[0]+5)
   0x08048bd9 <+53>:    je     0x8048be0 <phase_2+60> 
   0x08048bdb <+55>:    call   0x8049626 <explode_bomb>
   0x08048be0 <+60>:    incl   -0x4(%ebp)    # i++
   0x08048be3 <+63>:    cmpl   $0x5,-0x4(%ebp)  # i<=5
   0x08048be7 <+67>:    jle    0x8048bc5 <phase_2+33>
   0x08048be9 <+69>:    leave  
   0x08048bea <+70>:    ret  

Dump of assembler code for function read_six_numbers:
   0x08048fcc <+0>: push   %ebp
   0x08048fcd <+1>: mov    %esp,%ebp
   0x08048fcf <+3>: push   %esi  
   0x08048fd0 <+4>: push   %ebx 
   0x08048fd1 <+5>: sub    $0x30,%esp #esp=esp-30 
   0x08048fd4 <+8>: mov    0xc(%ebp),%eax #local  eax= *(ebp+12)= a
   0x08048fd7 <+11>:    add    $0x14,%eax    # &a[5] of int a[6]
   0x08048fda <+14>:    mov    0xc(%ebp),%edx
   0x08048fdd <+17>:    add    $0x10,%edx
   0x08048fe0 <+20>:    mov    0xc(%ebp),%ecx
   0x08048fe3 <+23>:    add    $0xc,%ecx
   0x08048fe6 <+26>:    mov    0xc(%ebp),%ebx
   0x08048fe9 <+29>:    add    $0x8,%ebx
   0x08048fec <+32>:    mov    0xc(%ebp),%esi
   0x08048fef <+35>:    add    $0x4,%esi    # &a[1]
   0x08048ff2 <+38>:    mov    %eax,0x1c(%esp)  #   arg8
   0x08048ff6 <+42>:    mov    %edx,0x18(%esp)  #   7
   0x08048ffa <+46>:    mov    %ecx,0x14(%esp)  #   6
   0x08048ffe <+50>:    mov    %ebx,0x10(%esp)  #   5
   0x08049002 <+54>:    mov    %esi,0xc(%esp)   #   4 = &a[1] 
   0x08049006 <+58>:    mov    0xc(%ebp),%eax  #eax= *(ebp+12) 
   0x08049009 <+61>:    mov    %eax,0x8(%esp)  # arg3= &a[0] 
   0x0804900d <+65>:    movl   $0x8049c45,0x4(%esp)  #arg2=format string
   0x08049015 <+73>:    mov    0x8(%ebp),%eax  #input string addr
   0x08049018 <+76>:    mov    %eax,(%esp)   #arg1=input string
   0x0804901b <+79>:    call   0x8048868 <sscanf@plt>
   0x08049020 <+84>:    mov    %eax,-0xc(%ebp)  # eax= return value of sscanf (string length) 
   0x08049023 <+87>:    cmpl   $0x5,-0xc(%ebp)  # 5 > strlen
   0x08049027 <+91>:    jg     0x804902e <read_six_numbers+98>
   0x08049029 <+93>:    call   0x8049626 <explode_bomb>
   0x0804902e <+98>:    add    $0x30,%esp
   0x08049031 <+101>:   pop    %ebx
   0x08049032 <+102>:   pop    %esi
   0x08049033 <+103>:   pop    %ebp
   0x08049034 <+104>:   ret  

phase_3

//答案:0 967
//要求:第一个输入是跳转地址在数组中的偏移,跳转后需要和一个立即数比较,第二个输入必须和这个立即数一样
//offset=0,Imm=0x3c7=967 ; offset=1,Imm=0x93......

Dump of assembler code for function phase_3:
   0x08048beb <+0>: push   %ebp
   0x08048bec <+1>: mov    %esp,%ebp
   0x08048bee <+3>: sub    $0x28,%esp           #esp-28
   0x08048bf1 <+6>: movl   $0x0,-0x8(%ebp)      # local2=*(ebp-8)=0
   0x08048bf8 <+13>:    movl   $0x0,-0x4(%ebp)     # local1=*(ebp-4)=0
   0x08048bff <+20>:    lea    -0x10(%ebp),%eax       #  eax=ebp-16=(int *)&num2   local4=num2
   0x08048c02 <+23>:    mov    %eax,0xc(%esp)         #  arg4=&num2 
   0x08048c06 <+27>:    lea    -0xc(%ebp),%eax        #  eax=ebp-12=(int *)&num1      local3=num1
   0x08048c09 <+30>:    mov    %eax,0x8(%esp)         #  arg3=&num1
   0x08048c0d <+34>:    movl   $0x8049947,0x4(%esp)   #arg2=format string 
   0x08048c15 <+42>:    mov    0x8(%ebp),%eax         #eax=input string
   0x08048c18 <+45>:    mov    %eax,(%esp)            #arg1=input string
   0x08048c1b <+48>:    call   0x8048868 <sscanf@plt>
   0x08048c20 <+53>:    mov    %eax,-0x4(%ebp)        #local1=ret value=num of digit
   0x08048c23 <+56>:    cmpl   $0x1,-0x4(%ebp)        
   0x08048c27 <+60>:    jg     0x8048c2e <phase_3+67>   #if(local1>1) jmp 67;
   0x08048c29 <+62>:    call   0x8049626 <explode_bomb> #else bomb;
   0x08048c2e <+67>:    mov    -0xc(%ebp),%eax        #eax=num1
   0x08048c31 <+70>:    mov    %eax,-0x14(%ebp)       #local5=*(ebp+20)=num1   (offset)
   0x08048c34 <+73>:    cmpl   $0x7,-0x14(%ebp)       #local5:7
   0x08048c38 <+77>:    ja     0x8048c8e <phase_3+163>   #if(local5>7)  bomb ;
   0x08048c3a <+79>:    mov    -0x14(%ebp),%edx       #edx=num1
   0x08048c3d <+82>:    mov    0x8049950(,%edx,4),%eax   #eax=0x8049950+4*num1  (array of address)
   0x08048c44 <+89>:    jmp    *%eax            # when num1=0,*(0x8049950+0)=0x08048c46
   0x08048c46 <+91>:    movl   $0x3c7,-0x8(%ebp)      #local2=0x3c7=967
   0x08048c4d <+98>:    jmp    0x8048c93 <phase_3+168>
   0x08048c4f <+100>:   movl   $0x93,-0x8(%ebp)
   0x08048c56 <+107>:   jmp    0x8048c93 <phase_3+168>
   0x08048c58 <+109>:   movl   $0x296,-0x8(%ebp)
   0x08048c5f <+116>:   jmp    0x8048c93 <phase_3+168>
   0x08048c61 <+118>:   movl   $0x225,-0x8(%ebp)
   0x08048c68 <+125>:   jmp    0x8048c93 <phase_3+168>
   0x08048c6a <+127>:   movl   $0x3a6,-0x8(%ebp)
   0x08048c71 <+134>:   jmp    0x8048c93 <phase_3+168>
   0x08048c73 <+136>:   movl   $0x17a,-0x8(%ebp)
   0x08048c7a <+143>:   jmp    0x8048c93 <phase_3+168>
   0x08048c7c <+145>:   movl   $0x1e5,-0x8(%ebp)
   0x08048c83 <+152>:   jmp    0x8048c93 <phase_3+168>
   0x08048c85 <+154>:   movl   $0x16b,-0x8(%ebp)
   0x08048c8c <+161>:   jmp    0x8048c93 <phase_3+168>
   0x08048c8e <+163>:   call   0x8049626 <explode_bomb>
   0x08048c93 <+168>:   mov    -0x10(%ebp),%eax   #eax=local4=num2
   0x08048c96 <+171>:   cmp    %eax,-0x8(%ebp)    #if(num2==local2)
   0x08048c99 <+174>:   je     0x8048ca0 <phase_3+181>
   0x08048c9b <+176>:   call   0x8049626 <explode_bomb>
   0x08048ca0 <+181>:   leave  
   0x08048ca1 <+182>:   ret    
End of assembler dump.
数组第一个元素:
(gdb) x/wx 0x8049950
0x8049950:  0x08048c46

phase_4

//答案:10
//要求:输入数的阶乘为0x375f00,即3628800


Dump of assembler code for function phase_4:
   0x08048cd1 <+0>: push   %ebp
   0x08048cd2 <+1>: mov    %esp,%ebp
   0x08048cd4 <+3>: sub    $0x28,%esp        #esp-0x28 
   0x08048cd7 <+6>: lea    -0xc(%ebp),%eax   #eax=ebp-12=&local3
   0x08048cda <+9>: mov    %eax,0x8(%esp)    #arg3=*(esp+8)=&local3
   0x08048cde <+13>:    movl   $0x8049970,0x4(%esp)   #arg2=format string
   0x08048ce6 <+21>:    mov    0x8(%ebp),%eax      #eax=input string
   0x08048ce9 <+24>:    mov    %eax,(%esp)         #arg1=*(esp)=input string
   0x08048cec <+27>:    call   0x8048868 <sscanf@plt>
   0x08048cf1 <+32>:    mov    %eax,-0x4(%ebp)  #local1=ret value
   0x08048cf4 <+35>:    cmpl   $0x1,-0x4(%ebp)  #if(local1!=1) bomb
   0x08048cf8 <+39>:    jne    0x8048d01 <phase_4+48>
   0x08048cfa <+41>:    mov    -0xc(%ebp),%eax  #eax=local3  = input
   0x08048cfd <+44>:    test   %eax,%eax        #if(local3>0)
   0x08048cff <+46>:    jg     0x8048d06 <phase_4+53>
   0x08048d01 <+48>:    call   0x8049626 <explode_bomb>
   0x08048d06 <+53>:    mov    -0xc(%ebp),%eax  #eax=local3
   0x08048d09 <+56>:    mov    %eax,(%esp)      #arg=local3=input
   0x08048d0c <+59>:    call   0x8048ca2 <func4>
   0x08048d11 <+64>:    mov    %eax,-0x8(%ebp)  #local2=ret value=input!
   0x08048d14 <+67>:    cmpl   $0x375f00,-0x8(%ebp)   #if(local2==0x375f00) 10!=0x375f00
   0x08048d1b <+74>:    je     0x8048d22 <phase_4+81>
   0x08048d1d <+76>:    call   0x8049626 <explode_bomb>
   0x08048d22 <+81>:    leave  
   0x08048d23 <+82>:    ret    
End of assembler dump.


Dump of assembler code for function func4:
   0x08048ca2 <+0>:  push   %ebp
   0x08048ca3 <+1>:  mov    %esp,%ebp
   0x08048ca5 <+3>:  sub    $0x8,%esp
   0x08048ca8 <+6>:  cmpl   $0x1,0x8(%ebp)         
   0x08048cac <+10>: jg     0x8048cb7 <func4+21>   #if(input<1)  jmp 21
   0x08048cae <+12>: movl   $0x1,-0x4(%ebp)        #else local1=1;
   0x08048cb5 <+19>: jmp    0x8048ccc <func4+42>      #return local1; 
   0x08048cb7 <+21>: mov    0x8(%ebp),%eax         #eax=input
   0x08048cba <+24>: dec    %eax                   #eax=input-1
   0x08048cbb <+25>: mov    %eax,(%esp)            #arg1=input-1
   0x08048cbe <+28>: call   0x8048ca2 <func4>      #call func4 recursively
   0x08048cc3 <+33>: mov    %eax,%edx              #edx=ret value
   0x08048cc5 <+35>: imul   0x8(%ebp),%edx         #edx=edx*input
   0x08048cc9 <+39>: mov    %edx,-0x4(%ebp)        #local1=edx
   0x08048ccc <+42>: mov    -0x4(%ebp),%eax        #eax=local1
   0x08048ccf <+45>: leave  
   0x08048cd0 <+46>: ret    
End of assembler dump.
//factorial function
//10!=3628800=0x375f00
int func4(int input)
{
   int local1;
   if(input>1)
    local1=input*func4(input-1);
   else
    local1=1;
   return local1;
}

phase_5

//答案:111100
//解题:
//phase_5中50~59取输入字符串中每个字符的低4位的ascii码值当作偏移,然后根据偏移找到int型数组(位于0x804a5c0)中对应的值
//若6个字符对应的整形值相加的和等于44(phase_5+88处),则成功

(gdb) disass phase_5
Dump of assembler code for function phase_5:
   0x08048d24 <+0>: push   %ebp
   0x08048d25 <+1>: mov    %esp,%ebp
   0x08048d27 <+3>: sub    $0x18,%esp     #esp-0x18
   0x08048d2a <+6>: mov    0x8(%ebp),%eax #eax=input string
   0x08048d2d <+9>: mov    %eax,(%esp)    #
   0x08048d30 <+12>:    call   0x8049035 <string_length>
   0x08048d35 <+17>:    mov    %eax,-0x4(%ebp)  #local1=string length
   0x08048d38 <+20>:    cmpl   $0x6,-0x4(%ebp)  
   0x08048d3c <+24>:    je     0x8048d43 <phase_5+31> #if(local1==6) jmp 31
   0x08048d3e <+26>:    call   0x8049626 <explode_bomb>  #else bom6
   0x08048d43 <+31>:    movl   $0x0,-0x8(%ebp)        #local2=0
   0x08048d4a <+38>:    movl   $0x0,-0xc(%ebp)        #local3=0
   0x08048d51 <+45>:    jmp    0x8048d6f <phase_5+75> #loop start
   0x08048d53 <+47>:    mov    -0xc(%ebp),%eax        #eax=local3  (init=0)  
   0x08048d56 <+50>:    add    0x8(%ebp),%eax         #eax+=input string addr
   0x08048d59 <+53>:    movzbl (%eax),%eax            #eax=first char=0x000000??
   0x08048d5c <+56>:    movsbl %al,%eax               #eax=0xffffff(??) 
   0x08048d5f <+59>:    and    $0xf,%eax              #eax=0x0000000(?)=(lower 4 bits) 
   0x08048d62 <+62>:    mov    0x804a5c0(,%eax,4),%eax#eax=*(0x804a5c0+4*eax) (watch *0x804a5c0 in mem)
   0x08048d69 <+69>:    add    %eax,-0x8(%ebp)        #local2+=eax;
   0x08048d6c <+72>:    incl   -0xc(%ebp)             #local3++
   0x08048d6f <+75>:    cmpl   $0x5,-0xc(%ebp)        #local3<=5 loop;
   0x08048d73 <+79>:    jle    0x8048d53 <phase_5+47> 
   0x08048d75 <+81>:    cmpl   $0x2c,-0x8(%ebp)       #if(loca2==44) success; else bomb;
   0x08048d79 <+85>:    je     0x8048d80 <phase_5+92> #
   0x08048d7b <+87>:    call   0x8049626 <explode_bomb>
   0x08048d80 <+92>:    leave  
   0x08048d81 <+93>:    ret    
End of assembler dump.

//整形数组
(gdb) x/4wx 0x804a5c0
0x804a5c0 <array.2480>: 0x00000002  0x0000000a  0x00000006  0x00000001

//可以看到4*0xa+2*0x2==44,偏移为2个0,4个1
//在6个字符中,只要4个字符的后4位为1,2个字符后2位为0 就可以成功。。
//比如0x313131313030,对应的字符串为111100

phase_6

//答案:345
//解题:看到phase_6的第88行是和输入的数做比较,只要在这里设置断点直接查看edx中的值即可

(gdb) disass phase_6
Dump of assembler code for function phase_6:
   0x08048e16 <+0>: push   %ebp
   0x08048e17 <+1>: mov    %esp,%ebp
   0x08048e19 <+3>: sub    $0x18,%esp      # esp-=0x18
   0x08048e1c <+6>: movl   $0x804a66c,-0x8(%ebp)   # local2=0x804a66c
   0x08048e23 <+13>:    mov    0x8(%ebp),%eax       # ax=input string
   0x08048e26 <+16>:    mov    %eax,(%esp)          
   0x08048e29 <+19>:    call   0x8048858 <atoi@plt> # eax=input number(string->int)
   0x08048e2e <+24>:    mov    %eax,%edx        # edx=input
   0x08048e30 <+26>:    mov    -0x8(%ebp),%eax      # eax=local2
   0x08048e33 <+29>:    mov    %edx,(%eax)      # *(0x804a66c)=input
   0x08048e35 <+31>:    mov    -0x8(%ebp),%eax      # eax=local2
   0x08048e38 <+34>:    mov    %eax,(%esp)         #  arg=local2
   0x08048e3b <+37>:    call   0x8048d82 <fun6>    
   0x08048e40 <+42>:    mov    %eax,-0x8(%ebp)     # local2=eax=ret value; (addr)
   0x08048e43 <+45>:    mov    -0x8(%ebp),%eax     
   0x08048e46 <+48>:    mov    %eax,-0x4(%ebp)     # local1=local2
   0x08048e49 <+51>:    movl   $0x1,-0xc(%ebp)     # local3=1
   0x08048e50 <+58>:    jmp    0x8048e5e <phase_6+72>
   #loop
   0x08048e52 <+60>:    mov    -0x4(%ebp),%eax     # eax=local1
   0x08048e55 <+63>:    mov    0x8(%eax),%eax      # eax=*(eax+8)
   0x08048e58 <+66>:    mov    %eax,-0x4(%ebp)     # local1=eax
   0x08048e5b <+69>:    incl   -0xc(%ebp)          # local3++
   0x08048e5e <+72>:    cmpl   $0x5,-0xc(%ebp)     #  compare 5:local3
   0x08048e62 <+76>:    jle    0x8048e52 <phase_6+60> # if(local3<=5) loop
   0x08048e64 <+78>:    mov    -0x4(%ebp),%eax     # eax=local1
   0x08048e67 <+81>:    mov    (%eax),%edx         # edx=*(local1)
   0x08048e69 <+83>:    mov    0x804a66c,%eax      # eax=*(0x804a66c)=input
   0x08048e6e <+88>:    cmp    %eax,%edx           #  if(edx==input)
   0x08048e70 <+90>:    je     0x8048e77 <phase_6+97>
   0x08048e72 <+92>:    call   0x8049626 <explode_bomb>
   0x08048e77 <+97>:    leave  
   0x08048e78 <+98>:    ret    
End of assembler dump.


(gdb) disass 0x8048d82
Dump of assembler code for function fun6:
   0x08048d82 <+0>:  push   %ebp
   0x08048d83 <+1>:  mov    %esp,%ebp
   0x08048d85 <+3>:  sub    $0x10,%esp       # esp-0x10
   0x08048d88 <+6>:  mov    0x8(%ebp),%eax   # eax=arg=local2=0x804a66c
   0x08048d8b <+9>:  mov    %eax,-0x10(%ebp) # local4=arg
   0x08048d8e <+12>: mov    0x8(%ebp),%eax   # 
   0x08048d91 <+15>: mov    %eax,-0x10(%ebp) 
   0x08048d94 <+18>: mov    0x8(%ebp),%eax   # eax=arg
   0x08048d97 <+21>: mov    0x8(%eax),%eax   # eax=*(arg+8)=*(0x804a66c)
   0x08048d9a <+24>: mov    %eax,-0xc(%ebp)  # local3=eax=*(0x804a66c)
   0x08048d9d <+27>: mov    -0x10(%ebp),%eax # eax=local4=0x804a66c
   0x08048da0 <+30>: movl   $0x0,0x8(%eax)   # *(0x804a66c)=0
   0x08048da7 <+37>: jmp    0x8048e0b <fun6+137>   
   #loop
   0x08048da9 <+39>: mov    -0x10(%ebp),%eax # eax=local4
   0x08048dac <+42>: mov    %eax,-0x4(%ebp)  # local1=local4
   0x08048daf <+45>: mov    -0x10(%ebp),%eax 
   0x08048db2 <+48>: mov    %eax,-0x8(%ebp)  # local2=local4
   0x08048db5 <+51>: jmp    0x8048dc6 <fun6+68>
   0x08048db7 <+53>: mov    -0x4(%ebp),%eax
   0x08048dba <+56>: mov    %eax,-0x8(%ebp)
   0x08048dbd <+59>: mov    -0x4(%ebp),%eax
   0x08048dc0 <+62>: mov    0x8(%eax),%eax
   0x08048dc3 <+65>: mov    %eax,-0x4(%ebp)
   0x08048dc6 <+68>: cmpl   $0x0,-0x4(%ebp)  
   0x08048dca <+72>: je     0x8048dda <fun6+88> # if(local1==0)
   0x08048dcc <+74>: mov    -0x4(%ebp),%eax
   0x08048dcf <+77>: mov    (%eax),%edx
   0x08048dd1 <+79>: mov    -0xc(%ebp),%eax
   0x08048dd4 <+82>: mov    (%eax),%eax
   0x08048dd6 <+84>: cmp    %eax,%edx
   0x08048dd8 <+86>: jg     0x8048db7 <fun6+53>
   0x08048dda <+88>: mov    -0x8(%ebp),%eax     # eax=local2
   0x08048ddd <+91>: cmp    -0x4(%ebp),%eax     # local2:local1
   0x08048de0 <+94>: je     0x8048ded <fun6+107>  # if(local2==local1)
   0x08048de2 <+96>: mov    -0x8(%ebp),%edx
   0x08048de5 <+99>: mov    -0xc(%ebp),%eax
   0x08048de8 <+102>:   mov    %eax,0x8(%edx)
   0x08048deb <+105>:   jmp    0x8048df3 <fun6+113>
   0x08048ded <+107>:   mov    -0xc(%ebp),%eax     # eax=local3
   0x08048df0 <+110>:   mov    %eax,-0x10(%ebp)    # local4=local3
   0x08048df3 <+113>:   mov    -0xc(%ebp),%eax     # eax=local3
   0x08048df6 <+116>:   mov    0x8(%eax),%eax      # eax=*(local3+8)
   0x08048df9 <+119>:   mov    %eax,-0x8(%ebp)     # local2=eax
   0x08048dfc <+122>:   mov    -0xc(%ebp),%edx     # edx=local3
   0x08048dff <+125>:   mov    -0x4(%ebp),%eax     # eax=local1
   0x08048e02 <+128>:   mov    %eax,0x8(%edx)      # *(local3+8)=local1
   0x08048e05 <+131>:   mov    -0x8(%ebp),%eax     # eax=local2
   0x08048e08 <+134>:   mov    %eax,-0xc(%ebp)     # local3=local2
   0x08048e0b <+137>:   cmpl   $0x0,-0xc(%ebp)     
   0x08048e0f <+141>:   jne    0x8048da9 <fun6+39> #if(local3!=0) jump 39;
   0x08048e11 <+143>:   mov    -0x10(%ebp),%eax
   0x08048e14 <+146>:   leave  
   0x08048e15 <+147>:   ret    
End of assembler dump.

0x159=345
1

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值