一个扫描器搞定TCP协议所有问题

目录

 

TCP协议扫描

TCP协议介绍

 TCP扫描原理

 TCP扫描实现


TCP三次握手介绍

TCP是面向连接的服务,所谓面向连接,即当计算机双方通信时,必须先建立连接,其次数据传送,最后结束连接这三个过程,即所谓的三次握手。对每次发送的数据量是怎样跟踪实行协商,使数据段的发送与接收实现同步。为了提供可靠的传送,TCP在发送新数据之前,以特定的顺序编排数据包的序号,并需要这些包传送给目标主机之后的确认消息。在收到数据后应用程序要做出确认时也会需要TCP。因为TCP需要时时刻刻跟踪,需要额外开销,使得TCP的格式有些复杂化。  

第一次握手:建立连接时,客户端发送SYN包(SYN=j)到服务器,即同步(Synchronize)标志的TCP报文,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器在收到客户端的SYN报文后,将返回一个SYN+ACK(ACK即确认Acknowledgement)的报文,表示客户端的请求被接受,同时TCP序号被加一,此时服务器进入SYN_RECV状态;  

第三次握手:客户端在收到服务器的SYN+ACK包后,向服务器发送确认包ACK(ACK=k+1),此包发送结束后,客户端和服务器均进入ESTABLISHED状态,完成三次握手过程。如图1.2所示。

TCP协议扫描

TCP协议为面向连接、可靠的、基于字节流的通信协议,其在通信中要实现三次握手连接,我们可以通过向目标主机发送连接请求的方式来确定目标主机是否存活。当然实现TCP扫描的方式有很多种,例如:简单的端口扫描(即:逐一测试主机存活),多线程connect扫描,半开发式的SYN扫描。

TCP协议介绍

Transmission Control Protocol (传输控制协议),简称TCP,是面向连接的、可靠的、基于字节流的通信协议,它位于运输层(Transport layer)中。在简化的OSI计算机网络模型中,它负责完成第四层(传输层)所指定的功能,UDP则为同一层内另一个重要的传输协议。

涉及到TCP扫描,我们就有必要分析一下TCP与UDP之间的联系与区别。

TCP是基于连接的协议,在正式收发数据之前,必须首先和对方建立可靠的连接。一个TCP连接要通过三次“对话”机制才可以建立起来,其过程十分复杂。TCP的目的是提供可靠数据传输,并且在相互进行通信的服务或设备之间保持一个虚拟连接。在数据包接收丢失、无序或交付期间被破坏时,TCP负责数据恢复的工作,即通过为其发送的每个数据包提供一个序号来完成恢复工作。

UDP(User Data Protocol),即是用户数据报协议,是与TCP相对应的协议。它是面向非连接的,通信时它不是与对方建立连接,而是直接把数据包发送过去。UDP适用的应用环境是每次只传送少量数据且对可靠性要求不高的环境。例如,使用“PING”命令来探测两台主机之间TCP/IP通信是否正常,实际上“PING”命令原理就是向对方主机发送UDP数据包,等待对方主机确认收到数据包,若数据包是否到达的消息可以及时反馈回来,那么这个网络就是通的。以上充分说明了UDP协议是面向非连接的,没有建立连接的。正因为如此,所以它的通信效率高;但也正因为如此,它的可靠性比TCP协议低。   

connect扫描原理,扫描主机通过TCP/IP协议的三次握手与目标主机的指定端口建立一次完整的连接,如果目标主机对该端口有回复,则说明该端口开放。利用多线程技术实现了对单个目标IP进行设定数目的端口扫描,对多IP段的特定端口进行扫描。此外,还利用委托技术实现对界面元素的刷新。②SYN扫描,也叫半开发式扫描,应用发送TCP的SYN请求包(指定端口),当对方收到SYN请求时,并且该端口打开时就会发送回应包:ACK =1,SYN =1, 这样就可以知道对方主机开发了哪些端口。

 

 TCP扫描原理

TCP扫描主要是有以下几个算法:SYN,Connect,FIN扫描,在这里主要介绍Connect扫描。

首先需要介绍一下TCP报文格式,如图3.7所示。

图3.7 TCP报文格式

 

