实现多线程端口扫描

耗尽温柔 提交于 2020-02-29 16:48:23

实验要求

  1. 能至少扫描5个IP地址;
  2. 针对每个iP地址,开设100个线程同时对其进行扫描;
  3. 如果端口打开,使用函数getservbyport获取其服务名,在屏幕上打印:IP port servername,如果是未知服务,则屏幕显示:ip port unkonown

实验环境

Red Hat 9

代码

ThreadsPortScan.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<errno.h>

void print_usage(char* str)
{
	printf("the command %s usage is:\n",str);
	printf("%s Ip_Address min_port max_port\n");
}

typedef struct portInfo{
	struct in_addr dest_ip;
	unsigned short int min_port;
	unsigned short int max_port;
}Port;

int scanone(struct sockaddr_in scanip)
{
        int sockfd;
        if(-1==(sockfd=socket(AF_INET, SOCK_STREAM, 0)))
        {
                perror("error in generate socket\n");
                exit(1);
        }

        int ret = connect(sockfd, (struct sockaddr*)&scanip, sizeof(scanip));

        if(ret < 0){
                if(errno == ECONNREFUSED)
		{
                        close(sockfd);
                        return 0;
                }
                else{
                        close(sockfd);
                        return -1;
                }
        }
        else if(ret == 0){
                close(sockfd);
                return 1;
        }
        return -1;
}

void *scanport(void* arg)
{
	struct sockaddr_in scanip;
	struct servent *serv;
	char addr[100];
	Port port;
	int ret;
	memcpy(&port, arg, sizeof(Port));
	
	scanip.sin_family = AF_INET;
	scanip.sin_addr.s_addr = port.dest_ip.s_addr;

	unsigned short int i;	
	for(i=port.min_port; i<port.max_port; i++)
	{
		scanip.sin_port = htons(i);
		ret = scanone(scanip);
		if(ret == -1)
		{
			printf("scan port %d error.\n", i);
			return;
		}
		else if(ret == 0)
			continue;
		else
		{
			serv = getservbyport(htons(i), "tcp");
			inet_ntop(AF_INET, &scanip.sin_addr, addr, sizeof(addr));
			if(NULL != serv)
				printf("%s\t\t%d\t\tOPEN\t\t%s\n", addr, i, serv->s_name);
			else
				printf("%s\t\t%d\t\tOPEN\t\tUNKNOW\n", addr, i);
		}
	}
	return;
}

int main(int argc, char**argv)
{
	pthread_t *thread;
	int sockfd;
	struct servent* sp;
	int min_port;
	int max_port;
	int thread_num;
	struct in_addr scanip[5];
	Port port;

	if(argc < 3){
		print_usage(argv[0]);
		exit(-1);
	}

	int i;
	for(i=0; i<argc-3; i++)
		inet_aton(argv[i+1], &scanip[i]);

	min_port = atoi(argv[i+1]);
	max_port = atoi(argv[i+2]);
	thread_num = 100;
	//thread_num = atoi(argv[i+3]);

	//if(max_port - min_port < thread_num)
		//thread_num = max_port - min_port;

	int len = (max_port - min_port) / thread_num;

	if(max_port % thread_num != 0)  
		len++;

	if((thread = (pthread_t*)malloc(sizeof(pthread_t) * thread_num * i)) == NULL)
		printf("malloc thread error");

	printf("\nAddress\t\t\tPort\t\tStatus\t\tProtocal\n");

	int j, k;
	for(j = 0; j < i; j++)
	{
		for(k=0; k < thread_num; k++)
		{
			Port port;
			port.dest_ip = scanip[j];
			port.min_port = k*len + min_port;
			
			if(k == thread_num - 1)
				port.max_port = max_port;
			else
				port.max_port = port.min_port + len - 1;

			if(pthread_create(&thread[k+j*thread_num], NULL, scanport, (void*)&port)!=0)
			{
				free(thread);
				printf("pthread_create error\n");
				exit(-2);
			}
			//pthread_join(thread[k+j*thread_num], NULL);
		}
		
		for(k=0; k<thread_num; k++)
			pthread_join(thread[k+j*thread_num], NULL);
	}
	if(thread != NULL)
		free(thread);
	return 0;
}

运行结果

由于没有太多的主机,因此只扫描了虚拟机和物理机两个IP地址。输入的命令表示目标主机IP(一个或多个,本程序设定最大个数为5个)、起始端口号、结束端口号,每个IP都会在这端口号范围内进行扫描。,且为100个并行线程。
在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!