Creation time: 2002-02-01
Article attribute: original
Article submission:
Refdom (refDom_at_263.net)
Author: refdom (refdom@263.net)
2002/1/31
Windows2000 has made a lot of improvements on TCP / IP protocol components, and features are also enhanced. For example, the adjustment on the protocol stack increases the default window size, and the high delay link new algorithm. At the same time, IPSec is applied to security, and there are many improvements in NT.
The Microsoft TCP / IP component contains "core protocol", "service", and "interfaces" between the two. Transmission Driver Interface (TDI) and Network Device Interface Specification (NDIS) are public. In addition, there are more advanced interfaces for many user model applications. The most common interface is Windows Sockets, Remote Process Call (RPC) and NetBIOS.
Windows Sockets is a programming interface that is defined on the basis of the socket interface developed by the University of California. It includes a set of expansions to make full use of the Microsoft Windows messaging feature. The normative version 1.1 is released in January 1993, and version 2.2.0 was issued in May 1996. Windows 2000 supports Winsock 2.2. In Winsock2, the original socket, overlapping I / O model, service quality control, etc. are supported by multiple transport protocols.
Here you will introduce some of the programming of the Raw Socket for Windows Sockets. Compared with Winsock1, the most obvious is to support the RAW Socket socket type. Through the original socket, we can control a variety of protocols under Windows, and can control the transmission mechanism of the network underlayer.
1. Create an original socket and set the IP header option.
Socket sock;
SOCK = Socket (AF_INET, SOCK_RAW, IPPROTO_IP);
or:
S = WSASOCCKET (AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
Here, we set up the SOCK_RAW flag, indicating that we declare a raw socket type. After creating the original socket, the IP header will be included in the received data, if we set the IP_HDRINCL option, then you need yourself to construct an IP header. Note that if you set the IP_HDRINCL option, you must have Administrator permissions, or you must modify the registry:
HKEY_LOCAL_MACHINE / SYSTEM / CURRENTCONTROLSET / SERVICES / AFD / PARAMETER /
Modify key: disableRawsecurity (type DWORD), modify the value to 1. If not, add it.
Bool BLNFLAG = TRUE;
Setsockopt (SOCK, IPPROTO_IP, IP_HDRINCL, (Char *) & blnflag, Sizeof (BLNFLAG);
Pay attention to such a few points when receiving a datagram:
1. If the received datagram is received, the protocol type and the defined original socket match, then all the received data is copied into the socket.
2. If the local address is bound, only the corresponding remote address matching in the received data IP header is copied to the socket.
3. If the external address is defined, for example, using connect (), then only the corresponding source address matching in the received data IP header is copied into the socket. 2, construct IP head and TCP head
Here, the structure of IP head and TCP header:
// Standard TCP Flags
#define urg 0x20
#define ack 0x10
#define psh 0x08
#define rst 0x04
#define SYN 0x02
#define fin 0x01
Typedef struct _iphdr // Defines IP header
{
Unsigned char h_lenver; // 4 top length 4-bit IP version number
Unsigned char TOS; // 8 service type TOS
Unsigned short total_len; // 16-bit total length (bytes)
UNSIGNED short ident; // 16 bit identity
Unsigned short frame_and_flags; // 3 bit flag
Unsigned char TTL; // 8-bit survival time TTL
Unsigned char proto; // 8-bit protocol (TCP, UDP or other)
UNSIGNED Short Checksum; // 16-bit IP header checksum
Unsigned int sourceip; // 32 bitsource IP address
UNSIGNED INT Destip; // 32 bit IP address
} Ip_header;
Typedef struct psd_hdr // Defines TCP pseudo
{
Unsigned long saddr; // source address
Unsigned long daddr; // destination address
CHAR MBZ;
CHAR PTCL; // Protocol Type
Unsigned short tcpl; // TCP length
} PSD_HEADER;
Typedef struct _tcphdr // Define TCP header
{
Ushort th_sport; // 16 bond source port
USHORT TH_DPORT; / / 16-bit destination port
Unsigned int th_seq; // 32-bit serial number
UNSIGNED INT TH_ACK; / / 32 bit confirmation number
Unsigned char th_lenres; // 4 head length / 6 reserved words
Unsigned char th_flag; // 6 bit flag
Ushort TH_WIN; / / 16-bit window size
USHORT TH_SUM; / / 16-bit checksum
Ushort TH_URP; // 16-bit emergency data offset
} TCP_HEADER;
The TCP pseudo head is not really existing, just for calculating inspection and. Check and function:
Ushort Checksum (Ushort * Buffer, int size)
{
Unsigned long cksum = 0;
While (size> 1)
{
CKSUM = * Buffer ;
Size - = SizeOf (Ushort);
}
size
{
CKSUM = * (Uchar *) BUFFER;
}
CKSUM = (CKSUM >> 16) (CKSUM & 0xFFF);
CKSUM = (CKSUM >> 16);
Return (Ushort) (~ CKSUM);
}
When you need to fill your IP head and TCP head, you need to calculate their inspection and.
3, send the original socket dataginary
Fill these heads slightly troublesome, and send relatively simple. Just use Sendto () OK.
Sendto (SOCK, (CHAR *) & TCPHEADER, SIZEOF (TCPHEADER), 0, (SockAddr *) & addr_in, sizeof (addr_in)); the following is a sample program that can be used as part of the SYN scan.
#include
#include
#include
#define Source_Port 7234
#define max_receivebyte 255
Typedef struct ip_hdr // Defines IP header
{
Unsigned char h_verlen; // 4 top length, 4-digit IP version number
Unsigned char TOS; // 8 service type TOS
Unsigned short total_len; // 16-bit total length (bytes)
UNSIGNED short ident; // 16 bit identity
Unsigned short frame_and_flags; // 3 bit flag
Unsigned char TTL; // 8-bit survival time TTL
Unsigned char proto; // 8-bit protocol (TCP, UDP or other)
UNSIGNED Short Checksum; // 16-bit IP header checksum
Unsigned int sourceip; // 32 bitsource IP address
UNSIGNED INT Destip; // 32 bit IP address
} Ipheader;
Typedef struct tsd_hdr // Defines TCP pseudo
{
Unsigned long saddr; // source address
Unsigned long daddr; // destination address
CHAR MBZ;
CHAR PTCL; // Protocol Type
Unsigned short tcpl; // TCP length
} PSDHeader;
Typedef struct tcp_hdr // Defines TCP header
{
Ushort th_sport; // 16 bond source port
USHORT TH_DPORT; / / 16-bit destination port
Unsigned int th_seq; // 32-bit serial number
UNSIGNED INT TH_ACK; / / 32 bit confirmation number
Unsigned char th_lenres; // 4 head length / 6 reserved words
Unsigned char th_flag; // 6 bit flag
Ushort TH_WIN; / / 16-bit window size
USHORT TH_SUM; / / 16-bit checksum
Ushort TH_URP; // 16-bit emergency data offset
} TCPHEADER;
// Checksum: Computing the subunies of the checksum
Ushort Checksum (Ushort * Buffer, int size)
{
Unsigned long cksum = 0;
While (size> 1)
{
CKSUM = * Buffer ;
Size - = SizeOf (Ushort);
}
size
{
CKSUM = * (Uchar *) BUFFER;
}
CKSUM = (CKSUM >> 16) (CKSUM & 0xFFF);
CKSUM = (CKSUM >> 16);
Return (Ushort) (~ CKSUM);
}
Void users ()
{
Printf ("**************************************************************************************************************);
Printf ("tcpping / n");
Printf ("/ T Written By Refdom / N);
Printf ("/ t email: refDom@263.net/n"); Printf ("Useage: tcpping.exe target_ip target_port / n");
Printf ("******************************************************************************************************) ;
}
Int main (int Argc, char * argv [])
{
Wsadata wsadata;
Socket sock;
SockAddr_in addr_in;
Ipheader ipheader;
TCPHEADER TCPHEADER;
PSDHeader PSDHead;
Char szsendbuf [60] = {0};
Bool flag;
Int Rect, NTimeover;
Useage ();
IF (argc! = 3)
{Return False;}
IF (WsaStartup (MakeWord (2, 2), & WSADATA)! = 0)
{
Printf ("WSAStartup Error! / N");
Return False;
}
IF ((SOCK = WSASOCKET (AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0, WSA_FLAG_OVERLAPPED) == Invalid_socket
{
Printf ("socket setup error! / n");
Return False;
}
Flag = true;
IF (setsockopt (sock, ipproto_ip, ip_hdrincl, (char *) & flag, sizeof (flash) == Socket_ERROR)
{
Printf ("setsockopt ip_hdrincl error! / n");
Return False;
}
NTIMEOVER = 1000;
IF (setsockopt (SOCK, SOL_SOCKET, SO_SNDTIMEO, (CHAR *) & ntimeover, sizeof (ntimeover)) == Socket_ERROR)
{
Printf ("setsockopt so_sndtimeo error! / n");
Return False;
}
Addr_in.sin_family = af_INet;
Addr_in.sin_port = htons (ATOI (ARGV [2]));
Addr_in.sin_addr.s_un.s_addr = inet_addr (Argv [1]);
//
//
// Fill the IP head
Ipheader.h_verlen = (4 << 4 | sizeof (iPheter) / sizeof (unsigned long);
// ipHeader.tos = 0;
Ipheter.total_len = Htons (Ipheter) SizeOf (TCPHEADER);
ipHeader.Ident = 1;
Ipheader.frag_and_flags = 0;
Ipheader.ttl = 128;
Ipheader.proto = ipproto_tcp;
Ipheader.checksum = 0;
Ipheader.SourceIP = INET_ADDR ("Local Address");
Ipheader.destip = inet_addr (argv [1]);
// Pack TCP header
TCPHEADER.TH_DPORT = HTONS (ATOI (ARGV [2]));
TCPHEADER.TH_SPORT = htons (source_port); // Source port number TCPHEADER.TH_SEQ = HTONL (0x12345678);
TCPHEADER.TH_ACK = 0;
TCPHEADER.TH_LENRES = (SIZEOF (TCPHEADER) / 4 << 4 | 0);
TCPHEADER.TH_FLAG = 2; // Modify here to achieve different flag detections, 2 is SYN, 1 is Fin, 16 is ACK detection, etc.
TCPHEADER.TH_WIN = HTONS (512);
TCPHEADER.TH_URP = 0;
TCPHEADER.TH_SUM = 0;
PSDHeader.saddr = ipheader.sourceIP;
PSDHeader.daddr = ipheader.destip;
PSDHeader.mbz = 0;
PSDHeader.ptcl = ipproto_tcp;
PSDHeader.tcpl = htons (sizeof (tcpHeader));
// calculate the checksum
Memcpy (Szsendbuf, & Psdheader, Sizeof (psdheader));
Memcpy (Szsendbuf Sizeof (Psdheader), & Tcpheader, Sizeof (TCPHEADER);
TCPHEADER.TH_SUM = Checksum ((Ushort *) SzsendBuf, SizeOf (PSDHeader) Sizeof (TCPHEADER));
Memcpy (SzsendBuf, & ipheader, sizeof (ipheader);
Memcpy (szsendbuf sizeof (ipheader), & tcpheader, sizeof (tcpheader);
MEMSET (SzsendBuf SizeOf (Ipheter) Sizeof (TCPHEADER), 0, 4);
Ipheader.checksum = Checksum ((Ushort *) SzsendBuf, SizeOf (Ipheader) Sizeof (TCPHEADER));
Memcpy (SzsendBuf, & ipheader, sizeof (ipheader);
Rect = Sendto (Sock, Szsendbuf, Sizeof (Ipheader) Sizeof (TCPHEADER),
0, (struct socketdr *) & addr_in, sizeof (addr_in));
IF (Rect == Socket_ERROR)
{
Printf ("Send Error!:% D / N", wsagetlasterror ());
Return False;
}
Else
Printf ("Send OK! / N");
CloseSocket (SOCK);
WSACLEANUP ();
Return 0;
}
4, receive data
Receive is more troublesome compared to sending original socket data. Because we can't use RECV () to receive data on the Raw Socket, all IP packages are first submitted to the system core, then transfer to the user program, when sending a Raws socket package (for example SYN), the core does not know, there is no record that is sent or connected or connected, so when the remote host responds, the system is lost all of them, thus can't get the application. Therefore, it is not possible to simply use the received function to receive these datagrams.
To reach the purpose of receiving data, you must use sniffing, receive all passed packets, and then filter, leaving the need to meet what we need. A raw socket can be defined, used to complete the task of receiving data, need to set SiO_RCVALL, indicating that all data is received. Socket sniffersock;
Sniffsock = WSASOCKET (AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
DWORD LPVBUFFER = 1;
DWORD LPCBBYTESRETURNED = 0;
WSAIOCTL (SnifferSock, SiO_RCVALL, & LPVBUFFER, SIZEOF (LPVBUFFER), NULL, 0, & LPCBBYTESRETURNED, NULL, NULL
Create a raw socket for receiving data, we can use the received function to receive the packet. Then use a filter function to reach the desired purpose to receive the packet we need.
in
http://www.xici.net/board/doc.asp?id=5891453&suB=15 provides a completely sending and reception program, you can refer to.
-------------------------------------------------- ------------
REFERENCE:
1, "MS Windows 2000 TCP-IP IMPLEMENTATION DETAILS"
2, ZISS "Raw Sockets in Windows 2000 / XP"
3, MSDN Platform SDK: "Windows Sockets 2"