TCP源端口(Source Port)号是16位,用于标识主机上面传送的应用程序;目的端口(Destination Port)是16位,定义传输目的。该端口指明接收方计算机上的应用接口。源端端口号和目的端的端口号,用来寻找发端与收端应用进程。这两个数值加上IP首部中的源端IP地址和目的端IP地址可以唯一确定一个TCP连接。一个I P地址与一个端口号有些时候也称为插口(socket),插口对(socket pair)(包含客户端口号、客户IP地址、服务器 IP地址与服务器端口号的四元组 )可以唯一确定互联网络中的每个TCP连接的双方。同样,IP+TCP端口可以唯一确定一个TCP连接。

序号字段(Sequence Number):该字段占32比特。用来标识TCP源端设备发送的字节流,表示在这个报文段中的第几个数据字节。

确认号字段(Acknowledge Number):该字段占32比特。TCP使用32位的确认号字段表示期望收到的下一个字段的第一个字节,声明在此之前的所有数据已经正确无误地被接收到了,所以,确认号应当是上次已经成功接收到的数据字节序列加1。只有ACK标志为1时,确认号字段才有效。

数据偏移(Data Offset):该字段包括TCP头大小,为4位字段。因为首部可能含有选项内容,所以首部长度不可确定。首部长度的单位是32比特或者4个八位组。实际上也表明了数据区在报文段中的起始偏移值。

预留(Reserved):由跟在数据偏移字段后的6位组成,预留位通常为0字段。

控制位(Control Bits):6位置0的字段,用作将来定义新的用途。  

SYN: 标志位用来表示建立连接,使连接双方同步的序列号。若SYN=1且ACK=0,表示该数据包是连接请求,假若SYN=1且ACK=1就表示接受连接。

FIN: 表示发送端已没有数据需要传输,希望释放该连接。

RST: 其用来复位一个连接。RST标志置位的数据包被称为复位包。一般情况下,若TCP收到的一个分段明显不是属于该主机的任何一个连接,则向远端发送复位包。

URG: 是紧急数据标志。假若为1,表示本数据包中包含紧急数据,紧急数据指针有效。

ACK: 是确认标志位。假若为1,表示包中的确认号是有效的。否则,包中确认号无效。

PSH: 假若置位,接收端应该尽快把数据传送给应用层。

Connect扫描也叫做全连接方式的扫描,他完成TCP连接三次握手的整个过程,当然他的扫描原理也是利用测试连接目标主机的端口号是否处于监听状态,如果处于监听状态就会接收到目标主机发回来的回应包,就可以知道目标主机该端口是否开发。

SYN扫描又叫做半开发式扫描,他没有完成TCP连接的三次握手(三次握手在第二章基础知识部分),当扫描器利用TCP协议向目标主机发送SYN请求信号,目标主机接收到请求信号给予回复,扫描器接收到回复信号后立即释放,并不再给目标主机发送回应数据包了。这样就只是完成了三次握手的前两次就可以完成整个扫描的过程,比起Connect扫描速度更加快捷。但是其实现复杂度要比connect难得很多。

 TCP扫描实现

TCP协议扫描的实现有很多种方式,该软件只是制作了Connect扫描与SYN扫描。

⑴Connect扫描:

①设置一个全局变量看是否有其他扫描器已经开启或者本身已经开始扫描了,如果已经开始扫描了不做任何处理,如果没开始扫描或者扫描已经结束的话那么就可以进行扫描。

②从界面中获取相关的IP号和起始端口号,以便下面的扫描填写参数。主要利用的函数为:

GetWindowsText(&PORT);Getaddress(IP);

将PORT转化为int类型;

③判断用户选择了哪项功能。当用户选择一个功能时,那么就对变量m_funtion进行赋值,利用一个switch来判断,用户选择了哪项功能,然后完成相应的功能,如果用户没有选择那么就显示“you do not select any funtion”提醒用户选择功能。(如果用户选择了connect,进行以下程序)

④判断端口号是否小于1或者大于65535,因为系统所能开发的端口号是在1-65535之间所以要进行错误判断。

⑤因为每一个线程都共用了一个int seq变量,所以创建线程互斥量,不让线程在进行同步的时候,seq出现错误。

⑥为每一个connect创建一个线程,将端口号和IP地址传到线程中去,利用结构体information_des来传递,因为线程传递参数的时候不能直接传递多个参数只能传递一个结构体。

