SYN端口扫描

/*
经典描器(全TCP连接)和SYN(半连接)扫描
全TCP连接   
全TCP连接是长期以来TCP端口扫描的基础。
扫描主机尝试(使用三次握手)与目的机指定端口建立建立正规的连接。
连接由系统调用connect()开始。对于每一个监听端口,connect()会获得成功,
否则返回-1,表示端口不可访问。 
 这种扫描方法很容易检测出来,在日志文件中会有大量密集的连接和错误记录)。
TCP SYN扫描   
在这种技术中,扫描主机向目标主机的选择端口发送SYN数据段。
石棉密封垫如果应答是RST,那么说明端口是关闭的,按照设定就探听其它端口;
如果应答中包含SYN和ACK,说明目标端口处于监听状态。
由于所有的扫描主机都需要知道这个信息,传送一个RST给目标机从而停止建立连接。
由于在SYN扫描时,全连接尚未建立,所以这种技术通常被称为<;半打开扫描>。
SYN扫描的优点在于即使日志中对扫描有所记录,但是尝试进行连接的记录也要比全扫描少得多。
缺点是在大部分操作系统下,发送主机需要<;构造适用于这种扫描的IP包>,
通常情况下,构造SYN数据包需要超级用户或者授权用户访问专门的系统调用。
一个TCP头包含6个标志位。
它们的意义分别为:
SYN: 标志位用来建立连接,让连接双方同步序列号。
如果SYN=1而ACK=0,则表示该数据包为连接请求,
如果SYN=1而ACK=1则表示接受连接。
FIN: 表示发送端已经没有数据要求传输了,希望释放连接。
RST: 用来复位一个连接。RST标志置位的数据包称为复位包。
一般情况下,如果TCP收到的一个分段明显不是属于该主机上的任何一个连接,则向远端发送一个复位包。
URG: 为紧急数据标志。如果它为1,表示本数据包中包含紧急数据。此时紧急数据指针有效。
ACK: 为确认标志位。如果为1,表示包中的确认号时有效的。否则,包中的确认号无效。
PSH: 如果置位,接收端应尽快把数据传送给应用层。
端口扫描技术(port scanning)   
端口扫描就是通过连接到目标系统的TCP或UDP端口,来确定什么服务正在运行。一般来说端口扫描有三个用途: 
* 识别目标系统上正在运行的TCP和UDP服务。 
* 识别目标系统的操作系统类型(Windows 9x, Windows NT,或UNIX,等)。 
* 识别某个应用程序或某个特定服务的版本号。   
端口扫描技术: 
1. TCP connect scan:这种方法最简单,直接连到目标端口并完成一个完整的三次握手过程(SYN, SYN/ACK, 和ACK)。
缺点是容易被目标系统检测到。 
2. TCP SYN scan:
这种技术也叫“半开式扫描”(half-open scanning),
因为它没有完成一个完整的TCP连接。这种方法向目标端口发送一个SYN分组(packet),
如果目标端口返回SYN/ACK,那么可以肯定该端口处于检听状态;
否则,返回的是RST/ACK。
这种方法比第一种更具隐蔽性,可能不会在目标系统中留下扫描痕迹。 
3. TCP FIN scan:这种方法向目标端口发送一个FIN分组。
按RFC793的规定(/),
对于所有关闭的端口,目标系统应该返回RST标志。
这种方法通常用在基于UNIX的TCP/IP堆栈。 
4. TCP Xmas Tree scan:这种方法向目标端口发送一个含有FIN, URG,和PUSH标志的分组。
根据RFC793,对于所有关闭的端口,目标系统应该返回RST标志。 
5. TCP Null scan:这种方法向目标端口发送一个不包含任何标志的分组。
根据RFC793,对于所有关闭的端口,目标系统应该返回RST标志。 
6. UDP scan:这种方法向目标端口发送一个UDP分组。
如果目标端口以“ICMP port unreachable”消息响应,那么说明该端口是关闭的;
反之,如果没有收到“ICMP port unreachable”响应消息,则可以肯定该端口是打开的。
由于UDP协议是面向无连接的协议,这种扫描技术的精确性高度依赖于网络性能和系统资源。
另外,如果目标系统采用了大量分组过滤技术,那么UDP扫描过程会变得非常慢。气体混合器
如果你想对Internet进行UDP扫描,那么你不能指望得到可靠的结果。   
另外,有某种系统的IP协议是这样实现的,对于所有扫描的端口,不管他们处于关闭或者监听状态,
都返回RST标志(我们知道,这不符合RFC793的规定)。因此,扫描这种系统时,用不同的扫描技术可能得到不同的扫描结果。   
*/
#include "stdio.h"
#include "winsock2.h"
#include "WS2TCPIP.H"
#include "mstcpip.h"
#pragma comment(lib,"ws2_32")
#define SEQ 0x28376839 //ip数据包的首部数据结构
typedef struct _iphdr {
unsigned char h_lenver; //4位首部长度+4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
有线电视分支分配器unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;
typedef struct _tcphdr //定义TCP首部
USHORT th_sport; //16位源端口
USHORT th_dport; //16位目的端口
unsigned int th_seq; //32位序列号
unsigned int th_ack; //32位确认号
unsigned char th_lenres; //4位首部长度/6位保留字
unsigned char th_flag; //6位标志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位校验和
USHORT th_urp; //16位紧急数据偏移量
}TCP_HEADER;
struct //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz; char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}psd_header;
SOCKET sockRaw = INVALID_SOCKET, sockListen = INVALID_SOCKET;
struct sockaddr_in dest;
/
/SOCK错误处理程序
void CheckSockError(int iErrorCode, char *pErrorMsg)
{
if(iErrorCode==SOCKET_ERROR) {
printf("%s Error:%d\n", pErrorMsg, GetLastError());
closesocket(sockRaw);
ExitProcess(-1);
}
}
//计算检验和
USHORT 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);
}
/
/IP解包程序
int DecodeIPHeader(char *recvbuf, int bytes)
{
IP_HEADER *iphdr;
TCP_HEADER *tcphdr;
unsigned short iphdrlen;
iphdr = (IP_HEADER *)recvbuf;
iphdrlen = sizeof(unsigned long) * (iphdr->h_lenver & 0xf);
tcphdr = (TCP_HEADER*)(recvbuf + iphdrlen); //是否来自目标IP
if(iphdr->sourceIP != dest.sin_addr.s_addr)
return 0; //序列号是否正确
if((ntohl(tcphdr->th_ack) != (SEQ+1)) && (ntohl(tcphdr->th_ack) != SEQ))
return 0; //RST/ACK - 无服务
if(tcphdr->th_flag == 20) {
printf("RST+ACK 无服务.\n");
return 1;
} //SYN/ACK - 扫描到一个端口
if(tcphdr ->th_flag == 18) {
printf("%d\n",ntohs(tcphdr->th_sport));
return 2;
}
return true; 测量电池内阻
}
//主函数
int main(int argc,char *argv[])
{
int iErrorCode;
int datasize;
struct hostent *hp;
IP_HEADER ip_header;
TCP_HEADER tcp_header;
char SendBuf[128]={0};
char RecvBuf[65535]={0};
printf("Useage: Target_ip Target_port \n");
//if (argc!=3) { return false; } //初始化SOCKET
WSADATA wsaData;
iErrorCode = WSAStartup(MAKEWORD(2,2),&wsaData);
CheckSockError(iErrorCode, "WSAStartup()");
sockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
sis压片CheckSockError(sockRaw, "socket()");
sockListen = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockListen, "socket"); //设置IP头操作选项
BOOL bOpt = true;
iErrorCode = setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&bOpt,sizeof(bOpt));
CheckSockError(iErrorCode, "setsockopt()"); //获得本地IP
SOCKADDR_IN sa; 黄军导航
unsigned char LocalName[256];
iErrorCode = gethostname((char*)LocalName,sizeof(LocalName)-1);
CheckSockError(iErrorCode, "gethostname()");
if((hp = gethostbyname((char*)LocalName)) == NULL) {
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
memcpy(&sa.sin_addr.S_un.S_addr,hp->
h_addr_list[0],hp->h_length);
sa.sin_family = AF_INET;
sa.sin_port = htons(7000);
iErrorCode = bind(sockListen, (PSOCKADDR)&sa, sizeof(sa));
CheckSockError(iErrorCode, "bind"); //设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
iErrorCode=WSAIoctl(sockListen, SIO_RCVALL,&dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );
CheckSockError(iErrorCode, "Ioctl"); //获得目标主机IP
memset(&dest,0,sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(argv[2]));
if((dest.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE) {
if((hp = gethostbyname(argv[1])) != NULL) {
memcpy(&(dest.sin_addr),hp->h_addr_list[0],hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("dest.sin_addr = %s\n",inet_ntoa(dest.sin_addr));
} else {
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
} //填充IP首部
ip_header.h_lenver=(4<<4 | sizeof(ip_header)/sizeof(unsigned long)); //高四位IP版本号,低四位首部长度
al_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)); //16位总长度(字节)
ip_header.ident=1; //16位标识
ip_header.frag_and_flags=0; //3位标志位
l=128; //8位生存时间TTL
ip_header.proto=IPPROTO_TCP; //8位协议(TCP,UDP…)
ip_header.checksum=0; //16位IP首部校验和
ip_header.sourceIP=sa.sin_addr.s_addr; //32位源IP地址
ip_header.destIP=dest.sin_addr.s_addr; //32位目的IP地址 //填充TCP首部
tcp_header.th_sport=htons(7000); //源端口号
tcp_header.th_dport=htons(atoi(argv[2])); //目的端口号
tcp_header.th_seq=htonl(SEQ); //SYN序列号
tcp_header.th_ack=0; //ACK序列号置为0
tcp_header.th_lenres=(sizeof(TCP_HEADER)/4<<4|0); //TCP长度和保留位
tcp_header.th_flag=2; //SYN 标志
tcp_header.th_win=htons(16384); //窗口大小
tcp_header.th_urp=0; //偏移
tcp_header.th_sum=0; //校验和
//填充TCP伪首部(用于计算校验和,并不真正发送)
psd_header.saddr=ip_header.sourceIP;
psd_header.daddr=ip_header.destIP;
psd_header.mbz=0;
psd_header.ptcl=IPPROTO_TCP;
pl=htons(sizeof(tcp_header)); //计算TCP校验和,计算校验和时需要包括TCP pseudo header
memcpy(SendBuf,&psd_header,sizeof(psd_header));
memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header)); //计算IP校验和
memcpy(SendBuf,&ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
datasize=sizeof(ip_header)+sizeof(tcp_header);
ip_header.checksum=checksum((USHORT *)SendBuf,datasize); //填充发送缓冲区
memcpy(SendBuf,&ip_header,sizeof(ip_header)); //发送TCP报文
iErro
rCode=sendto(sockRaw,SendBuf,datasize,0,(struct sockaddr*) &dest,sizeof(dest));
CheckSockError(iErrorCode, "sendto()"); //接收数据
DWORD timeout = 200000;//2000
DWORD start = GetTickCount();
while(true) { //计时,2s超时
if((GetTickCount() - start) >= timeout) break;
memset(RecvBuf, 0, sizeof(RecvBuf));
iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
CheckSockError(iErrorCode, "recv");
if(int i = DecodeIPHeader(RecvBuf,iErrorCode)) {
if(i == 1) break;
tcp_header.th_flag=4; //RST 标志
/
/计算TCP校验和,计算校验和时需要包括TCP pseudo header
memcpy(SendBuf,&psd_header,sizeof(psd_header));
memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header)); //计算IP校验和
memcpy(SendBuf,&ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
datasize=sizeof(ip_header)+sizeof(tcp_header);
ip_header.checksum=checksum((USHORT *)SendBuf,datasize); //填充发送缓冲区
memcpy(SendBuf,&ip_header,sizeof(ip_header)); //发送TCP报文
iErrorCode=sendto(sockRaw,SendBuf,datasize,0,(struct sockaddr*) &dest, sizeof(dest));
CheckSockError(iErrorCode, "sendto()");
break;
}
} //退出前清理
if(sockRaw != INVALID_SOCKET) closesocket(sockRaw);
WSACleanup();
getchar();
return 0;
}

本文发布于:2024-09-22 01:43:47,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/99455.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:cc2530_I2C
标签:端口   目标   连接   扫描   系统   发送
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议