Raw Socket Programming under Windows 2000

zhaozj2021-02-17  41

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

Below is an example program that can be part of the SYN scan.

#include

#include

#include

#define Source_Port 7234

#define max_receivebyte 255typedef 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.

At http://www.xici.net/board/doc.asp?id=5891453&sub=15 provides a complete sector, which can be referred 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"

转载请注明原文地址:https://www.9cbs.com/read-28714.html

New Post(0)