⑦线程内部:获得主窗口的指针为将信息输出在列表控件中用。创建套接字为connet连接用

填写套接字中的IP地址和指定阻塞或非阻塞,连接connet()。

⑧利用select函数判断连接是否正确,select()有一个int类型的返回值,如果连接失败,就返回 0,如果连接成功就返回其他值,那么就利用这个返回值来判断是否连接成功,如果连接成功就说明该IP的该端口是打开的,如果连接不成功就说明该IP的该端口是关闭的,不能连接。将打开的端口的信息输入到主窗口的列表控件中去。让用户知道扫描结果。

⑨结束所有套接字closesocket()函数完成,无论是超时的还是连接成功的都结束套接字让程序释放资源。将所有变量清空。

⑵SYN扫描:

①设置一个全局变量看是否有其他扫描器已经开启或者本身已经开始扫描了,如果已经开始扫描了不做任何处理,如果没开始扫描或者扫描已经结束的话那么就可以进行扫描。

②界面中获取相关的IP号和起始端口号,以便下面的扫描填写参数。主要利用的函数为:GetWindowsText(&PORT);Getaddress(IP);

③判断用户选择了哪项功能,当用户选择一个功能时,那么就对变量m_funtion进行赋值,利用一个switch来判断,用户选择了哪项功能,然后完成相应的功能,如果用户没有选择那么就显示“you no select any funtion”提醒用户选择功能。(如果用户选择了SYN进行一下程序);

④首先获得要进行扫描的主机的MAC然后填写TCP包上的目的地址eh_dst上。第二获得本机的MAC,函数GetHostMAC()然后填写协议为:0x0800。

计算头部长度并填写:

IpHeader.h_verlen=(4<<4|sizeof(IpHeader)/sizeof(unsigned int));

IpHeader.tos = 0;//表示服务类型为0;

IpHeader.tos = 0;//表示服务类型为0;

IpHeader.total_len = htons(sizeof(IpHeader)+sizeof(TcpHeader)); //表示该IP包的总长度;

IpHeader.ident = 1;// 表示IP包识别号为1;

IpHeader.frag_and_flags = 0x40;//表示片标志;

IpHeader.ttl = 128;// 表示生存时间TTL值为128。该部分占8个BIT;

IpHeader.proto = IPPROTO_TCP;//表示协议类型为TCP,协议代码是6;

IpHeader.checksum = 0;//表示IP包头校验和为0;

IpHeader.sourceIP = inet_addr(LocalIP );// 表示IP数据包源地址为:本机地址;

m_IPAdress.GetAddress(desIP1);

desIP.Format("%d",desIP1);

IpHeader.destIP = inet_addr( desIP ); //表示IP数据包目的地址为要扫描地址

TcpHeader.th_sport = htons(1222);//源端口号

TcpHeader.th_dport = htons( port );//目的端口号要扫描的端口号

TcpHeader.th_seq = SEQ; //表示初始连接的请求号

 TcpHeader.th_ack = 0;

TcpHeader.th_lenres = (sizeof(TcpHeader)/4<<4|0);

TcpHeader.th_flag = 02; //该值用两个十六进制数来表示标识SYN值1

TcpHeader.th_win = htons(16348);// 表示窗口是16348

TcpHeader.th_sum = 0;

TcpHeader.th_urp = 0;

PsdHeader.saddr = inet_addr( LocalIP );

PsdHeader.daddr = IpHeader.destIP; //输入目的主机得IP

PsdHeader.mbz = 0;

PsdHeader.ptcl = IPPROTO_TCP; //标识选择TCP协议

PsdHeader.tcpl = htons(sizeof(TcpHeader));

将以上内容填写完成之后。将TCP结构的信息转化为字符串类型进行发送,发送TCP包的函数为pcap_sendpacket();⑤等待回应,接收回应的TCP报文,分析接收的SEQ等于发送SYN数据包的SEQ+1那么就知道这个为我们接受到得回应包,这样记录下该端口号并且把他显示到界面中区这样我们就能够知道该端口号为开发端口。

 

源码地址: https://download.csdn.net/download/arv002/12413239

开发软件VC++6.0

调测前记得安装winpcap。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三雷科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值