⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpsynscan.cpp

📁 “网络安全技术实践与代码详解”实例代码
💻 CPP
字号:
#include   <winsock2.h>   
#include   <ws2tcpip.h>   
#include   <stdio.h>   

#include   <time.h>   
#include   "mstcpip.h"   
#pragma   comment(lib,"ws2_32.lib")   
#define   SEQ   0x27456737   // 伪造的序列号

SOCKET   sockRaw;      // 发送SYN扫描数据包套接字
SOCKET   sockListen;   // 监听目标主机返回数据包套接字
struct   sockaddr_in   targethost;  // 目标主机地址结构
BOOL     ScanFIN=FALSE;    // 是否扫描完毕
char     TargetIP[20];     // 目标机IP地址
int      TargetPort;       // 目标机起始端口
int      TargetPortEnd;    // 目标机结束端口
int      ProgressTag=0;    // 进度条标志位  


// 定义IP首部格式
typedef   struct   _iphdr     
{   
	unsigned   char   h_lenver;     //4位首部长度+4位IP版本号   
	unsigned   char   tos;          //8位服务类型TOS   
	unsigned   short   total_len;   //16位总长度(字节)   
	unsigned   short   ident;       //16位标识   
	unsigned   short   frag_and_flags;   //3位标志位   
	unsigned   char   ttl;          //8位生存时间   TTL   
	unsigned   char   proto;        //8位协议   (TCP,   UDP   或其他)   
	unsigned   short   checksum;    //16位IP首部校验和   
	unsigned   int   sourceIP;      //32位源IP地址   
	unsigned   int   destIP;        //32位目的IP地址   
}IP_HEADER;   

//定义TCP首部格式
typedef   struct   _tcphdr     
{   
	USHORT   th_sport;   //16位源端口   
	USHORT   th_dport;   //16位目的端口   
	unsigned   int   th_seq;   //32位序列号   
	unsigned   int   th_ack;   //32位确认号   
	unsigned   char   th_lenres;   //4位首部长度/6位保留字   
	unsigned   char   th_flag;    //6位标志位   
	USHORT   th_win;   //16位窗口大小   
	USHORT   th_sum;   //16位校验和   
	USHORT   th_urp;   //16位紧急数据偏移量   
}TCP_HEADER;     

// 定义TCP伪首部格式 
struct     
{   
	unsigned   long   saddr;   //源地址   
	unsigned   long   daddr;   //目的地址   
	char   mbz;   
	char   ptcl;   //协议类型   
	unsigned   short   tcpl;   //TCP长度   
}psd_header;   

void   usage(void)   
{    
	printf("\tusage:     TCPSYNScan   [IP | DomainName]   [StartPort-EndPort] \n");   
	printf("\tExample:   TCPSYNScan   www.sohu.com   1-139\n");   
	printf("\tExample:   TCPSYNScan   192.168.0.1   1-1024\n");   
}   

void ParseCmd(int argc,char **argv)
{
	char   *p;   
	if(argc!=3)   
	{   
		usage();   
		ExitProcess(-1);
	}   
    // 提取端口参数
	p=argv[2]; 
	if(strstr(argv[2],"-"))   
	{         TargetPort=atoi(argv[2]);   
	for(;*p;)   
		if(*(p++)=='-')
		{
			break;
		}
		TargetPortEnd=atoi(p);   
		
		if(TargetPort<1   ||   TargetPortEnd>65535)   
		{         
			printf("端口范围错误(1-65535) !\n");   
			ExitProcess(-1);   
		}   
		
	}
	// 设置目标机IP地址
    strcpy(TargetIP,argv[1]);   
}

//SOCK错误处理程序   
void   CheckSockError(int   iErrorCode,   char   *pErrorMsg)   
{   
	if(iErrorCode==SOCKET_ERROR)   
	{   
		printf("%s   Error:%d\n",   pErrorMsg,   GetLastError());   
		closesocket(sockRaw);   
		ExitProcess(-1);   
	}       
}   

//计算检验和   
USHORT   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);   
}   

//IP解包程序   
bool   DecodeIPPack(char   *buf,   int   bytes)   
{   
	IP_HEADER   *iphdr;   
	TCP_HEADER   *tcphdr;   
	unsigned   short   iphdrlen;   
	iphdr   =   (IP_HEADER   *)buf;   
	iphdrlen   =   sizeof(unsigned   long)   *   (iphdr->h_lenver   &   0xf);   
	tcphdr   =   (TCP_HEADER*)(buf   +   iphdrlen);   
	//是否来自目标IP   
	if(iphdr->sourceIP   !=   targethost.sin_addr.s_addr)
	{
		return  false;
	}
	//序列号是否正确   
	if((ntohl(tcphdr->th_ack)   !=   (SEQ+1))   &&   (ntohl(tcphdr->th_ack)   !=   SEQ))
	{
		return   false;
	}
	// 18表示 SYN/ACK
	if(tcphdr   ->th_flag   ==   18)   
	{   
		printf("端口 %5d  开放!   \n",ntohs(tcphdr->th_sport));   
		return   true;   
	}     
	return   true;   
}   





