ICMP扫描程序.docx

上传人:b****5 文档编号:5978477 上传时间:2023-01-02 格式:DOCX 页数:18 大小:84.48KB
下载 相关 举报
ICMP扫描程序.docx_第1页
第1页 / 共18页
ICMP扫描程序.docx_第2页
第2页 / 共18页
ICMP扫描程序.docx_第3页
第3页 / 共18页
ICMP扫描程序.docx_第4页
第4页 / 共18页
ICMP扫描程序.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

ICMP扫描程序.docx

《ICMP扫描程序.docx》由会员分享,可在线阅读,更多相关《ICMP扫描程序.docx(18页珍藏版)》请在冰豆网上搜索。

ICMP扫描程序.docx

ICMP扫描程序

课程名称

网络技术课程设计

时间

2010~2011学年第二学期17~18周

学生姓名

帅哥

指导老师

刘青

题目

ICMP扫描程序的设计与实现

主要内容:

(1)了解ICMP协议,知道ICMP协议的概念,内容,重要性等。

(2)学会编写ICMP扫描程序。

要求:

(1)综合运用计算机网络基本理论和编程语言设计本系统。

(2)学会文献检索的基本方法和综合运用文献的能力。

(3)通过课程设计培养严谨的科学态度,认真的工作作风和团队协作精神。

应当提交的文件:

(1)课程设计学年论文。

(2)课程设计附件(相关图纸、设备配置清单、报告等)。

ICMP扫描程序的设计与实现

学生姓名:

帅哥指导教师:

刘青

摘要:

我们常用Ping程序来判断一个特定的主机是否处于活动状态.该程序发送一个ICMP回应请求报文给主机,然后等待返回的ICMP报文回应应答就可以知道自己是否能成功的访问到那台机器.本次课程设计涉及到MFC的应用,要在充分了解套接字的实现以及IP,ICMP的格式,功能等的基础上才能实现此设计。

关键字:

ICMP;扫描;程序;协议;

 

附录及源代码15

1引言

1.1课程设计目的

IP协议的优点是简单,但缺少差错控制和查询机制,而网际控制报文协议(ICMP具有补充IP功能的作用。

在网络管理中,常常要确定当前网络在红处于活动状态的主机,这时可以通过ICMP的回送和回送响应消息来完成这项工作。

这课程设计的目的就是编制程序,利用ICMP数据包,发现网络中的活动主机,即ping消息的请求和应答。

通过课程设计,熟悉ICMP报文的结构,对ICMP协议有更好的理解和认识,培养综合运用网络知识解决实际问题能力。

1.2课程设计要求

设计程序,其功能是发送ICMP数据包,以获取指定望段中的活动主机,并将结果显示在标准输出设备上程序的具体要求如下:

1.用命令形式运行

scanhost为程序名;start_ip为被搜索网段;end_ip为被搜索网段的结束IP地址。

如在命令行输入scanhost192.168.0.1192.168.0.100

2.输出格式

活动主机1的IP地址

活动主机2的IP地址

活动主机n的IP地址

 

2概要设计

2.1设计原理

本程序使用的原始套接字生成ICMP请求/应答报文来进行活动主机的探查。

这个程序使用的是回送请求和应答消息。

程序的大致思想是把ICMP的数据报类型设置为回送请求,将它发送给网络上的一个IP地址,如果这个IP地址已经被占用的话,那么使用位于这个IP地址的主机上的TCP/IP软件就能接受到这个ICMP回送请求,从而返回一个ICMP回送请求(类型号为0)信息。

信息封装在一个IP包中,我们需要解析该IP包,从中找到ICMP数据信息,相反,如果这个IP地址没有人使用,那么发送的ICMP回送请求在设定的延时内就不可能得到响应。

2.2数据结构设计

2.2.1.IP头部数据结构

typedefstructiphdr{

unsignedintheadlen:

4;//ip头长度

unsignedintwersion:

4;//ip版本号

unsignedchartos;//服务类型

unsignedshorttotallen;//ip包总长度

unsignedshortid;//ip号

unsignedshortflag;//标记

unsignedcharttl;//生存时间

unsignedcharprot;//协议(UDPTCP)

unsignedshortchecksum;//校验和

unsignedintsourceip;//源ip

unsignedintdestip;//目的ip

}IpHeader;

2.2.2.ICMP头部数据结构

typedefstructicmphdr{

BYTEtype;//icmp类型码,回送请求的类型码为8

BYTEcode;//子类型码,保存与特定ICMP报文类型相关的细节信息

USHORTchecksum;//校验和

USHORTid;//ICMP报文id号

USHORTseq;//ICMP数据报的序列号

}Icmpheader;

 

2.3系统流程图

2.3.1.主流程图(图1)

2.3.2.子流程图(图2)

3详细设计

3.1ICMP报文分析

ICMP是一种差错和控制报文协议,用于传输错误报告和控制信息。

ICMP报文分为头部和数据部分。

ICMP报文封装在IP数据报中传输。

IP报头中的类型为1时,表示报文的数据部分为ICMP报文。

虽然ICMP报文由IP报文传输,但是并不能认为ICMP是IP的上层协议,而是IP协议的有机补充。

把ICMP报文放在IP包中,是要利用IP的转发功能。

类型(TYPE)是一个字节,表示ICMP消息的类型。

代码(CODE)也是一个字节,表示报文类型的下一步信息。

校验和共有两个字节,提供对整个ICMP报文的校验和(和IP报文类型的进一步信息)。

校验和共两个字节,提供对整个ICMP报文的校验和。

按照协议的功能来分,ICMP报文可以分为

[1].ICMP差错报文

包括目的不可达报告,超时报告,参数出错报告。

[2].ICMP控制报文

包括拥塞控制和源抑制报文,路游控制和重定向报文

[3].ICMP测试报文

包括请求应答报文,时戳请求应答报文。

本课程设计就是使用ICMP请求/应答报文来测试目的主机是否存在,请求者想某特定的主机发送请求,其中包含任选的数据。

目的主机收到请求后,发送应答报文。

在同一时刻,一台机器可以同时向多台主机发送请求报文。

ICMP报文格式如图3所示,ICMP回送报文格式如下图4所示。

类型

代码

校验和

数据区(变长)

类型(8,0)码(0)

校验和

标志位

序号

任选数据

图3.ICMP报文格式图4.ICMP回应报文格式

3.2程序功能分析

在初始化原始套接字之后,本程序就要开始在一个IP网段内寻找活动主机。

因为要寻找活动的主机可能很多,为节省时间可以采用多线程编程。

结合核心代码对程序的具体进行分析。

3.2.1使用原始套接字

为了实现发送/监听ICMP抱文,必须使用原始套接字,创建原始套接字的代码如下:

SOCKETsockraw;

sockraw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,wsa_flag_overlapped);

