使用ICMP探查网络活动主机程序

需积分: 10 11 下载量 164 浏览量 更新于2024-09-11 3 收藏 6KB TXT 举报
"发现网络中的活动主机源程序是一款利用ICMP协议进行网络主机探测的应用,它能够自动向指定网段内的所有IP地址发送ICMP消息,并根据收到的回应列出活动主机。程序通过封装和解析ICMP数据报文,实现网络扫描功能,无需在DOS环境下执行ping命令。" 在编程领域,特别是网络编程中,ICMP(Internet Control Message Protocol,互联网控制消息协议)是TCP/IP协议栈的一个重要组成部分,用于在IP网络中传输错误和控制信息。例如,我们熟知的ping命令就是基于ICMP协议来检测网络连通性的。 该源程序的主要工作流程如下: 1. **初始化网络连接**:首先,程序需要初始化Winsock库,这通常是通过调用`WSAStartup`函数完成的,以确保网络编程所需的服务就绪。在给定的代码中,`WSADATA wsaData`变量用于存储初始化结果。 2. **创建原始套接字**:为了发送和接收ICMP数据报文,程序需要创建一个原始套接字。原始套接字允许应用程序直接处理IP头部,而不只是应用层协议(如TCP或UDP)。在Windows中,使用`socket`函数创建套接字,类型为`SOCK_RAW`。 3. **设置目的地址**:程序定义了结构体`struct sockaddr_in dest`来存储目标主机的IP地址和端口信息,以便于向特定主机发送ICMP请求。 4. **填充ICMP数据**:`fill_icmp_data`函数用于生成ICMP数据包的内容,包括 ICMP 请求的类型(如 ICMP_ECHO8 表示回显请求)和其他相关字段。 5. **计算校验和**:`checksum`函数用于计算ICMP数据报文的校验和,这是ICMP协议规范的一部分,确保数据在传输过程中没有被篡改。 6. **发送ICMP请求**:使用创建的原始套接字,程序可以调用`sendto`函数将封装好的ICMP数据报文发送到目标主机。 7. **接收ICMP响应**:程序创建一个缓冲区`recvbuf`来接收响应,设置`fromlen`为`sizeof(from)`以存储接收方的地址信息,然后使用`recvfrom`函数等待并接收ICMP响应。 8. **解析响应**:接收到ICMP响应后,`decode_resp`函数解析响应数据,提取相关信息,例如类型、代码、ID、序列号等。 9. **处理结果**:根据解析出的响应,判断目标主机是否活跃。如果收到回应,则说明该IP地址上存在活动主机。 10. **结束并清理**:最后,程序可能需要释放分配的内存,关闭套接字,并调用`WSACleanup`来清理Winsock环境。 这个源程序提供了一种自动化的方法来探测网络中的活动主机,对于网络管理员来说,这是一个非常实用的工具,能够快速了解网络状况,找出可能存在的在线设备。同时,它也展示了如何在Windows环境下利用原始套接字进行低级别的网络通信。
2008-12-21 上传
#pragma pack(4) //#include "stdafx.h" #pragma comment (lib,"Ws2_32.lib") #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include typedef struct iphdr { unsigned int headlen:4; unsigned int version:4; unsigned char tos; unsigned short totallen; unsigned short id; unsigned short falg; unsigned char ttl; unsigned char prot; unsigned short checksum; unsigned int sourceIP; unsigned int destIP; }IpHeader; typedef struct icmphdr { BYTE type; BYTE code; USHORT checksum; USHORT id; USHORT seg; }IcmpHeader; #define ICMP_RCHO 8 #define ICMP_RCHO_REPLY 0 #define ICMP_MIN 8 #define STATUS_FAILED 0xFFFF #define DEF_PACKET_SIZE 32 #define MAX_PACKET 1024 #define MAX_PING_PACKET_SIZE (MAX_PACKET+sizeof(IpHeader)) void fill_icmp_data(char *,int); USHORT checksum(USHORT *,int); void decode_resp(char *,int,struct sockaddr_in *); DWORD WINAPI FindIP(LPVOID pIPAddrTemp); WSADATA wsaData; SOCKET sockRaw; struct sockaddr_in dest,from,end; int fromlen =sizeof(from); char *recvbuf=new char[MAX_PING_PACKET_SIZE]; unsigned int addr=0; long ThreadNumCounter=0,ThreadNumLimit=20; long *aa=&ThreadNumCounter; void main(int argc,char *argv[]) { /*if(argc!=3) { cout<<"输入格式错误: start_ip end_ip"<<endl; return; }*/ if(WSAStartup(MAKEWORD(2,1),&wsaData)!=0) { cout<<"WASStartup failed"<<GetLastError()<<endl; ExitProcess(STATUS_FAILED); } sockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED); if(sockRaw==INVALID_SOCKET) { cout<<"WASSocketet() falied"<<WSAGetLastError()<<endl; ExitProcess(STATUS_FAILED); } int timeout=1000; int bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout)); if(bread==SOCKET_ERROR) { cout<<"FAILED TO SEY RECV TIMEOUT"<<WSAGetLastError()<<endl; ExitProcess(STATUS_FAILED); } timeout=1000; bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout)); if(bread==SOCKET_ERROR) { cout<<"FAILED TO SEY RECV TIMEOUT"<<WSAGetLastError()<<endl; ExitProcess(STATUS_FAILED); } memset(&dest,0,sizeof(dest)); unsigned long startIP,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]); HANDLE hThread; while(htonl(startIP)ThreadNumLimit) { Sleep(5000); continue; } DWORD ThreadID; sockaddr_in *pIPAddrTemp=new (sockaddr_in); if(!pIPAddrTemp) { cout<<"memory alloc failed"<<endl; return ; } *pIPAddrTemp=dest; clock_t start; start=clock(); hThread=CreateThread(NULL,NULL,FindIP,(LPVOID)pIPAddrTemp,NULL,&ThreadID); long i=60000000L; while(i--); TerminateThread(hThread,0); InterlockedDecrement(aa); memset(&from,0,sizeof(from)); startIP=htonl(htonl(startIP)+1); dest.sin_addr.s_addr=startIP; } while(ThreadNumCounter!=0) { Sleep(2000); return; cout<<"error"<type=ICMP_RCHO; icmp_hdr->id=(USHORT)GetCurrentThreadId(); datapart=icmp_data+sizeof(IcmpHeader); memset(datapart,'A',datasize-sizeof(IcmpHeader)); } void decode_resp(char *buf,int bytes,struct sockaddr_in *from) { IpHeader *iphdr; IcmpHeader *icmphdr; unsigned short iphdrlen; iphdr=(IpHeader*) buf; iphdrlen=iphdr->headlen*4; icmphdr=(IcmpHeader *)(buf+iphdrlen); if(bytestype!=ICMP_RCHO_REPLY)return; if(icmphdr->id!=(USHORT)GetCurrentThreadId())return; cout<<"活动主机: "<<endl; cout<<" "<sin_addr)<1) { cksum+=*buffer++; size-=sizeof(USHORT); } if(size) { cksum+=*(UCHAR*)buffer; } cksum=(cksum>>16)+(cksum& 0xffff); cksum+=(cksum>>16); return (USHORT)(~cksum); } DWORD WINAPI FindIP(LPVOID pIPAddrTemp) { InterlockedIncrement(aa); char icmp_data[MAX_PACKET]; memset(icmp_data,0,MAX_PACKET); int datasize=DEF_PACKET_SIZE; datasize+=sizeof(IcmpHeader); fill_icmp_data(icmp_data,datasize); ((IcmpHeader*)icmp_data)->checksum=0; ((IcmpHeader*)icmp_data)->seg=0; ((IcmpHeader*)icmp_data)->checksum=checksum((USHORT*)icmp_data,datasize); int bwrote=sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr *)pIPAddrTemp,sizeof(dest)); int n=0; if(bwrote==SOCKET_ERROR) { if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"timed out"<<endl; } cout<<"sendto failies"<<WSAGetLastError()<<endl; ExitProcess(STATUS_FAILED); n=1; } if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"timed out"<<endl; ExitProcess(STATUS_FAILED); n=1; } if(bwrote<datasize) { cout<<"Worte"<<bwrote<<"bytes"<<endl; ExitProcess(STATUS_FAILED); n=1; } int bread=recvfrom(sockRaw,recvbuf,MAX_PING_PACKET_SIZE,0,(struct sockaddr *)&from,&fromlen); if(bread==SOCKET_ERROR) { if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"timed out"<<endl; } cout<<"recvfrom falied"<<WSAGetLastError()<<endl; ExitProcess(STATUS_FAILED); n=1; } if(n==0) { decode_resp(recvbuf,bread,&from); InterlockedDecrement(aa); } return 0; }