//接收数据包线程函数  
DWORD   WINAPI   RecvThread(LPVOID   para)
{   
	int   iErrorCode;   
	struct   hostent   *hp;   
	char   RecvBuf[65535]={0};   
	sockListen   =   socket(AF_INET, SOCK_RAW, IPPROTO_IP);   
	CheckSockError(sockListen,   "socket");   
    
	//设置IP头操作选项   
	BOOL   bOpt   =   true;   
	iErrorCode   =   setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char   *)&bOpt,sizeof(bOpt));   
	CheckSockError(iErrorCode,   "setsockopt()");     
    
	//获得本地IP   
	SOCKADDR_IN   sa;   
	unsigned   char   LocalName[256];   
    // 获取主机信息
	iErrorCode   =   gethostname((char*)LocalName,sizeof(LocalName)-1);   
	CheckSockError(iErrorCode,   "gethostname()");   
	if((hp   =   gethostbyname((char*)LocalName))   ==   NULL)   
	{   
		CheckSockError(SOCKET_ERROR,   "gethostbyname()");   
	}   
	memcpy(&sa.sin_addr.S_un.S_addr,hp->h_addr_list[0],hp->h_length);   
	sa.sin_family   =   AF_INET;   
	sa.sin_port   =   htons(7000);   
	iErrorCode   =   bind(sockListen,   (PSOCKADDR)&sa,   sizeof(sa));   
	CheckSockError(iErrorCode,   "bind");   
    
	//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包   
	DWORD   dwBufferLen[10]   ;   
	DWORD   dwBufferInLen   =   1   ;     
	DWORD   dwBytesReturned   =   0   ;
	// 设置套接字接收全部数据包
	iErrorCode=WSAIoctl(sockListen, SIO_RCVALL,
		&dwBufferInLen, sizeof(dwBufferInLen),
		&dwBufferLen, sizeof(dwBufferLen),
		&dwBytesReturned , NULL , NULL   );   
	CheckSockError(iErrorCode,   "Ioctl");   
	memset(RecvBuf, 0, sizeof(RecvBuf));   
	//接收数据   
	for(;;)   
	{   
		
		iErrorCode   =   recv(sockListen,   RecvBuf,   sizeof(RecvBuf),   0);    
		DecodeIPPack(RecvBuf,iErrorCode); // 解析IP数据包   
	}   
	if(ScanFIN)   
	{   
		closesocket(sockListen);   
		return   0;   
	}   
}   
// 定义状态提示函数 
void   ProgressShow(void)    
{     
	//   进度条     
	char   *progressbar[12]=     
	{     
		"   |   ",     
			"   /   ",     
			"   -   ",     
			"   \\   ",     
			"   |   ",     
			"   /   ",     
			"   -   ",     
			"   \\   ",     
			"   |   ",     
			"   /   ",     
			"   -   ",     
			"   \\   ",     
	};     
	printf("   =%s=\r",   progressbar[ProgressTag]);   
	ProgressTag=(ProgressTag==11)?0:ProgressTag+1;   
	Sleep(2);   
}     

