logo资料库

主机端口扫描程序设计实验报告.doc

第1页 / 共18页
第2页 / 共18页
第3页 / 共18页
第4页 / 共18页
第5页 / 共18页
第6页 / 共18页
第7页 / 共18页
第8页 / 共18页
资料共18页,剩余部分请下载后查看
中南大学
中南大学 “通信网原理”实验报告 (第 三 次实验) 实验名称: 主机端口扫描程序设计 专业班级: 电子信息工程 学生姓名: 学 号: 指导教师: 陈科文,周扬 实验日期: 2016 年 11 月 22 日 中南大学·信息科学与工程学 1
实验名称 主机端口扫描程序设计 一、实验目的和要求 1、 实验目的 (1)通过实验,进一步加深理解传输层服务的基本概念和 TCP 与 UDP 协议的工作原理; (2)掌握网络中主机端口扫描的设计思想与编程方法。 2、 实验要求 (1)实验之前应做好充分准备工作,并预先编写好源代码; (2)上机实验时,程序必须调试成功,并接受教师验收(需边演示边 讲解,并回答教师提问); (3)按要求撰写《实验报告》。 二、实验关键技术(包括编程环境和关键 API 函数简介,以及程 序设计基本思想,比如要解决的关键问题、工作流程,或主要数 据结构的定义、算法的描述等) 关键问题: TCP 端口扫描 (1)端口扫描程序调用 socket()函数建立套接字,SOCK_STREAM 表示流 式套接字 (2)调用 connect()函数请求与目的主机的指定端口建立连接 (3)根据 TCP 连接是否成功建立,判断目的主机中的端口状态 UDP 端口扫描 (1)端口扫描程序调用 socket()函数建立套接字,SOCK_DGRAM 表示数 据报套接 字 (2)调用 ioctlsocket()函数将套接字设置为非阻塞 (3)调用 sendto()函数发送 UDP 数据包 (4)调用 recvfrom()函数接收返回的错误码,判断目的主机的端口状 态 实验原理: 端口是一个 0-65 535 之间的整数。端口可以分为两种类型:TCP 端口与 UDP 端口。其中,TCP 端口分配给 TCP 服务使用,UDP 端口分配给 UDP 服务使 2
用。通常情况下,TCP 与 UDP 端口同时分配给一种服务。 端口可以分为 3 种类型:熟知端口、注册端口与临时端口。其中,熟知端 口的范围是 0-- 1023,它被统一分配给某种指定的网络服务;注册端口的范 围是 1024-49151,它被分配给用户注册过的网络服务;临时端口的范围是 49152 一 65535,它可以被任何进程临时申请使用。根据传输层协议的规定, 服务器必须使用熟知端口来提供服务,客户机则使用临时端口来发送服务请 求。 主机端口扫描是网络安全检测的主要手段,它可以确定目的主机中处于 打开状态的端口,从而确定目的主机已经开启的服务类型,对维护主机系统 的安全性具有重要作用。由于有 TCP 与 UDP 两种端口类型,它们分别针对具 有不同特点的网络服务,因此端口扫描可以分为 TCP 端口扫描与 UDP 端口扫 描。 TCP 端口:TCP“三次握手”连接完成,说明连接成功。 TCP 端口扫描可以分为 3 种类型:  Connect 扫描:这是原理最简单的 TCP 扫描方式。端口扫描程序调用 Connect 系统调用,尝试连接目的主机的指定端口。如果成功建立 TCP 连接,说明两台主机完成一次完整的三次握手过程,该端口处 于开启状态;否则,说明该端口处于关闭状态。这种方式的优点是不 需要手工构造 TCP 包。由于 TCP 协议是保证可靠运行的协议,Connect 不会在尝试第一次连接未得到响应就放弃,而是会经过多次尝试后 才彻底放弃,因此它的缺点是工作效率比较低。  SYN 扫描:这是当前使用最广泛的 TCP 扫描方式。端口扫描程序向目 ACK=1 的主机的指定端口发送 SYN=1 的 TCP 包。如果接收到 SYN=1, 的 TCP 包,说明该端口处于开启状态;如果接收到 RST=1 的 TCP 包, 说明该端口处于关闭状态;如果没有接收到任何数据包,并且确定目 的主机开启,说明该端口被防火墙等安全设备过滤。由于 SYN 扫描 不完成 TCP 连接的三次握手过程,因此这种方式称为半开放扫描。 这种方式的最大优点是工作效率高,缺点是容易被人侵检测系统发 现。  FIN 扫描:这是一种比较隐蔽的 TCP 扫描方式。端口扫描程序向目的 主机的指定端口发送 FIN=I 的 TCP 包。如果没有接收到任何数据包, 并且确定目的主机开启,说明该端口处于开启状态;如果接收到 RST=I 的 TCP 包,说明该端口处于关闭状态。FIN 扫描的应用有很大 的局限性。不同系统实现网络协议栈的细节不同,FIN 扫描只能用 于 Linux 或 UNIX 系统。如果目的主机使用的是 Windows 系统,无论 端口是否开启都会直接返回 RST=1 的 TCP 包。 UDP 端口针对基于 UDP 服务的网络应用。在大多数情况下,如果向未开 3
启的 UDP 端口发送数据,目的主机都会返回一个端口不可达 ICMP 包 UDP 扫描的工作原理:端口扫描程序向目的主机的指定端口发送零字节的 UDP 包。如果没有接收到任何数据包,并且确定目的主机开启,说明该 端口处于开启状态;如果接收到端口不可达的 ICMP 包,说明该端口处干 关闭状态。由于 UDP 与 ICMP 协议都是不可靠的协议,没有接收到响应 可能是由于数据包没有到达,因此需要对端口进行多次扫描才能确定状 态。 实验流程图: 4
三、实验操作过程(包括:每一步实验内容、实验方法与中间结 果,实验过程中遇到的问题及解决办法) 1.了解传输层协议,主机端口分配方法,tcp,udp 端口扫描原理,方法, 以及不同扫描方法的优点和缺点的对比 2.界面设计 3.代码编写与调试 4.分析实验结果,总结 四、程序源代码(要求有良好的编程规范和必要的注释信息,完 整源代码可打印并粘贴) // FindPortDlg.h : header file class CFindPortDlg : public CDialog { // Construction public: CFindPortDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CFindPortDlg) enum { IDD = IDD_FINDPORT_DIALOG }; CProgressCtrl m_progress; CIPAddressCtrl m_Ip; CString m_Port1; CString m_Port2; CString m_Status; //}}AFX_DATA 5
// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CFindPortDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: HICON m_hIcon; // Generated message map functions //{{AFX_MSG(CFindPortDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnTcpscan(); afx_msg void OnUdpscan(); afx_msg void OnClear(); afx_msg void OnStop(); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: WSADATA WSAData; SOCKET Socket; CString Ip; int ip; sockaddr_in DestHost; CString Port; BOOL isStop ; }; // FindPortDlg.cpp : implementation file #include "stdafx.h" #include "FindPort.h" #include "FindPortDlg.h" #include "conio.h" //控制台调试信息 6
//TCP 端口扫描 void CFindPortDlg::OnTcpscan() { // TODO: Add your control notification handler code here //OnClear(); m_progress.SetPos(0); SetDlgItemText(IDSTATUS,""); UpdateData(true); if ((m_Port1 == "") || (m_Port2 == "")) { MessageBox("您没有输入正确的端口号"); return; } if(atoi(m_Port1) > atoi(m_Port2)) { MessageBox("请将小的端口号输在前面"); return; } if(WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { m_Status += "初始化 Winsock 失败!\r\n"; UpdateData(false); return; } m_Status += "初始化 Winsock 成功!\r\n"; //创建连接套接字 Socket = socket(AF_INET,SOCK_STREAM,0); if(Socket == INVALID_SOCKET) { m_Status += "创建 Socket 失败!\r\n"; UpdateData(false); WSACleanup(); return; } 7
m_Status += "创建 Socket 成功!\r\n"; //转换 IP 地址格式 m_Ip.GetWindowText(Ip); //判断域名或 IP 地址 ip = inet_addr(Ip); if(ip == INADDR_NONE) { hostent* pHostent = gethostbyname(Ip); if(pHostent) ip = (*(in_addr*)pHostent->h_addr_list).S_un.S_addr; } //定义目的主机地址 memset(&DestHost,0,sizeof(DestHost)); DestHost.sin_family = AF_INET; DestHost.sin_addr.S_un.S_addr = ip; int pos = 0; double step; //setPos 时转为 int isStop = FALSE; step = (100+0.0)/(atoi(m_Port2)-atoi(m_Port1)); cprintf("step=%lf\n",step); CString str; //循环扫描套接字 for( int m_Port = atoi(m_Port1); m_Port <= atoi(m_Port2); m_Port++) { if(isStop==TRUE) //安全停止 { cprintf("stop...\n"); break; } DestHost.sin_port = htons(m_Port); 8
分享到:
收藏