ronnie
{ int cd1=0;int cd2=0;int ci1=0;int ci2=0; char c1[4],c2[4]; while (*starthost!='\\0'&&*endhost!='\\0') { if (*starthost!='\\0') { if (cd1<3) { if(*starthost=='.') ++cd1; } else { c1[ci1]=*starthost; ++ci1; } ++starthost; } if(*endhost!='\\0') { if (cd2<3) { if(*endhost=='.') ++cd2; } else { c2[ci2]=*endhost; ++ci2; } ++endhost; } } c1[3]=c2[3]='\\0'; *start=atoi(c1); *end=atoi(c2); }
//将当前IP低三位与网段号组装,用于发送ICMP的目的主机IP地址 char* Assemble(char starthost[],int cur) { int i=0,cd=0;char appendix[4],*tmp=starthost; itoa(cur,appendix,10);
26
ronnie
//printf(\ while (cd<3) { if (*tmp=='.') ++cd; ++tmp; } *tmp='\\0'; strcat(starthost,appendix); return starthost; }
//计算检验和
unsigned short checksum(unsigned short *buffer, int size) { unsigned long cksum=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); }
//利用TCP connect()方法对目的主机的指定端口范围扫描 void ConnectScan(int startport,int endport,char hostname[]) { int i,status; SOCKET sock=INVALID_SOCKET; strncpy((char *)&dest,\ dest.sin_family = AF_INET; InitializeWinsock(); Resolove(hostname); printf(\
27
ronnie
printf(\for(i = startport ; i<= endport ; i++) { sock = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP); //创建一个Socket if(sock==INVALID_SOCKET) { printf(\ exit(EXIT_FAILURE); } }
//主机字节序转换为网络字节序 dest.sin_port = htons(i);
//用此Socket连接目的主机,核心代码
status = connect(sock , (struct sockaddr *)&dest , sizeof dest);
if(status == SOCKET_ERROR) //连接失败 { switch(WSAGetLastError()) { case 10060: printf(\ break; case 10061: printf(\ break; default: printf(\ break; } //fflush(stdout); }
else //连接成功 { printf(\ //关闭收发服务 if( shutdown( sock ,SD_BOTH ) == SOCKET_ERROR ) { printf(\ exit(EXIT_FAILURE); } }
closesocket(sock); //关闭Socket,回收资源
28
ronnie
}
//利用ICMP进行网段扫描
void SegmentScan(char starthost[],char endhost[]) { int status, //记录状态信息 tick, //获取当前系统启动时间的毫秒数 start, //起始网络号 end, //结尾网络号 i; //用于for循环等 WSADATA wsa; //char starthost[50],endhost[50]; SOCKET sock=INVALID_SOCKET; char recvBuf[1024*5]; //设置接收缓冲区,这里设为5K ICMP_HDR* icmp_hdr,*recv_icmp; //发送和接收的ICMP报文首部定义 unsigned short nSeq = 0; int nLen = sizeof(from); //创建ICMP数据包 char buff[sizeof(ICMP_HDR) + 32]; icmp_hdr = (ICMP_HDR*)buff; //加载动态链接库 InitializeWinsock(); //创建原始套接字 //AF_INET表示地址族为IPV4, //SOCK_RAW表示创建的为原始套接字,注意若在UNIX/LINUX环境下 //应该获得root权限,在Windows环境下使用管理员权限运行程序 //协议参数填写ICMP协议 sock=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); if (sock == INVALID_SOCKET) { if (WSAGetLastError()==10013) { //错误代码为10013,原因是权限不够 printf(\ exit(EXIT_FAILURE); } }
29
ronnie
//填写目的主机相关信息,不需要填写端口,因为ICMP是网络层协议 dest.sin_family=AF_INET; ResoloveIPAddr(starthost,endhost,&start,&end); printf(\ printf(\ for (i=start;i<=end;i++) { //printf(\ Resolove(Assemble(starthost,i)); //printf(\ //填充ICMP包 InitIcmpHeader(icmp_hdr); //icmp_hdr->icmp_checksum=0; //icmp_hdr->icmp_timestamp = GetTickCount(); icmp_hdr->icmp_sequence=i; icmp_hdr->icmp_checksum=checksum((unsigned short*)buff, sizeof(ICMP_HDR) + 32); // 开始发送和接收ICMP封包 status=sendto(sock, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest)); if(status==SOCKET_ERROR) { printf(\ exit(EXIT_FAILURE); } //接受回显回答 status=recvfrom(sock,recvBuf,1024*5,0,(SOCKADDR*)&from,&nLen); if(status==SOCKET_ERROR) { if(WSAGetLastError()==WSAETIMEDOUT) { printf(\ exit(EXIT_FAILURE); } printf(\ exit(EXIT_FAILURE); } // 接收到的数据中包含IP头,IP头大小为20个字节,所以加20得到ICMP头 recv_icmp=(ICMP_HDR*)(recvBuf+20); tick=GetTickCount(); //判断回显报是否符合长度 if (status 30