windows 套接字

0 views
Skip to first unread message

my12...@gmail.com

unread,
Oct 7, 2005, 12:36:22 AM10/7/05
to java home
我搜了一篇关于着放面的文章,你好好看看吧!

其实很多动西不需要问的,自己艘一下就有了

具体的你可以看这个网址
http://www.morning-tech.com/site/Article_View.asp?id=977

TCP端口扫描方法整理
TCP扫描的主要原理:
RFC793中TCP连接建立的三次握手过程,以及RST报文段的产生条件等

TCP端口扫描方法整理


花了几天搜集这些TCP扫描方法,国外网总上不去,资料不全面.要放假了,时间来不及,下学期有时间再详细描述每种扫描方法吧.
TCP扫描的主要原理:
RFC793中TCP连接建立的三次握手过程,以及RST报文段的产生条件等

常见的TCP扫描方法有:

1.TCP connect scan
这种方法最简单,直接连到目标端口并完成一个完整的三次握手过程(SYN,
SYN/ACK, 和ACK)。缺点是容易被目标系统检测到。
2.TCP SYN scan
这种扫描方式也被称为"半打开扫描"(half-open
scanning)。它利用了TCP连接建立三次握手的第一步,并且没有建立一个完整的TCP连接。实现办法是向远端主机某端口发送一个只有SYN标志位的TCP报文段,如果主机反馈一个SYN|ACK数据包,那么,这个主机正在监听该端口,如果反馈的是RST数据包,说明,主机没有监听该端口。在X-Scanner扫描工具上就有SYN的选择项。
3.TCP FIN scan
这种方法向目标端口发送一个FIN分组。按RFC793的规定,对于所有关闭的端口,目标系统应该返回RST标志。这种方法通常用在基于UNIX的TCP/IP协议栈。
4.TCP ACK scan
发送一个只有ACK标志的TCP数据报给主机,如果主机反馈一个TCP
RST数据报来,那么这个主机是存在的。也可以通过这种技术来确定对方防火墙是否是简单的分组过滤,还是一个基于状态的防火墙。
5.TCP SYN|ACK scan
6.TCP NULL sacn(turn off all flags)
即发送一个没有任何标志位的TCP包,根据RFC793,如果目标主机的相应端口是关闭的话,应该发送回一个RST数据包。
7.TCP Xmas Tree scan(set all flags)
向目标主机发送一个FIN+URG+PUSH分组,根据RFC793,如果目标主机的相应端口是关闭的,那么应该返回一个RST标志。
8.TCP reverse identd scanning
identd protocol (rfc1413): disclose the username of the owner of any
process connected via TCP, even if that process didn't initiate the
connection.
Example: connect to the http port (80), and then use identd to find out
whether the server is running as root.
该方法的缺点是必须建立连接,隐蔽性较差.


下面是一个TCP SYN扫描程序.

程序有两个子线程,SendThread用于发送SYN报文段,RecvThread用于接收SYN|ACK报文段,并从中获取相应的处于LISTEN状态的端口.

//该程序通过raw socket发送TCP报文段
//开发&运行环境: VC6.0 + SDK + Win2000
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib,"ws2_32.lib")

#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)

#define RECV_BUF_SIZE 1024; //receiving buffer size
#define SOURCE_PORT 8088 //local TCP segment source port
#define TCP_RTT 2000 //Round-trip time,in milliseconds

typedef struct _iphdr
{
unsigned char h_verlen;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
}IP_HEADER;

typedef struct _psdhdr //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}PSD_HEADER;

// Standard TCP flags
#define URG 0x20
#define ACK 0x10
#define PSH 0x08
#define RST 0x04
#define SYN 0x02
#define FIN 0x01

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;

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);
}

void useage()
{
printf("TCP SYN Port Scanner\n");
printf("\t Email : moog...@163.net\n");
printf("\t Useage: *.exe Target_ip [start_port] [end_port].\n");
}

