利用TCP/IP协议进行端口扫描
1、首先,应用VC++6.0开发一个cmd命令行,实现端口扫描的程序可以利用TCP协议和UDP协议,原理是通过Socket连接对方的计算机的某端口,试图和该端口建立连接,如果建立成功,就说明对方开放了该端口,如果失败了,就说明对方没有开放该端口。下面将给出利用TCP/IP协议实现端口扫描的C++程序:
下面是我所应用的源程序,大家可以试验一下。
#include<stdlib.h>
#include<stdio.h>
#include<winsock.h>
该头文件中包含了与windows套接字相关的函数和一些结构
#include<winbase.h>
#define BUFSIZE 64
定义了缓冲区容量
#define WSVERS MAKEWORD(2,0)
调用MAKEWORD()函数获得Winsock的版本,用于加载Winsock库
#define WINPOCH 2208988800
#define MSG "Is this port you open?\n"
#define MAX_PACKET 1024
SOCKET connectsock(const char *host,const char *service,
const char *transport);
void errexit(const char *,...);
int main(int argc,char *argv[])
{
char *host="localhost";//定义变量host用来存储本地计算机的相关信息
char *service="5060";//服务默认的扫描端口
SOCKET s;
SOCKET是一种数据类型。在WIN32 SDK中有详细的描述
int errcnt=0;
WSADATA wsadata;
WSADATA是一种windows内部定义的结构体,其具体描述如下:
typedef struct WSAData { WORD wVersion; WORD wHighVersion; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo;
} WSADATA, FAR * LPWSADATA;
switch(argc){
case 1:
break;
case 3:
service=argv[2];
case 2:
host=argv[1];
break;
default:
fprintf(stderr,"usage:Prog4_4.exe [host [port]]\n");
fprintf隶属头文件为stdio.h是一个格式输出语句
stderr为指向文件的标准错误。
本句的意思是:将错误信息输出到屏幕
exit(1);
}
if(WSAStartup(WSVERS,&wsadata))
WSAStartup(WSVERS,&wsadata) 该语句用来加载Winsock库
errexit("WSAStartup failed\n");
s=connectsock(host,service,"tcp");
(void) send(s,MSG,strlen(MSG),0);
send函数用来发送数据到连接套接字
int send ( SOCKET s, const char FAR * buf, int len, int flags );
closesocket(s);//关闭套接字s
WSACleanup();//卸载Winsock库
return 1;
}
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
SOCKET connectsock(const char *host,const char *service,
const char *transport)
{
struct hostent *phe;
struct servent *pse;
struct protoent *ppe;
struct sockaddr_in sin;
int s,type;
memset(&sin,0,sizeof(sin));
//该函数的意思是将sin的第一个值用sin本身的大小来替代
//这里的sin是一个类的对象。其定义方式为:
template<class T>
valarray<T> sin(const valarray<T>& x);
sin.sin_family=AF_INET;// AF_INET与TCP/IP Raw Sockets有关。
if(pse=getservbyname(service,transport)) //本函数用来取得服务器的相关信息和协议
sin.sin_port=pse->s_port;
else if((sin.sin_port=htons((u_short)atoi(service)))==0) atoi()函数用来将字符型变量转换成整型变量。Htons()函数用来转换TCP/IP网络的命令的。
errexit("can't get \"%s\" service entry\n",service);
if(phe=gethostbyname(host)) //从已收到的主机数据中得到通信主机的相关信息
memcpy(&sin.sin_addr,phe->h_addr,phe->h_length);
else if((sin.sin_addr.s_addr=inet_addr(host))==INADDR_NONE)
errexit("can't get\"%s\" host entry\n",transport);
if((ppe=getprotobyname(transport))==0) //通过端口得到协议名
errexit("can't get \"%s\" host entry\n",transport);
if(strcmp(transport,"udp")==0)
type=SOCK_DGRAM;
else
type=SOCK_STREAM;
// SOCK_STREAM SOCK_DGRAM由三部分组成:一个主机地址、协议数字和表示应用程序的端口数字
s=socket(PF_INET,type,ppe->p_proto);
if(s==INVALID_SOCKET)
errexit("can't create sockey: %d\n",GetLastError());
if(connect(s,(struct sockaddr *)&sin,sizeof(sin))==
SOCKET_ERROR)
errexit("can't connect to %s.%s: %d\n",host,service,
GetLastError());
return s;
}
//下面的函数是出错处理函数,用来打印出错信息的
void errexit(const char *format,...)
{
va_list args;
va_start(args,format);
vfprintf(stderr,format,args);
va_end(args);
WSACleanup();
exit(1);
}
2、以上程序给出之后,再列出该程序的基本流程图。

3、程序的运行方法:
将编译连接好的位于debug文件夹下的tcp.exe文件拷到C盘跟目录下。然后在命令提示符下键入如下给出的格式的命令即可运行:
tcp [目标主机的IP] [要扫描的端口号]
下面给出程序的运行结果:
如下图:

4、我们进行扫描的目的是利用各种工具对攻击目标的IP地址或地址段的主机查找漏洞。扫描采取模拟攻击的形式对目标可能存在的已知安全漏洞逐项进行检查,目标可以是工作站、服务器、交换机、路由器和数据库应用等。根据扫描结果想扫描者或管理员提供周密可靠的分析报告。