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


// FinScan.cpp : 定义控制台应用程序的入口点。 
// 
#include "stdafx.h" 
#include  
 
#include  
#include "FinScan.h" 
#include "ws2tcpip.h" 
//#include "mstcpip.h" 
 
#pragma comment(lib,"ws2_32.lib")  
 
#define Port_Src 2233 
#define SEQ 2315 
 
USHORT FinScan::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 FinScan::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  = 1;                         //  Fin = 2;ack = 0; means Fin 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));            //计算IP头校验和 
	((IPV4_HDR *)&buf)->ip_checksum = ip_hdr.ip_checksum; 
 
	ret = sendto(s, buf, sizeof(IPV4_HDR)+sizeof(TCP_HDR), 0, (struct sockaddr*) &dst_addr,sizeof(dst_addr));  //发送Fin报文 
	if (ret == SOCKET_ERROR) {  
		sprintf(msg_buf,"Scan Port %d: Fin 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: Fin 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){                                 //是否RST包 
		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){                                //ack位检测 
		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); 
} 
 
int main() 
{	 
	char result[500]; 
	result[0] = '\0'; 
	char* ip_dest = "192.168.1.5"; 
	FinScan* test = new FinScan(); 
	test->Scan(ip_dest,25,1000,result); 
	std::cout<