书:计算机网络高级软件编程技术(P120) 之 基础训练:利用TCP协议扫描端口
来源:互联网 发布:ubuntu下重装ubuntu 编辑:程序博客网 时间:2024/05/22 12:35
Section I Problem Specification
本次实验主要是写一个程序:能够扫描到指定Ip地址的端口是否开放。主要利用TCP协议,因为如果端口开放,目的主机将会:发送固定格式的TCP数据给源主机,表示:可以利用TCP进行连接。如果端口没有开发,那么也会返回一个特别的TCP数据包给源主机,表示不能连接。我们主要是根据返回的TCP数据包判断该端口是否开放。
TCP数据包:
作为必备的知识,主要就是TCP数据包的格式以及各个字段的含义:
上面两幅图清楚的指明了TCP数据包的格式以及内容,下面对其内容作简要的解释:
序列号(sequence Number):TCP协议将发送一段连接的数据,这个序列号也就是按照数据流的先后顺序给每个发送的数据包编号
确认号(Acknowledgement number):表示接收端希望接受的下一个TCP协议包的第一个字节的编号,与发送端下一个要发的序列号相对应。
头部长度:TCP数据包的长度,单位为ULONG,其范围为5到15之间,基本长度为20B,最长可以是60B。
保留字段:无实际用途,设置为0。
控制字段:
SYN:同步信息,用于建立一个新的TCP连接
SYN:同步信息,用于建立一个新的TCP连接
ACK:确认信息,当当前号设置为1时,表示确认号才有效。
PSH:表示希望协议栈尽快向上层传递数据
RST:表示Reset,强制切断连接
URG:表示需要紧急处理的数据存在。
FIN:连接正常终止,用来接收现有的TCP连接
PSH:表示希望协议栈尽快向上层传递数据
RST:表示Reset,强制切断连接
URG:表示需要紧急处理的数据存在。
FIN:连接正常终止,用来接收现有的TCP连接
窗口大小:用来表示滑动窗口的大小
校验和:数据报的忘记校验和
紧急指针:代表紧急数据在数据包中的位置,在URG置位时才有效(置位一词说的是将该位设置为1)
利用TCP扫描端口:
TCP连接的正常流程,
- Host A 发一个 SYN 包 给Host B,
- 如果端口打开,Host B 将会回一个 SYN+ACK包给 Host A。如果端口关闭,Host B 将会发一个RST+ACK包给Host A
- 那么Host A只需要再回一个ACK给Host B即可建立连接。
所以我们关键就是利用 第2部回过来的消息判断,到底是打开还是关闭。
Section II Solution Method and Design
主要流程还是构造包、发包、收包的过程,和上次实验差不多。这不过这次构造的是TCP的包。
类图:
序列图:
Section III Test Cases and Results Analysis
Section IV Conclusion
校验和 一定要计算吗?
百度知道:用wireshark抓包,为什么校验和错误还是能建立TCP三次连接
我也在此遇到了问题,如果 用网上下载的软件:ScanPort1.2(已存网盘)进行端口扫描,
无论我是否将网卡的 CheckSum Offload(硬件校验和) 功能 开启,该软件均能成功进行TCP连接(或者扫描到端口)。
但是,经过我用wireshark抓的包来看,该软件的的IPheader的checkSum还是TCP数据包里面的CheckSum 均为错误。
然而,我使用winpcap发包,我计算了IP头的checkSum,也计算了TCP数据包的checkSum, CheckSum Offload(硬件校验和) 功能是否开启,我都必须填写正确的CheckSum。
计算TCP包的校验和:
我的错在于
伪首部的长度:
theTcpFakeHeader.bTcpLength=htons(32);//计算校验和的时候必须将32转为网络字节
Section V References
书:计算机网络高级软件编程技术(吴功宜) 第八章 TCP和UDP数据包发送程序
网站:msdn
Section VI Appendix
TCP类:
头文件:其中继承的Ipheader类等等的详细情况请看移驾本人另一篇博客:
书:计算机网络高级软件编程技术(P88) 之 基础训练:路由追踪程序的实现(tracert程序)
#pragma once#include "ipheader.h"class TCPpacket :public Ipheader{public://下面两个是传输层的内容 //由于我想取到端口号,TCP协议和UDP协议在destAddress后面都是2个字节的源端口和2个字节的目的端口unsigned short SourcePort;//源端口unsigned short DestPort;//目的端口ULONG dwSeq;ULONG dwAck;UCHAR ucLength; //4 位首部长度/4 位保留字UCHAR ucFlag; //6 位标志位USHORT usWindow; //16 位窗口大小USHORT usCrc;//16 位校验和USHORT usUrgent;//16 位紧急数据偏移量UINT unMssOpt;UINT windowsScale;//根据抓包器抓出来的TCP包就有这个字段,具体不知道为什么。USHORT usNopOpt;USHORT usSackOpt;TCPpacket(unsigned short DestinationPort,LPVOID lpParameter,PIP_ADAPTER_INFO currentSlectedAdapter ,MIB_IPNET_ROW2 gatewayMAC);~TCPpacket(void);unsigned short getSourcePort();unsigned short getDestPort();unsigned short TCPpacket::GenerateChecksum(unsigned short* pBuf, int iSize); unsigned short TCPpacket::TcpCheckSum(const char *pTcpData, const char *pPshData, UINT nTcpCount);USHORT TCPpacket::CheckSum(USHORT *buffer, int size);USHORT TCPpacket::CheckSum(const char *buf, int size);};
实现文件:
#include "StdAfx.h"#include "dialog1Dlg.h"#include "TCPpacket.h"struct TcpFakeHeader{DWORD dwSourceAddr;//源地址DWORD dwDestAddr;//目的地址BYTE bZero;//置空BYTE bProtocolType;//协议类型USHORT bTcpLength;//TCP长度};TCPpacket::TCPpacket(unsigned short DestinationPort,LPVOID lpParameter,PIP_ADAPTER_INFO currentSlectedAdapter ,MIB_IPNET_ROW2 gatewayMAC){Cdialog1Dlg *Cdialog=(Cdialog1Dlg*)lpParameter;//EthernetHeaderint i=0;for (i;i<6;i++){this->destinationAddress[i]=gatewayMAC.PhysicalAddress[i];this->sourceAddress[i]=currentSlectedAdapter->Address[i];}this->ethernetType=htons(0x0800);//Ipheaderthis->Version_HeaderLength=0x45;this->TypeOfService=0x00;this->TotalLength=htons(52);//根据wireshark抓的一个包的大小填的this->Identification=htons(0x3521);this->Flags_FragmentOffset=htons(0x4000);this->TimeToLive=64;this->Protocal=6;//1就是ICMP的协议this->HeaderChecksum=htons(0x0000);TcpFakeHeader theTcpFakeHeader;CString text;Cdialog->m_ListBoxIpAddress.GetText(0,text);this->SourceAddress=inet_addr(text);theTcpFakeHeader.dwSourceAddr=inet_addr(text);Cdialog->m_CEditScanIp.GetWindowText(text);this->DestAddress=inet_addr(text);theTcpFakeHeader.dwDestAddr=inet_addr(text);if (DestinationPort+20000>60000)//这个地方的算法简直没设计好。{this->SourcePort=htons(DestinationPort+20000);}else{this->SourcePort=htons(DestinationPort-20000);}this->DestPort=htons(DestinationPort);this->dwSeq=ntohl(198327);//绝对不能为0this->dwAck=0;this->ucLength=0x80;this->ucFlag=0x002;//表示只是设置SYN为1this->usWindow=htons(0x2000);this->usCrc=0;this->usUrgent=0;this->unMssOpt=htonl(0x020405B4);this->windowsScale=htonl(0x01030302);this->usNopOpt=0x0101;this->usSackOpt=0x0204;//ip包的checkSum unsigned char IPheaderToCheck[20]; memset(&IPheaderToCheck,0,sizeof(IPheaderToCheck)); memcpy(&IPheaderToCheck,&this->Version_HeaderLength,20);//ip包头的大小 this->HeaderChecksum=GenerateChecksum((unsigned short*)IPheaderToCheck,20); theTcpFakeHeader.bZero=0;theTcpFakeHeader.bTcpLength=htons(32);//计算校验和的时候必须将32转为网络字节theTcpFakeHeader.bProtocolType=6;this->usCrc=TcpCheckSum((char *)(&(this->SourcePort)),(char *)(&theTcpFakeHeader),32);}TCPpacket::~TCPpacket(void){}unsigned short TCPpacket::getSourcePort() { return SourcePort; }unsigned short TCPpacket::getDestPort() { return DestPort; }unsigned short TCPpacket::GenerateChecksum(unsigned short* pBuf, int iSize) { unsigned long cksum = 0; while (iSize>1) { cksum += *pBuf++; iSize -= sizeof(USHORT); } if (iSize) cksum += *(UCHAR*)pBuf; cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return (USHORT)(~cksum); } USHORT TCPpacket::CheckSum(const char *buf, int size) { USHORT *buffer=(USHORT *)buf;unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size ) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } USHORT TCPpacket::CheckSum(USHORT *buffer, int size) { unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size ) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } unsigned short TCPpacket::TcpCheckSum(const char *pTcpData, const char *pPshData, UINT nTcpCount){unsigned short sCheckSum = ~CheckSum(pTcpData,nTcpCount);unsigned long checkSum = sCheckSum;checkSum <<= 16;sCheckSum = ~CheckSum(pPshData,12);checkSum += sCheckSum;return CheckSum((char*)&checkSum,4);}
在dialog1Dlg.cpp里添加的代码:
在button监听实现:
void Cdialog1Dlg::OnBnClickedButton2(){m_CEditScanIp.GetWindowText(str);if(currentSlectedAdapter==0){MessageBox("请先于左侧框内选择设备!");}else if (str.IsEmpty()){MessageBox("请输入IP地址");}else{m_hThreadtoRoute = CreateThread(NULL,0,ThreadProcScanPortByWinpcap,this,0,NULL);}// TODO: 在此添加控件通知处理程序代码}
接包和发包的线程:
DWORD _stdcall ThreadProcScanPortByWinpcap(LPVOID lpParameter){Cdialog1Dlg *Cdialog=(Cdialog1Dlg*)lpParameter;char errBuf[PCAP_ERRBUF_SIZE];pcap_findalldevs(&allDevs,errBuf);//列举所有设备 ,这里用来获取网络适配器信息的函数.pcap_findalldevs() returns 0 on success and -1 on failure.当errBuf满了会返回错误信息。CString a=currentSlectedAdapter->AdapterName;CString subfromIpHelper = a.Mid(a.ReverseFind('{')+1, 4);for(Dev=allDevs;Dev;Dev=Dev->next){a=Dev->name;CString subfromWinpcap = a.Mid(a.ReverseFind('{')+1, 4);if(subfromWinpcap==subfromIpHelper){break;}}currentOpenDev=pcap_open(Dev->name,65535,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,errBuf);CString text;Cdialog->m_CEditScanPortBegin.GetWindowText(text);int begin=_ttoi(text);Cdialog->m_CEditScanPortEnd.GetWindowText(text);int end=_ttoi(text);for (begin;begin<=end;begin++){TCPpacket sendTCPpacket=TCPpacket(begin,Cdialog,currentSlectedAdapter,gatewayMAC);unsigned char frame[66];memset(&frame,0,sizeof(frame));memcpy(&frame,&sendTCPpacket,sizeof(sendTCPpacket));pcap_sendpacket(currentOpenDev,frame,sizeof(frame));}pcap_pkthdr* hdr; const u_char *pkt_datas; int flag=0;unsigned long temp;while(true){ pcap_next_ex(currentOpenDev,&hdr,&pkt_datas); TCPpacket *getTCP;; getTCP=(TCPpacket *)pkt_datas;if (ntohs(getTCP->ethernetType)==0x0800&&getTCP->Protocal==6&&getTCP->ucFlag==0x12){str.Format("%d",ntohs(getTCP->SourcePort));int length=Cdialog->m_ListBoxScanResult.GetCount();for (flag=0;flag<length;flag++){CString strToCompare;Cdialog->m_ListBoxScanResult.GetText(flag,strToCompare);if (strToCompare==str){break;}}if (flag==Cdialog->m_ListBoxScanResult.GetCount()){Cdialog->m_ListBoxScanResult.AddString(str);}}}return 0;}
- 书:计算机网络高级软件编程技术(P120) 之 基础训练:利用TCP协议扫描端口
- 书:计算机网络高级软件编程技术(P46) 之 基础训练:使用Arp协议获得本地局域网内在线主机MAC地址
- 书:计算机网络高级软件编程技术(P69) 之 基础训练:统计本机 ip 流量包及展示其详细信息
- 书:计算机网络高级软件编程技术(P88) 之 基础训练:路由追踪程序的实现(tracert程序)
- 计算机网络高级软件编程技术
- 计算机网络Socket编程之TCP协议
- 计算机网络之tcp/ip协议
- 计算机网络之TCP协议与UDP协议
- 计算机网络之TCP协议与UDP协议
- 网络扫描技术揭秘读书笔记2--常用的网络编程-TCP/IP协议编程
- 计算机网络之TCP/IP协议栈
- 计算机网络基础之TCP/IP网络协议
- 计算机网络—传输层协议之TCP
- 计算机网络之WireShark与TCP协议
- 计算机网络之TCP/IP协议族
- 一、计算机网络之TCP/IP协议
- 网络扫描技术揭秘学习笔记《一》TCP/IP协议编程
- 计算机网络----学习协议端口
- twitter面试题之装水问题
- 华为 Ascend Mate 电池续航测试|5小时日常使用测试+8小时待机测试
- JS中如何检测img图片加载完成?
- BitmapFactory.decodeByteArray函数获取的bitmap为null
- 一个老程序员对刚上大学的学弟学妹的忠告
- 书:计算机网络高级软件编程技术(P120) 之 基础训练:利用TCP协议扫描端口
- 华为 A199 / Ascend G710 详细跑分数据公布 全面了解A199
- OpenGL 矩阵变换(讲的太好了~!)
- 华为 A199 / Ascend G710摄像头拍摄样张 多图 高清无码 慎入
- 数据结构之我思
- ASP.NET中如何在子窗体中调用母模板中的控件
- hdu 1874
- HTC One |M7|801e 真机高清图赏及初体验报告 HTC扛鼎之作
- SQL Sever 中(branch-name, customer-name) in XX 是不对的