在WSASocket函数中,我们使用IPPROTO_ICMP表示接受ICMP数据包,为了使用发送接受超时设置(设置SO_RCVTIMEO或SO_SNDTIMEO),必须将标志位置为WSA_FLAG_OVERLAPPED。

然后调用setsockopt函数设置读取迟延。

在setsockopt函数中,sockraw是之前创建的原始套接字,设置SOL_SOCKET表明使用基本套接字处理ICMP抱文。

设置SO_RCVTIMEO表示使用接受超时设置,SOSNDTIMEO表示使用发送超时设置,在这里,超时时间均设置为1000ms。

3.2.2定义IP头部和ICMP头部数据结构

由于socket发送/捕获的是IP包,因此要分别定义IP头部的数据结构和ICMP头部的数据结构。

IP头部的数据结构和ICMP头部的数据结构在概要设计中已有分析。

3.2.3填充并发送请求类型的ICMP报文

#defineICMP_ECHO8//请求回送

#defineDEF_PACKET_SIZE32//缺省数据报长度

#defineMAX_PACKET1024//最大数据报长度

#charicmp_data[MAX_PACKET];//ICMP数据报最大可能长度

Memset(icmp_data,0,MAX_PACKET)//将数据报清空初始化

Intdatasize=DEF_PACKET_SIZE;//ICMP数据报报文体的额缺省长度

Datasize+=sizeof(icmpHeader);//加上ICMP数据头部

icmp_header*icmp_hdr;

char*datapart;

icmp_hdr=(icmpheader*)icmp_data;

icmp_hdr->type=icmp_echo;//设置类型

icmp_hdr->id=(ushort)getcurrentthreadid();//设置其ID号为当前线程号

datapart=icmp_data+sizeof(icmpheader);//计算出ICMP数据报的数据部分

memset(datapart,'A',datasize-sizeof(icmphearder));//填入数据

((IcmpHeader*)icmp_data)->seq=0;//序列号

((IcmpHeader*)icmp_data)->check_sum=0;//先将检验和置0

((IcmpHead*)icmp_data)->checksum=checksum(USHORT*)icmp_data,data_size);

Checksum为计算校验和的函数,设校验和初值为0,然后对数据每16位求异或,结果取反,便得校验和。

其代码如下:

unsingedlongcksum=0;

while(size>1)

{cksum+=*buffer++;

size-=sizeof(ushort);}

if(size)

{cksum+=*(uchar)buffer;}

cksum=(cksum>>16)+(cksum&0xffff);