//主函数   
int   main(int   argc,char   **argv)   
{   
	int   iErrorCode;   
	int   datasize;   
	struct   hostent   *hp;   
	IP_HEADER   ip_header;   
	TCP_HEADER   tcp_header;   
	char   SendBuf[128]={0};
	ParseCmd(argc, argv);
     
	WSADATA   wsaData;
	// 初始化Winsock库
	iErrorCode   =   WSAStartup(MAKEWORD(2,2),&wsaData);   
	CheckSockError(iErrorCode,   "WSAStartup()");
	// 创建发送数据包套接字
	sockRaw   =   socket(AF_INET   ,   SOCK_RAW   ,   IPPROTO_IP);   
	CheckSockError(sockRaw,   "socket()");
	// 创建接收数据包套接字
	sockListen   =   socket(AF_INET   ,   SOCK_RAW   ,   IPPROTO_IP);   
	CheckSockError(sockListen,   "socket");   
    
	//设置IP头操作选项   
	BOOL   bOpt   =   true;   
	iErrorCode   =   setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char   *)&bOpt,sizeof(bOpt));   
	CheckSockError(iErrorCode,   "setsockopt()");     
    
	//获得本地IP   
	SOCKADDR_IN   sa;   
	unsigned   char   LocalName[256];   

	iErrorCode   =   gethostname((char*)LocalName,sizeof(LocalName)-1);   
	CheckSockError(iErrorCode,   "gethostname()");   
	if((hp = gethostbyname((char*)LocalName))   ==   NULL)   
	{   
		CheckSockError(SOCKET_ERROR,   "gethostbyname()");   
	}   
    // 设置本地地址结构
	memcpy(&sa.sin_addr.S_un.S_addr,hp->h_addr_list[0],hp->h_length); 
	sa.sin_family   =   AF_INET;   
	sa.sin_port   =   htons(7000);
	// 绑定套接字
	iErrorCode   =   bind(sockListen,   (PSOCKADDR)&sa,   sizeof(sa));   
	CheckSockError(iErrorCode,   "bind");     
	//获得目标主机IP   
	memset(&targethost,0,sizeof(targethost));   
	targethost.sin_family   =   AF_INET;   
	targethost.sin_port   =   htons(TargetPort);   
	if((targethost.sin_addr.s_addr   =   inet_addr(TargetIP))   ==   INADDR_NONE)   
	{   
		if((hp   =   gethostbyname(TargetIP))   !=   NULL)   
		{   
			memcpy(&(targethost.sin_addr),hp->h_addr_list[0],hp->h_length);   
			targethost.sin_family   =   hp->h_addrtype;   
			printf("targethost.sin_addr   =   %s\n",inet_ntoa(targethost.sin_addr));   
		}   
		else   
		{   
			CheckSockError(SOCKET_ERROR,   "gethostbyname()");   
		}   
	}   
    
	//开启监听线程   
	HANDLE   Thread=CreateThread(NULL,0,RecvThread,0,0,0);   
	//填充IP首部   
	ip_header.h_lenver=(4<<4   |   sizeof(ip_header)/sizeof(unsigned   long));   
	//高四位IP版本号,低四位首部长度   
	ip_header.total_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER));   //16位总长度(字节)   
	ip_header.ident=1;   //16位标识   
	ip_header.frag_and_flags=0;   //3位标志位   
	ip_header.ttl=128;   //8位生存时间TTL   
	ip_header.proto=IPPROTO_TCP;   //8位协议(TCP,UDP…)   
	ip_header.checksum=0;   //16位IP首部校验和   
	ip_header.sourceIP=sa.sin_addr.s_addr;   //32位源IP地址   
	ip_header.destIP=targethost.sin_addr.s_addr;   //32位目的IP地址   
    
    
	//填充TCP首部   
	tcp_header.th_sport=htons(7000);   //源端口号   
	tcp_header.th_lenres=(sizeof(TCP_HEADER)/4<<4|0);   //TCP长度和保留位   
	tcp_header.th_win=htons(16384);     
    
    
	//填充TCP伪首部(用于计算校验和,并不真正发送)   
	psd_header.saddr=ip_header.sourceIP;   
	psd_header.daddr=ip_header.destIP;   
	psd_header.mbz=0;   
	psd_header.ptcl=IPPROTO_TCP;   
	psd_header.tcpl=htons(sizeof(tcp_header));   
    
    
	Sleep(500);   
	printf("\n");   
	printf("开始扫描主机  %s  端口范围 %d-%d \n\n",TargetIP,TargetPort,TargetPortEnd);   
	DWORD dwStart=GetTickCount();//开始计时    
	for(;TargetPort<TargetPortEnd;TargetPort++)   
	{   
		
		ProgressShow();   
		tcp_header.th_dport=htons(TargetPort);   //目的端口号   
		tcp_header.th_ack=0;   //ACK序列号置为0   
		tcp_header.th_flag=2;   //SYN   标志   
		tcp_header.th_seq=htonl(SEQ);   //SYN序列号   
		tcp_header.th_urp=0;   //偏移   
		tcp_header.th_sum=0;   //校验和   
		//计算TCP校验和,计算校验和时需要包括TCP   pseudo   header     
		memcpy(SendBuf,&psd_header,sizeof(psd_header));     
		memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));   
		tcp_header.th_sum=checksum((USHORT   *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));   
		
		//计算IP校验和   
		memcpy(SendBuf,&ip_header,sizeof(ip_header));   
		memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));   
		memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);   
		datasize=sizeof(ip_header)+sizeof(tcp_header);   
		ip_header.checksum=checksum((USHORT   *)SendBuf,datasize);   
		
		//填充发送缓冲区   
		memcpy(SendBuf,&ip_header,sizeof(ip_header));   
		
		//发送TCP报文   
		iErrorCode=sendto(sockRaw,SendBuf,datasize,0,(struct   sockaddr*)   &targethost,   
			sizeof(targethost));   
		CheckSockError(iErrorCode,   "sendto()");   
	}   
	DWORD dwEnd=GetTickCount();//计时结束   
	ScanFIN=TRUE;   
	printf("\n关闭线程.....\n\n");
	// 等待线程退出
	WaitForSingleObject(Thread,5000);   
	CloseHandle(Thread);   
	printf("端口扫描消耗时间 : %d ms ",dwEnd-dwStart);//显示耗时   
	//关闭套接字,释放相关资源   
	if(sockRaw   !=   INVALID_SOCKET)
	{
		closesocket(sockRaw);
	}
	WSACleanup();   
	return   0;   
  }     

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -