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

📄 tcp_scan.c

📁 TCP/IP商品扫描器 0.1
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * tcp_scan.c -- A large scale TCP ports scanner. * Created: Xie Han, net lab of Peking University. <e@pku.edu.cn> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* I like BSD style better. */#define _BSD_SOURCE#include <errno.h>#include <sys/types.h>#include <sys/time.h>#include <sys/select.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#ifdef IPV6# include <netinet/ip6.h># include <netinet/icmp6.h>#endif#include <netinet/tcp.h>#include <arpa/inet.h>#include <time.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <string.h>#include <rbtree.h>#include <unp.h>#include "tcp_scan.h"#define TCP_SCANNER_PORT		12200#define TCP_SCAN_REPEATS		4#define MAX_SEG_LIFETIME		30#define SET_FD_NONBLOCK(fd) \({																\	int __flags = fcntl(fd, F_GETFL, 0);						\	if (__flags >= 0)											\		__flags = fcntl(fd, F_SETFL, __flags | O_NONBLOCK);		\	__flags;													\})#ifdef IPV6# define IN6_ADDR_NEXT(addr) \do {															\	int i;														\	for (i = 15; i >= 0; i--)									\	{															\		if (++(addr)->s6_addr[i] != 0)							\			break;												\	}															\} while (0)#endif/* "sockaddr" structs arranged in a Red-Black tree. */struct __sockaddr_rb{	struct rb_node rb;	socklen_t addrlen;	struct sockaddr sockaddr;};/* Union of sockaddr. */union __sa_union{	struct sockaddr sockaddr;	struct sockaddr_in sin;#ifdef IPV6	struct sockaddr_in6 sin6;#endif};/* IP pseudoheader of TCP or UDP. */struct __ip_pheader{	struct in_addr src;	struct in_addr dst;	unsigned char zero;	unsigned char protocol;	unsigned short len;};#ifdef IPV6struct __ip6_pheader{	struct in6_addr src;	struct in6_addr dst;	unsigned int len;	unsigned short zero1;	unsigned char zero2;	unsigned char next;};#endif/* TCP header combined with IP pseudoheader. */struct __tcp_pheader{#ifdef IPV6	union	{		struct __ip6_pheader phdr6;		struct		{			char __null__[sizeof (struct __ip6_pheader) -						  sizeof (struct __ip_pheader)];			struct __ip_pheader phdr;		};	};#else	struct __ip_pheader phdr;#endif	struct tcphdr tcphdr;};unsigned short __tcp_scanner_port = TCP_SCANNER_PORT;int __tcp_scan_repeats = TCP_SCAN_REPEATS;int __max_seg_lifetime = MAX_SEG_LIFETIME;/* For the sake of simplicity. */static unsigned int __tcp_header_seq;static scan_info_t __info;static void *__arg;inline static void __make_tcp_ip_pheader(const struct in_addr *saddr,										 const struct in_addr *daddr,										 struct __ip_pheader *phdr){	phdr->src = *saddr;	phdr->dst = *daddr;	phdr->zero = 0;	phdr->protocol = IPPROTO_TCP;	phdr->len = htons(sizeof (struct tcphdr));}#ifdef IPV6inline static void __make_tcp_ip6_pheader(const struct in6_addr *saddr,										  const struct in6_addr *daddr,										  struct __ip6_pheader *phdr){	phdr->src = *saddr;	phdr->dst = *daddr;	phdr->len = htonl(sizeof (struct tcphdr));	phdr->zero1 = 0;	phdr->zero2 = 0;	phdr->next = IPPROTO_TCP;}#endif/* Send a TCP packet. (Without TCP options or TCP data.) */static int __tcp_send(int sockfd, struct __tcp_pheader *tcpphdr,					  const void *saddr, const struct sockaddr *daddr,					  socklen_t addrlen){	unsigned short *pfrom;	int len;	switch (daddr->sa_family)	{	case AF_INET:		__make_tcp_ip_pheader((const struct in_addr *)saddr,							  &((const struct sockaddr_in *)daddr)->							  sin_addr, &tcpphdr->phdr);		pfrom = (unsigned short *)&tcpphdr->phdr;		len = sizeof (struct __ip_pheader) + sizeof (struct tcphdr);		break;#ifdef IPV6	case AF_INET6:		__make_tcp_ip6_pheader((const struct in6_addr *)saddr,							   &((const struct sockaddr_in6 *)daddr)->							   sin6_addr, &tcpphdr->phdr6);		pfrom = (unsigned short *)&tcpphdr->phdr6;		len = sizeof (struct __ip6_pheader) + sizeof (struct tcphdr);		break;#endif	default:		errno = EAFNOSUPPORT;		return -1;	}	tcpphdr->tcphdr.th_sum = 0;	tcpphdr->tcphdr.th_sum = in_cksum(pfrom, len);	return sendto(sockfd, &tcpphdr->tcphdr, sizeof (struct tcphdr), 0,				  daddr, addrlen);}/* Send a SYN packet to the remote server. */static int __tcp_syn(int sockfd, unsigned short sport, unsigned short dport,					 const void *saddr, const struct sockaddr *daddr,					 socklen_t addrlen){	struct __tcp_pheader tcpphdr = {		tcphdr	:	{			th_sport	:	htons(sport),			th_dport	:	htons(dport),			th_seq		:	htonl(__tcp_header_seq),			th_ack		:	htonl(0),			th_x2		:	0,			th_off		:	sizeof (struct tcphdr) >> 2,			th_flags	:	TH_SYN,			th_win		:	htons(8192),			th_urp		:	htons(0)		}	};	return __tcp_send(sockfd, &tcpphdr, saddr, daddr, addrlen);}/* Tell the remote server that connection is aborted. */static int __tcp_rst(int sockfd, unsigned short sport, unsigned short dport,					 const void *saddr, const struct sockaddr *daddr,					 socklen_t addrlen){	struct __tcp_pheader tcpphdr = {		tcphdr	:	{			th_sport	:	htons(sport),			th_dport	:	htons(dport),			th_seq		:	htonl(0),			th_ack		:	htonl(0),			th_x2		:	0,			th_off		:	sizeof (struct tcphdr) >> 2,			th_flags	:	TH_RST,			th_win		:	htons(0),			th_urp		:	htons(0)		}	};	return __tcp_send(sockfd, &tcpphdr, saddr, daddr, addrlen);}/* Search a sockaddr in a Red-Black tree. */static struct __sockaddr_rb *__rb_search_sockaddr(const struct sockaddr *sockaddr, socklen_t addrlen,					 const struct rb_root *root){	const struct rb_node *p = root->node;	struct __sockaddr_rb *entry;	int n;	while (p)	{		entry = rb_entry(p, struct __sockaddr_rb, rb);		if (addrlen < entry->addrlen)			n = -1;		else if (addrlen > entry->addrlen)			n = 1;		else if ((n = memcmp(sockaddr, &entry->sockaddr, addrlen)) == 0)			return entry;		p = n < 0 ? p->left : p->right;	}	return NULL;}/* Insert a sockaddr into a Red-Black tree. */static struct __sockaddr_rb *__rb_insert_sockaddr(const struct sockaddr *sockaddr, socklen_t addrlen,					 struct rb_root *root){	struct rb_node **p = &root->node;	struct rb_node *parent = NULL;	struct __sockaddr_rb *entry;	int n;	while (*p)	{		parent = *p;		entry = rb_entry(parent, struct __sockaddr_rb, rb);		if (addrlen < entry->addrlen)			n = -1;		else if (addrlen > entry->addrlen)			n = 1;		else if ((n = memcmp(sockaddr, &entry->sockaddr, addrlen)) == 0)			return entry;		p = n < 0 ? &parent->left : &parent->right;	}	#define __SOCKADDR_RB_LEN \		(sizeof (struct __sockaddr_rb) - sizeof (struct sockaddr) + addrlen)	if (entry = (struct __sockaddr_rb *)malloc(__SOCKADDR_RB_LEN))	{		entry->addrlen = addrlen;		memcpy(&entry->sockaddr, sockaddr, addrlen);		rb_link_node(&entry->rb, parent, p);		rb_insert_color(&entry->rb, root);		return NULL;	}	#undef __SOCKADDR_RB_LEN	return (struct __sockaddr_rb *)-1;}static void __rb_destroy_sockaddr(struct rb_root *root){	struct __sockaddr_rb *entry;	while (root->node)	{		entry = rb_entry(root->node, struct __sockaddr_rb, rb);		rb_erase(root->node, root);		free(entry);	}}static int __proc_tcp_packet(int sockfd, const struct tcphdr *tcphdr,							 const void *daddr, const struct sockaddr *saddr,							 socklen_t addrlen, struct rb_root *root){	struct __sockaddr_rb *entry;	int state;	if (ntohs(tcphdr->th_dport) == __tcp_scanner_port)	{		if (tcphdr->th_flags & (TH_SYN | TH_RST) &&			tcphdr->th_flags & TH_ACK &&			ntohl(tcphdr->th_ack) == __tcp_header_seq + 1)		{			if (tcphdr->th_flags & TH_SYN)			{				/* The connection is accepted. Abort it. */				__tcp_rst(sockfd, __tcp_scanner_port,						  ntohs(tcphdr->th_sport),						  daddr, saddr, addrlen);			}			if (!(entry = __rb_insert_sockaddr(saddr, addrlen, root)))			{				state = tcphdr->th_flags & TH_SYN ? TS_ACCEPTED : TS_REFUSED;				if (__info(saddr, addrlen, state, __arg) < 0)					return -1;			}			else if (entry == (struct __sockaddr_rb *)-1)				return -1;		}	}	return 0;}static int __recv_tcp_packet(int sockfd, struct rb_root *root){	/* We do not care the TCP options or TCP data, so the buffer size is the	   biggest IPv4 header size, which is bigger than IPv6 header size, plus	   TCP header size. */	#define __BUFSIZE	((0xf << 2) + sizeof (struct tcphdr))	char buf[__BUFSIZE];	struct ip *iphdr = (struct ip *)buf;#ifdef IPV6	struct ip6_hdr *ip6hdr = (struct ip6_hdr *)buf;#endif	struct tcphdr *tcphdr;	union __sa_union un;	socklen_t addrlen;	ssize_t n;	while (addrlen = sizeof (union __sa_union), (n = recvfrom(sockfd, buf,							__BUFSIZE, 0, &un.sockaddr, &addrlen)) >= 0)	{		if (un.sockaddr.sa_family == AF_INET)		{			/* Make sure that it is a valid TCP packet. */			if (n >= sizeof (struct ip) && iphdr->ip_p == IPPROTO_TCP &&				n >= (iphdr->ip_hl << 2) + sizeof (struct tcphdr))			{				tcphdr = (struct tcphdr *)(buf + (iphdr->ip_hl << 2));				un.sin.sin_port = tcphdr->th_sport;				if (__proc_tcp_packet(sockfd, tcphdr, &iphdr->ip_dst,									  &un.sockaddr, addrlen, root) < 0)					break;			}		}#ifdef IPV6		else if (un.sockaddr.sa_family == AF_INET6)		{			if (n >= sizeof (struct ip6_hdr) + sizeof (struct tcphdr) &&				ip6hdr->ip6_nxt == IPPROTO_TCP)			{				tcphdr = (struct tcphdr *)(ip6hdr + 1);				un.sin6.sin6_port = tcphdr->th_sport;				if (__proc_tcp_packet(sockfd, tcphdr, &ip6hdr->ip6_dst,									  &un.sockaddr, addrlen, root) < 0)					break;			}		}#endif	}	#undef __BUFSIZE	return n < 0 && errno == EAGAIN ? 0 : -1;}static int __proc_icmp_packet(const struct icmp *icmp, size_t icmplen,							  struct sockaddr *saddr, socklen_t addrlen,							  struct rb_root *root){	struct __sockaddr_rb *entry;	const struct ip *iphdr;	const struct tcphdr *tcphdr;	/* We care only ICMP unreach packet. */	#define __offset(type, member)	((size_t)&((type *)0)->member)	if (icmp->icmp_type == ICMP_UNREACH)	{	/*	if (icmplen >= sizeof (struct icmp) + sizeof (struct ip))	*/		if (icmplen >= __offset(struct icmp, icmp_data) + sizeof (struct ip))		{			iphdr = (const struct ip *)icmp->icmp_data;			if (icmplen >= __offset(struct icmp, icmp_data) +						   (iphdr->ip_hl << 2) + 8)			{				tcphdr = (const struct tcphdr *)((const char *)iphdr +												 (iphdr->ip_hl << 2));				if (ntohs(tcphdr->th_sport) == __tcp_scanner_port &&					ntohl(tcphdr->th_seq) == __tcp_header_seq)				{					((struct sockaddr_in *)saddr)->sin_port = tcphdr->th_dport;					if (!(entry = __rb_insert_sockaddr(saddr, addrlen, root)))					{						if (__info(saddr, addrlen, TS_UNREACH, __arg) < 0)							return -1;					}

⌨️ 快捷键说明

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