www.pudn.com > PortScan_sjtu.rar > SYNScan.cpp


// SYNScan.cpp : 定义控制台应用程序的入口点。 
// 
#include "stdafx.h" 
#include  
 
#include  
#include "SYNScan.h" 
#include "ws2tcpip.h" 
#include "mstcpip.h" 
 
#pragma comment(lib,"ws2_32.lib")  
 
#define Port_Src 2233 
#define SEQ 2315 
 
USHORT SYNScan::checksum(USHORT *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); 
} 
 
int SYNScan::Scan(char* IP_Dest, int Port_Dst, u_int time_out, char* msg) 
{ 
	char msg_buf[100]; 
	WSADATA wsa; 
	SOCKET s; 
	char buf[256]; 
	char recv_buf[256]; 
	struct sockaddr_in src_addr,dst_addr; 
 
	int ret = WSAStartup(MAKEWORD(2,2), &wsa); 
	s = socket(AF_INET , SOCK_RAW , IPPROTO_IP); 
	int flag = 1;   
 
	ret = setsockopt(s, IPPROTO_IP,IP_HDRINCL ,(char *)&flag, sizeof(flag));     //socket选项,手动定义IP头 
	if (ret==SOCKET_ERROR) { 
		sprintf(msg_buf,"Scan Port %d: setopt:syn Error %d\r\n", Port_Dst,WSAGetLastError()); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return (-1); 
	}  
 
	ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&time_out, sizeof(time_out)); 
	if (ret==SOCKET_ERROR) { 
		sprintf(msg_buf,"Scan Port %d: 无法设置套接字的接受超时时间!\r\n",Port_Dst); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return (-1); 
	} 
 
	ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&time_out, sizeof(time_out)); 
	if (ret==SOCKET_ERROR) { 
		sprintf(msg_buf,"Scan Port %d: 无法设置套接字的发送超时时间!\r\n",Port_Dst); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return (-1); 
	} 
 
	dst_addr.sin_family = AF_INET; 
	dst_addr.sin_port = htons(Port_Dst); 
	dst_addr.sin_addr.s_addr = inet_addr(IP_Dest); 
 
	char host_name[100];                        //取得主机地址 
	gethostname(host_name, sizeof(host_name)-1); 
	LPHOSTENT host = gethostbyname(host_name); 
 
	src_addr.sin_addr = *(in_addr *)host->h_addr; 
 
	IPV4_HDR ip_hdr;                     //IP头设置 
 
	ip_hdr.ip_verlen = (4<<4 | sizeof(IPV4_HDR)/sizeof(unsigned long)); 
	ip_hdr.ip_tos = 0; 
	ip_hdr.ip_totallength = htons(sizeof(IPV4_HDR)+sizeof(TCP_HDR)); 
	ip_hdr.ip_id = 1; 
	ip_hdr.ip_offset = 0; 
	ip_hdr.ip_ttl = 128; 
	ip_hdr.ip_protocol = IPPROTO_TCP; 
	ip_hdr.ip_checksum = 0; 
	ip_hdr.ip_srcaddr = src_addr.sin_addr.s_addr; 
	ip_hdr.ip_destaddr = inet_addr(IP_Dest); 
 
	TCP_HDR tcp_hdr;                       //Tcp头设置 
 
	tcp_hdr.th_sport = htons(Port_Src);              
	tcp_hdr.th_dport = htons(Port_Dst);        
	tcp_hdr.th_seq   = htonl(SEQ);       
	tcp_hdr.th_ack   = 0;            
	tcp_hdr.th_lenres= (sizeof(TCP_HDR)/4<<4|0);     
	tcp_hdr.th_flag  = 2;                         //  SYN = 2;ack = 0; means SYN scan  
	tcp_hdr.th_win   = htonl(512);              
	tcp_hdr.th_checksum   = 0;                
	tcp_hdr.th_urp   = 0;         
 
	IP_PSD_HDR psd_hdr;                  //伪IP头设置 
 
	psd_hdr.src_addr = src_addr.sin_addr.s_addr; 
	psd_hdr.dest_addr = inet_addr(IP_Dest); 
	psd_hdr.mbz = 0; 
	psd_hdr.protocol  = IPPROTO_TCP;             
	psd_hdr.tcplength  = htons(sizeof(TCP_HDR));  
 
	memcpy(buf, &psd_hdr, sizeof(IP_PSD_HDR)); 
	memcpy(buf + sizeof(IP_PSD_HDR), &tcp_hdr, sizeof(TCP_HDR));  
	tcp_hdr.th_checksum = checksum((u_short *)buf, sizeof(IP_PSD_HDR)+sizeof(TCP_HDR));   //计算Tcp头校验和 
 
	memcpy(buf, &ip_hdr, sizeof(IPV4_HDR));  
	memcpy(buf + sizeof(IPV4_HDR), &tcp_hdr, sizeof(TCP_HDR));  
	memset(buf + sizeof(IPV4_HDR) + sizeof(TCP_HDR), 0, 4);	 
 
	ip_hdr.ip_checksum = checksum((u_short *)buf, sizeof(IPV4_HDR)+sizeof(TCP_HDR));  
	((IPV4_HDR *)&buf)->ip_checksum = ip_hdr.ip_checksum;         //计算IP头校验和 
 
	ret = sendto(s, buf, sizeof(IPV4_HDR)+sizeof(TCP_HDR), 0, (struct sockaddr*) &dst_addr,sizeof(dst_addr));  //发送Syn包 
	if (ret == SOCKET_ERROR) {  
		sprintf(msg_buf,"Scan Port %d: Syn send error %d!\r\n",Port_Dst,WSAGetLastError()); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return (-1); 
	} 
 
	int src_len = sizeof(src_addr); 
 
	ret = recvfrom(s, (char *)&recv_buf, sizeof(recv_buf), 0, (SOCKADDR *)&src_addr, &src_len);  //接受回复 
 
	if (ret==SOCKET_ERROR) { 
		sprintf(msg_buf,"Scan Port %d: Syn Reply recv error %d!\r\n",Port_Dst,WSAGetLastError()); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return (-1); 
	} 
	int recv_len = ret;          //回复包分析 
 
	if (recv_len < sizeof(IPV4_HDR)){          
		sprintf(msg_buf,"Scan Port %d: Syn Reply IPHEADER error!\r\n",Port_Dst); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return (-1); 
	} 
	IPV4_HDR *ip_hdr_recv = (IPV4_HDR *)recv_buf;               //回复报文IP头分析 
 
	int ip_hdr_recv_len = ip_hdr_recv->ip_verlen & 0x0F; 
	ip_hdr_recv_len = (ip_hdr_recv_len) << 2; 
 
	if (checksum((u_short *)ip_hdr_recv, ip_hdr_recv_len)) { 
		sprintf(msg_buf,"Scan Port %d: Syn Reply checksum error!\r\n",Port_Dst); 
		strcat(msg,msg_buf); 
		WSACleanup(); 
		return(-1); 
	} 
 
	if (recv_len < (ip_hdr_recv_len + sizeof(TCP_HDR))) {             //校验和 
		sprintf(msg_buf,"Scan Port %d: Syn Reply TCPHEADER recv error!\r\n",Port_Dst); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
	TCP_HDR *tcp_hdr_recv = (TCP_HDR *) (recv_buf + ip_hdr_recv_len);     //回复报文TCP头分析 
 
	if ((tcp_hdr_recv->th_flag & 0x04) > 0){ 
		sprintf(msg_buf,"Scan Port %d: Syn connect is rejected!\r\n",Port_Dst); 
		strcat(msg,msg_buf); 
		WSACleanup(); 
		return(-1); 
	} 
 
	if ((tcp_hdr_recv->th_flag & 0x10) == 0){                         //标志位 
		sprintf(msg_buf,"Scan Port %d: Syn reply ack error!\r\n",Port_Dst); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
 
 
	if (ntohl(tcp_hdr_recv->th_ack) != (SEQ+1) ){                     //是否对刚发出去的报文的ack 
		sprintf(msg_buf,"Scan Port %d: Syn reply ack sequence error!\r\n",Port_Dst); 
		strcat(msg,msg_buf); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
 
 
	sprintf(msg_buf,"Scan Port %d: Syn scan succeed!\r\n",Port_Dst); 
	strcat(msg,msg_buf); 
	WSACleanup(); 
	return (0); 
}