SOCKET g_sock; //用于收发TCP报文段的全局socket
hostent* g_pHost;
unsigned int g_nStartPort,g_nEndPort;
void RecvThread(char* sAddr)
{
char RecvBuf[RECV_BUF_SIZE];
IP_HEADER* ip;
TCP_HEADER * tcp;
while(1)
{
int ret = recv(g_sock, RecvBuf, RECV_BUF_SIZE, 0);
if (ret > 0)
{
ip = (IP_HEADER*)RecvBuf;
tcp = (TCP_HEADER*)(RecvBuf + (ip->h_verlen&0x0f)*4);

if(ip->proto!=IPPROTO_TCP)
continue;
if( strcmp(sAddr,inet_ntoa(*(in_addr*)&ip->sourceIP) ) )
continue;
if(tcp->th_flag&SYN && tcp->th_flag&ACK)
printf("Port %6u OPEN.\n",ntohs(tcp->th_sport));
}
}
}
void SendThread(char* sAddr)
{
SOCKADDR_IN addr_dst;
char szSendBuf[60] = {0};
IP_HEADER ipHeader;
TCP_HEADER tcpHeader;
PSD_HEADER psdHeader;
//要发送的目的地址
addr_dst.sin_family = AF_INET;
addr_dst.sin_addr.S_un.S_addr = inet_addr(sAddr);

//填充IP首部
ipHeader.h_verlen = (4<<4 | sizeof(ipHeader)/4);
ipHeader.tos=0;
ipHeader.total_len = htons( sizeof(ipHeader)+sizeof(tcpHeader) );
ipHeader.ident = 1;
ipHeader.frag_and_flags = 0;
ipHeader.ttl = 128;
ipHeader.proto = IPPROTO_TCP;

ipHeader.sourceIP = *(int*)g_pHost->h_addr_list[0];
ipHeader.destIP = inet_addr(sAddr);

//填充TCP首部
tcpHeader.th_sport = htons( SOURCE_PORT ); //源端口号
tcpHeader.th_seq = htonl( 0x12345678 );
tcpHeader.th_ack = 0;
tcpHeader.th_lenres = (sizeof(tcpHeader)/4<<4|0);
tcpHeader.th_flag = SYN;//发送SYN报文段
tcpHeader.th_win = htons(512);
tcpHeader.th_urp = 0;

psdHeader.saddr = ipHeader.sourceIP;
psdHeader.daddr = ipHeader.destIP;
psdHeader.mbz = 0;
psdHeader.ptcl = IPPROTO_TCP;
psdHeader.tcpl = htons(sizeof(tcpHeader));

for(unsigned int nPort=g_nStartPort; nPort {
ipHeader.checksum = 0;
tcpHeader.th_sum = 0;
tcpHeader.th_dport = htons( nPort );

//计算TCP校验和
memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));
memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));
tcpHeader.th_sum = checksum((USHORT
*)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader));

//计算IP校验和
memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), 0, 4);
ipHeader.checksum = checksum((USHORT *)szSendBuf,
sizeof(ipHeader)+sizeof(tcpHeader));

memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));

addr_dst.sin_port = htons( nPort );
int ret = sendto(g_sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader),
0, (struct sockaddr*)&addr_dst, sizeof(addr_dst) );
}
//等待一个合适的RTT周期.RTT太小可能导致被扫描主机端口的SYN|ACK报文来不及接收
Sleep(TCP_RTT);
}
int main(int argc,char* argv[])
{
if (argc<2)
{
useage();
return 0;
}
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0)
{
printf("WSAStartup Error!\n");
return -1;
}
if
((g_sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)

{
printf("Socket Setup Error!\n");
return -1;
}
BOOL flag = true;
//包含IP头部,即程序自己封装IP头部,接收的数据报中也包含IP头部
if (setsockopt(g_sock,IPPROTO_IP, IP_HDRINCL,(char
*)&flag,sizeof(flag))==SOCKET_ERROR)
{
printf("setsockopt IP_HDRINCL error!\n");
return -1;
}

//将本主机的IP地址赋给源IP
char sLocalName[64];
gethostname((char*)sLocalName, sizeof(sLocalName)-1);
g_pHost = gethostbyname(sLocalName);

// 填充SOCKADDR_IN结构
sockaddr_in addr_local;
addr_local.sin_addr = *(in_addr *)g_pHost->h_addr_list[0];
//绑定到本地网卡,INADDR_ANY不行
addr_local.sin_family = AF_INET;
addr_local.sin_port = htons(SOURCE_PORT);

// 把原始套接字sock 绑定到本地网卡地址上
if( bind(g_sock, (PSOCKADDR)&addr_local,
sizeof(sockaddr_in))==SOCKET_ERROR )
{
printf("Bind Error:%d.\n",WSAGetLastError());
WSACleanup();
return -1;
}

//
设置SOCK_RAW为SIO_RCVALL(混合模式),以便接收所有的IP包.
DWORD dwValue = 1;
ioctlsocket(g_sock, SIO_RCVALL, &dwValue); //
dwValue为1时执行,0时取消

//发送超时计时
int nTimeOut = 500;
if (setsockopt(g_sock,SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOut,
sizeof(nTimeOut))==SOCKET_ERROR)
{
printf("setsockopt SO_SNDTIMEO error!\n");
return -1;
}

g_nStartPort= argc>=3 ? atoi(argv[2]) : 1;
g_nEndPort = argc>=4 ? atoi(argv[3]) : 65535;

printf("Scanning %s from port %d to
%d...\n",argv[1],g_nStartPort,g_nEndPort);
HANDLE threads[2];
threads[0] = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)RecvThread,
(LPVOID)argv[1],
0,
NULL);
threads[1] = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)SendThread,
(LPVOID)argv[1], //destination IP address
0,
NULL);
WaitForMultipleObjects(2,threads,FALSE,INFINITE);
printf("Scan complete.\n",argv[1],g_nStartPort,g_nEndPort);
closesocket(g_sock);
WSACleanup();
return 0;
}


Never give up!

Reply all
Reply to author
Forward
0 new messages