cksum+=(cksum>>16);

return(ushort)(~cksum);

填充ICMP报文之后,应在ICMP报文之前加上IP报头并发送出去。

可调用下面的代码发送数据包。

注意,这里的dest是填入目的主机的IP地址的一个sockaddr_in数据结构,IP_STRING是目的的主机的IP地址字符串。

Structsockaddr_in_dest;

Dest.sin_family=AF_INET;

Dest.sin_addr.s_addr=inet_addr(IP_STRING);

Sendto(sockraw,icmp_data,datasize,0,(sockaddr*)&dest,sizeof(dest));

3.2.4解析数据包

如果所ping的目的主机存在,那么它会发出一个回送应答包。

这是一个IP包,受到后解析此数据包并获得其中的ICMP信息。

根据IP报头信息中的IP报头长度字段,就可以得到ICMP报文的真实地址。

ICMP数据包中的IP地址就是活动主机的IP。

代码分析如下:

#defineICMP_MIN8

#defineMAX_PING_PACKET_SIZE(MAX_PACKET+sizeof(IpHeader))

char*recvbuf=new[MAX_PING_PACKET_SIZE];

structsockaddr_indest,from,end;

intformlen=sizeof(from);

intbytes=recvfrom(sockraw,recvbuf,MAX_PACKET,0,(Structsockaddr*)&from,&fromlen)

ipheader*iphdr;

icmpheader*icmphdr;

unsignedshortiphdrlen;

iphdr=(ipheader*)buf;

iphdrlen=iphdr->headlen*4;//IP报头的长度

icmphdr=(icmpheader*)(buf+iphdrlen);//跳过IP头

//数据包太短丢弃

if(bytes

//不是回送请求(ping应答),丢弃

if(icmphdr->type!

=icmp_echo_reply)return;

//ID不相符,丢弃

if(icmphdr->id!

=(USHORT)getcurrentthreadid())return;

//输出正在使用的IP地址

cout<<"活动主机"<sin_addr)<

 

4测试结果

4.1遇到问题

[1]找不到头文件。

因为头文件存放位置错误。

[2]变量没有定义。

因为变量没有定义和变量名书写写错。

[3]指针书写错误。

[4]宏参数列表错误。

[5]结构体指针传递错误。

Cannotcovertfrom‘structiphdr*’to‘structicmphar*ip’

Ipheader*iphdr.因为缺少成员运算符”.”。

4.2测试结果

经反复调试,运行正常,运行结果如下(图5)

 

5结束语

回顾过去的一个星期,有紧张,有忙碌,有苦恼,也有欢笑,在不断的改进与努力中,终于可以实现利用ICMP发现网络上的活动主机。

通过这次课程设计,我加深了对ICMP协议的理解,巩固了课堂知识,为以后学习网络协议打下基础。

在课程设计中,我和搭档李宝详配合的很融洽,相互帮助,共同进步。

在调试过程中难免要出现一些问题,为了能够快速地确定错误的原因,尽快的排除程序逻辑错误,通常把程序错误划分为三种类型:

语法错误、运行错误和逻辑错误。

在这次网络课程设计中,也发生了这样那样的错误,如变量没有定义、缺少头文件。

通过查阅文献资料、请教老师和同学讨论,以及自己认真地分析与思考,逐一对错误进行了调试,使程序基本能正常运行,大体上符合了设计的意图和设计的要求。

由于网络协议比较抽象,比较难学,也学得不深入,何况还要把所学知识运用到实践中来,真是一大难题,所以一开始时,真是有点一筹莫展,网上查有关资料却总觉得不搭干。

通过这次课程设计,我明白做什么事都要沉得下心,在搞任何研发工作时,遇到问题沉着冷静是特别重要的,千万不能有半点浮躁的心情。

在程序的调试过程中,出现问题是正常的,关键是如何去发现问题的根源,然后去解决它。

其实写程序并不是很花时间,改错才是最花时间的的事情。

还有一点特别重要的是,在设计过程中或者是改错的过程中遇到棘手的问题时,借助网络去解决的确是一种很好的选择。

一个星期的课程设计,我过的很充实,感觉每天都在学习,每天都在进步,在课程设计完成之际,我在此向所有关心我帮助我的刘老师和同学们致以最真诚的感谢。

在这次课程设计中,我从刘老师身上学到了很多东西,他认真负责,知识丰富,要求严格,无论在理论上还是在系统调试中,都给与我很大的帮助,使我得到很大的提高,这对于我以后的工作和学习都有一种巨大的帮助,在此再次感谢刘老师耐心的耐心辅导。

 

参考文献

[1]吴功宜,胡晓英等著.计算机网络课程设计.北京:

机械工业出版社。

2005

[2]周明天等,TCP/IP网络原理与技术.北京:

清华大学出版社.

[3]陈坚,陈伟.VisualC++网络高级编程[M].北京:

人民邮电出版社,2001.

[4]方路平,曹平,林毅,等采用IP多址广播技术的应用系统开发[J].计算机系统应用,2001

[5]蒋东兴.WindowsSockets网络程序设计大全[M].北京:

清华大学出版社,1999.

 

附录及源代码

1.scanhost.h

#pragmapack(4)

#pragmacomment(lib,"Ws2_32.lib")

#definewin32_LEAN_AND_MEAN

#include

#include

#include

#include

#include

#include

//THEIPHEADER

typedefstructiphdr{

unsignedintheadlen:

4;//ip头长度

unsignedintwersion:

4;//ip版本号

unsignedchartos;//服务类型

unsignedshorttotallen;//ip包总长度

unsignedshortid;//ip号

unsignedshortflag;//标记

unsignedcharttl;//生存时间

unsignedcharprot;//协议(UDPTCP)

unsignedshortchecksum;//校验和

unsignedintsourceip;//源ip

unsignedintdestip;//目的ip

}IpHeader;

//ICMPHEADER

typedefstructicmphdr{

BYTEtype;//icmp类型码,回送请求的类型码为8

BYTEcode;//子类型码,保存与特定ICMP报文类型相关的

//节信息

USHORTchecksum;//校验和

USHORTid;//ICMP报文id号

USHORTseq;//ICMP数据报的序列号

}Icmpheader;

#defineICMP_ECHO8//请求回送

#defineICMP_ECHO_REPLY0//请求回应

#defineICMP_MIN8//ICMP包头长度(最小ICMP包长度)

#defineSTATUS_FAILED0xFFFF//错误码

#defineDEF_PACKET_SIZE32//缺省数据报长度

#defineMAX_PACKET1024//最大数据报长度

#defineMAX_PING_PACKET_SIZE(MAX_PACKET+sizeof(IpHeader))//最大接受数据报长度

voidfill_icmp_date(char*,int);//填充ICMP包

USHORTchecksum(USHORT*,int);//校验和函数

voiddecode_resp(char*,int,structsockaddr_in*);//找到此数据报IP地址

DWORDWINAPIFindIp(LPVOIDpipaddrtemp);//线程调用子函数

2.scanhost.cpp

#include"scanhost.h"

WSADATAwsadata;

SOCKETsockraw;

structsockaddr_indest,from,end;

intfromlen=sizeof(from);

char*recvbuf=newchar[MAX_PING_PACKET_SIZE];

unsignedintaddr=0;

longthreadnumcounter=0,threadnumlimit=20;

long*aa=&threadnumcounter;

voidmain(intargc,char*argv[]){

if(argc!

=3){

cout<<"输入格式错误:

scanhoststart_ipend_ip"<

return;

}

if(WSAStartup(MAKEWORD(2,1),&wsadata)!

=0){

cout<<"WSAStartupfailed:

"<

ExitProcess(STATUS_FAILED);

}

//创建原始套接字

sockraw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);

if(sockraw==INVALID_SOCKET){

cout<<"WSASocket()failed:

"<

ExitProcess(STATUS_FAILED);

}

//设置读取延时

inttimeout=1000;

intbread=setsockopt(sockraw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));

if(bread==SOCKET_ERROR){

cout<<"failtosetrecvtimeout:

"<

ExitProcess(STATUS_FAILED);

}

timeout=1000;

bread=setsockopt(sockraw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));

if(bread==SOCKET_ERROR){

cout<<"failedtosetsendtimeout:

"<

ExitProcess(STATUS_FAILED);

}

memset(&dest,0,sizeof(dest));

unsignedlongstartip,endip;

dest.sin_family=AF_INET;

dest.sin_addr.s_addr=inet_addr(argv[1]);

startip=inet_addr(argv[1]);

end.sin_family=AF_INET;

end.sin_addr.s_addr=inet_addr(argv[2]);

endip=inet_addr(argv[2]);

HANDLEhthread;

while(htonl(startip)<=htonl(endip)){

if(threadnumcounter>threadnumlimit){

Sleep(5000);

continue;

}

DWORDThreadid;

sockaddr_in*pipaddrtemp=new(sockaddr_in);

if(!

pipaddrtemp){

cout<<"memoryallocfailed"<

return;

}

*pipaddrtemp=dest;

//创建新线程

clock_tstart;

start=clock();

hthread=CreateThread(NULL,NULL,FindIp,(LPVOID)pipaddrtemp,NULL,&Threadid);

longi=60000000L;

while

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 畜牧兽医

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1