网络程序设计实践 实验二 端口扫描实验(C语言实现)

1.实验任务

        编写一个利用全连接的端口扫描程序,能显示目标主机的端口开放情况。要求能在命令行输入要扫描的目标主机和端口范围。比如:scan  *.*.*.*   nnnn-mmmm。

2.实验原理

        

        我们知道完成一次TCP连接需要完成三次握手才能建立。端口扫描正是利用了这个原理,通过假冒正常的连接过程,依次向目标主机的各个端口发送连接请求,并根据目标主机的应答情况判断目标主机端口的开放情况,从而分析并对一些重要端口实施攻击。

3.实验设计

        利用理论课实验二()中的客户端程序代码修改而来(记得修改IP地址)

        原理是通过connect()函数向主机端发送SYN包,如果主机端端口开放,则会返回SYN+ACK包,客户端再发送ACK包以发送连接请求,加入accept()队列,此过程可通过connect函数的返回值判断是否成功连接,从而判断端口是否开放

        运行代码可能导致windows防火墙报错,选择信任即可

#include"stdafx.h"
#include <Winsock2.h>
#include <string>
#include <iostream>

int scanpost(int hp)
{
	WSADATA wsd;								
	WSAStartup(MAKEWORD(2, 2), &wsd);		
	SOCKET sock_c;
	SOCKADDR_IN addr_c;
	sock_c = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);	//**重要**采用TCP协议 
	
	addr_c.sin_family = AF_INET;						//指定IPV4地址协议 
	addr_c.sin_addr.S_un.S_addr = inet_addr("xxx.xxx.153.117"); //目标地址 
	addr_c.sin_port = htons(hp);						//指定端口 
	
	int ret = connect(sock_c, (LPSOCKADDR)&addr_c, sizeof(addr_c));		//ret=0 连接成功,ret = -1 连接失败; 
	if(ret == 0)			
	{
		printf("端口号:%d 端口开放\n",hp);
	}
	else
	{
//		printf("端口号:%d 端口关闭\n",hp);
	}
	WSACleanup();
  	closesocket(sock_c);
  	return 0;
}
int main()
{
	for(int hp=1;hp<10000;hp++)
	{
		scanpost(hp);
	}
	return 0;
}

4.思考题

        ①阐述全连接扫描的原理

                这个属于理论知识,上面的实验原理解释了一部分,但大伙自己搜的肯定比我讲的准确

        ②你的程序是否考虑了扫描效率?如没有考虑你准备如何改进?

                大伙运行上面的基础程序肯定会感觉很慢,这是因为connect的超时时间较长,对于未开放的端口,需要等待很久(大概1秒?)才会确定无法连接,返回-1,我们可以采取select模型+非阻塞套接字限制超时时间(Timeout),从而极大缩短判断超时所需时间

                

#include"stdafx.h"
#include <Winsock2.h>
#include <string>
#include <iostream>

int scanpost()
{
	WSADATA wsd;								
	WSAStartup(MAKEWORD(2, 2), &wsd);		
	SOCKET sock_c;
	SOCKADDR_IN addr_c;
	
	TIMEVAL TimeOut;		//超时时间 
  	FD_SET mask;			//管理套接字结构体 
	TimeOut.tv_sec = 0;		//秒 
  	TimeOut.tv_usec = 10000; //微秒 
  	
  	unsigned long mode = 1; //指定模式 
  	
	for(int hp = 1;hp<10000;hp++)
	{ 
		sock_c = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);	//**重要**采用TCP协议 
		
		addr_c.sin_family = AF_INET;						//IPV4地址协议 
		addr_c.sin_addr.S_un.S_addr = inet_addr("100.98.153.117"); //目标地址 
		addr_c.sin_port = htons(hp);						//端口变量 
		
		FD_ZERO(&mask);		//清空 
    	FD_SET(sock_c, &mask);	//装入sock_c 
    	
    	ioctlsocket(sock_c, FIONBIO, &mode);			//将套接字转为非阻塞 
    	connect(sock_c, (struct sockaddr *)&addr_c, sizeof(addr_c)); //发送连接请求 
    	
		int ret = select(0, 0, &mask, 0, &TimeOut);		// 0表示超时,1表示成功,-1表示错误 
		if(ret != 0 && ret != -1)			
		{
			printf("端口号:%d 端口开放\n",hp);
		}
		else
		{
//			printf("端口号:%d 端口关闭\n",hp);
		}
	}
	WSACleanup();
  	closesocket(sock_c);
  	return 0;
}
int main()
{
	scanpost();
	return 0;
}

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值