一個掃描器搞定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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章