Winsocket programming-original socket

Source: Internet
Author: User

The original socket is a socket programming interface exposed By Winsock. It allows us to program sockets on the IP layer and control their behavior. common applications include packet capture (sniffer) analysis Package, flood attack, ICMP ping, etc., but it cannot intercept packets (the so-called interception package is to intercept the package, to achieve this "firewall" function, the driver layer must be a lower one ). However, copying packets from the network to the local machine is a very useful function. I once tried to open my sniffer in a LAN, and copied all the packets from my colleagues' computers. Then, if you perform some analysis on the package, hum...

In fact, the most fundamental of the original socket is that you can construct your own IP package at the IP layer and then send this IP package out. Similarly, we can capture and analyze packets from the TCP/UDP Transport layer...

It is also easy to write the original socket program, because Windows has helped us define and implement these interfaces (Winsock ). In addition, we also need to define the structure definitions of IP and UDP headers. For details, refer to the following code.

The following is a rawsniffer class I defined. This class uses the original socket to implement a listener. This class also relies on MFC (I have been developing it on Windows platform, it is also used for MFC, so it is a bit preference for MFC ...). The following is the code of the class:

// Header file

# Ifndef raw_def_h
# Define raw_def_h

# Include <winsock2.h>
# Pragma comment (Lib, "ws2_32 ")

# Include <ws2tcpip. h>
# Include <mstcpip. h> // This file is a function of the Windows platform SDK. If it cannot be found, install the SDK

# Define protocol_string_icmp_txt "ICMP"
# Define protocol_string_tcp_txt "TCP"
# Define protocol_string_udp_txt "UDP"
# Define protocol_string_spx_txt "SPX"
# Define protocol_string_ncp_txt "NCP"
# Define protocol_string_unknow_txt "unknow"

// Define the IP Header
Typedef struct ip_hdr
{
Unsigned char h_verlen; // 4-bit header length, 4-bit IP version number
Unsigned char TOS; // an 8-bit service type TOS
Unsigned short total_len; // The total length of 16 bits (in bytes)
Unsigned short ident; // 16-bit ID
Unsigned short frag_and_flags; // 3-Bit Flag
Unsigned char TTL; // 8-bit TTL
Unsigned char proto; // 8-bit protocol (TCP, UDP, or other)
Unsigned short checksum; // 16-bit IP header checksum
Unsigned int sourceip; // 32-bit source IP address
Unsigned int destip; // 32-bit destination IP address
} Ipheader;

// Define the TCP pseudo Header
Typedef struct tsd_hdr
{
Unsigned long saddr; // Source Address
Unsigned long daddr; // Destination Address
Char mbz; // 0
Char ptcl; // protocol UDP protocol type: 17; TCP protocol: 6
Unsigned short tcpl; // TCP packet length
} Psdheader;

// Define the TCP Header
Typedef struct tcp_hdr
{
Ushort th_sport; // 16-bit 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-bit header length/6-bit reserved words
Unsigned char th_flag; // 6-digit flag
Ushort th_win; // 16-bit window size
Ushort th_sum; // 16-bit checksum
Ushort th_urp; // 16-bit emergency data offset
} Tcpheader;

// Define the ICMP Header
Typedef struct icmp_hdr
{
Unsigned char I _type; // type
Unsigned char I _code; // code
Unsigned short I _cksum; // check code
Unsigned short I _id; // non-standard ICMP Header
Unsigned short I _seq;
Unsigned long timestamp;
} Icmpheader;

// Define the UDP Header
// The UDP packet is lick this. took from rfc768.
// 0 7 8 15 16 23 24 31
// + -------- +
// | Source | destination |
// | Port |
// + -------- +
// |
// | Length | checksum |
// + -------- +
// |
// | Data octets...
// + ----------------...

Typedef struct udp_hdr // 8 bytes
{
Unsigned short uh_sport;
Unsigned short uh_dport;
Unsigned short uh_len;
Unsigned short uh_sum;
} Udpheader;

/*
// Do not place the function implementation in the header file; otherwise, the definition will be repeated in different places.
// Checksum: The subfunction used to calculate the checksum.
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 & 0 xFFFF );
Cksum + = (cksum> 16 );
Return (ushort )(~ Cksum );
}
*/

Ushort checksum (ushort * buffer, int size );

// Callback function

// The callback function is called when a packet is caught.
Typedef int (callback * capturedef) (cstring & strmsg );

Class yrawsniffer
{
Public:
Yrawsniffer ();
~ Yrawsniffer ();
Bool startall ();
Bool exitall ();
Bool capture (capturedef capturefunc = NULL );
Bool stopcapture ();

Static DWORD winapi capturethread (lpvoid lpparam );
Handle m_hcapturethread;

// Filter criteria
Bool m_bcaptcp;
Bool m_bcapudp;
Bool m_bcapicmp;
Cstring m_strsrcip;
Cstring m_strdstip;
 
Socket m_rawsock;
// Cstring m_strfilepath;

PRIVATE:
Capturedef m_capturefunc;
Bool m_bexitcapture;
 
Ipheader m_ipheader;
Tcpheader m_tcpheader;
Icmpheader m_icmpheader;
Udpheader m_udpheader;
};

# Endif

// CPP File

# Include "stdafx. H"
# Include "rawdef. H"

// Checksum: The subfunction used to calculate the checksum.
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 & 0 xFFFF );
Cksum + = (cksum> 16 );
Return (ushort )(~ Cksum );
}

Char * getprotocol (int proto)
{
Switch (PROTO)
{
Case ipproto_icmp: Return protocol_string_icmp_txt;
Case ipproto_tcp: Return protocol_string_tcp_txt;
Case ipproto_udp: Return protocol_string_udp_txt;
Default: Return protocol_string_unknow_txt;
}
}

DWORD waitforobjectex (handle hhandle, DWORD dwmilliseconds)
{
Bool Bret;
MSG;
Int iwaitret;
DWORD ntimeout = 0;
While (Bret =: getmessage (& MSG, null, 0, 0 ))! = 0)
{
If (ntimeout ++ * 100> = dwmilliseconds)
Break;

Iwaitret = waitforsingleobject (hhandle, 100 );
If (iwaitret! = Wait_timeout)
{
Break;
}
If (Bret =-1)
{
Break;
}
Else
{
: Translatemessage (& MSG );
: Dispatchmessage (& MSG );
}
}

Return iwaitret;
}

 

//////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// ///////
Yrawsniffer * g_rawsniffer;

Yrawsniffer: yrawsniffer ()
{
M_bcaptcp = false;
M_bcapudp = false;
M_bcapicmp = false;
M_strsrcip = "";
M_strdstip = "";

M_rawsock = invalid_socket;
// M_strfilepath = "";

M_bexitcapture = false;
M_capturefunc = NULL;
M_hcapturethread = NULL;

G_rawsniffer = this;

Wsadata;
If (wsastartup (makeword (2, 2), & wsadata )! = 0)
{
Trace1 ("wsastartup () error! % D ", getlasterror ());
Return;
}

}

Yrawsniffer ::~ Yrawsniffer ()
{
Wsacleanup ();
}

Bool yrawsniffer: exitall ()
{
M_bexitcapture = true;

Shutdown (m_rawsock, sd_both );
 
If (m_hcapturethread! = NULL)
{
DWORD dwret = 0;
Dwret = waitforobjectex (m_hcapturethread, infinite );
If (dwret = wait_object_0)
{
Trace ("capturethread exit success! ");
}
Closesocket (m_rawsock );
M_rawsock = invalid_socket;
Closehandle (m_hcapturethread );
M_hcapturethread = NULL;
}

Trace ("exitall OK! ");

Return true;
}

Bool yrawsniffer: startall ()
{
M_bexitcapture = false;

Sockaddr_in addr_in;

If (m_rawsock = invalid_socket)
M_rawsock = socket (af_inet, sock_raw, ipproto_ip );

Bool flag = true;

If (setsockopt (m_rawsock, ipproto_ip, ip_hdrincl, (char *) & flag, sizeof (FLAG ))! = 0)
{
Trace1 ("setsockopt () error! % D ", wsagetlasterror ());
Return false;
}
 
Char localname [16];
Struct hostent * phost;

// Obtain the local name
If (gethostname (char *) localname, sizeof (localname)-1) = socket_error)
{
Trace1 ("gethostname error! % D ", wsagetlasterror ());
Return false;
}
 
// Obtain the local IP Address
If (phost = gethostbyname (char *) localname) = NULL)
{
Trace1 ("gethostbyname error! % D ", wsagetlasterror ());
Return false;
}
 
// M_strsrcip = phost-> h_addr_list [0];
Addr_in.sin_addr = * (in_addr *) phost-> h_addr_list [0]; // ip
Addr_in.sin_family = af_inet;
Addr_in.sin_port = htons (0, 57274 );
 
If (BIND (m_rawsock, (struct sockaddr *) & addr_in, sizeof (addr_in ))! = 0)
{
Trace1 ("BIND error! % D ", wsagetlasterror ());
Return false;
}
 
// Set the I/O behavior of the NIC to receive all packets on the network
DWORD dwvalue = 1;
If (ioctlsocket (m_rawsock, sio_rcvall, & dwvalue )! = 0)
{
Trace1 ("ioctlsocket error! % D ", wsagetlasterror ());
Return false;
}

Return true;
}

DWORD winapi yrawsniffer: capturethread (lpvoid lpparam)
{
// Cfile flog;
// Bool blogfile = false;
// Open the record file
// If (g_rawsniffer-> m_strfilepath = "")
// G_rawsniffer-> m_strfilepath = "C: // capture.txt ";
// If (g_rawsniffer-> m_strfilepath! = "")
//{
// If (! Flog. Open (g_rawsniffer-> m_strfilepath, cfile: modecreate | cfile: modereadwrite ))
// Trace1 ("file flog open failed! % D ", getlasterror ());
// Else
// Blogfile = true;
//}

Const int max_receivebuf = 1000;
Char recvbuf [max_receivebuf] = {0 };
Char MSG [max_receivebuf] = {0 };

Char * PTR = NULL;

Cstring strlog, strtmp, strcontent;

DWORD ntcpcnt = 0, nudpcnt = 0, nicmpcnt = 0;

While (! G_rawsniffer-> m_bexitcapture)
{
Int ret = Recv (g_rawsniffer-> m_rawsock, recvbuf, max_receivebuf, 0 );
If (ret = socket_error)
Trace1 ("% d, Recv (g_rawsniffer-> m_rawsock, recvbuf, max_receivebuf, 0) failed! ", Getlasterror ());

Strlog = "";
Strcontent = "";

If (Ret> 0)
{
G_rawsniffer-> m_ipheader = * (ipheader *) recvbuf;

// Get the correct IP header length
Int iiphlen = sizeof (unsigned long) * (g_rawsniffer-> m_ipheader.h_verlen & 0xf );
Int cpysize = 0;

// Filter the target IP address or source IP address
// If (g_rawsniffer-> m_strsrcip.find (".")> 0
// | G_rawsniffer-> m_strdstip.find (".")> 0)
{
If (g_rawsniffer-> m_strsrcip! = ""
| G_rawsniffer-> m_strdstip! = "")
{
If (inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.sourceip )! = G_rawsniffer-> m_strsrcip
& Inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.destip )! = G_rawsniffer-> m_strdstip)
Continue;
}
}

/*
// Filter the target IP address or source IP address
If (g_rawsniffer-> m_strsrcip! = "")
{
If (inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.sourceip )! = G_rawsniffer-> m_strsrcip)
Continue;
}

If (g_rawsniffer-> m_strdstip! = "")
{
If (inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.destip )! = G_rawsniffer-> m_strdstip)
Continue;
}
*/

If (g_rawsniffer-> m_ipheader.proto = ipproto_tcp & g_rawsniffer-> m_bcaptcp)
{
Ntcpcnt ++;
G_rawsniffer-> m_tcpheader = * (tcpheader *) (recvbuf + iiphlen );
Strtmp. Format ("Get % d TCP packet", ntcpcnt); strlog + = strtmp;
Strtmp. Format ("Protocol: % S/R/N", getprotocol (g_rawsniffer-> m_ipheader.proto); strlog + = strtmp;
Strtmp. Format ("IP Source Address: % S/R/N", inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.sourceip); strlog + = strtmp;
Strtmp. Format ("ip Destination Address: % S/R/N", inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.destip); strlog + = strtmp;
Strtmp. Format ("TCP source port: % d/R/N", g_rawsniffer-> m_tcpheader.th_sport); strlog + = strtmp;
Strtmp. Format ("TCP destination port: % d/R/N", g_rawsniffer-> m_tcpheader.th_dport); strlog + = strtmp;
Strtmp. Format ("Packet Length: % d/R/N", ntohs (g_rawsniffer-> m_ipheader.total_len); strlog + = strtmp;
Strtmp. Format ("TCP packet content:/R/N"); strlog + = strtmp;

PTR = recvbuf + iiphlen + (4 * (g_rawsniffer-> m_tcpheader.th_lenres & 0xf0)> 4 | 0 ));
Cpysize = ntohs (g_rawsniffer-> m_ipheader.total_len)-(iiphlen + (4 * (g_rawsniffer-> m_tcpheader.th_lenres & 0xf0)> 4 | 0 )));

// ASCII code
Memcpy (MSG, PTR, cpysize );
For (INT I = 0; I <cpysize; I ++)
{
If (MSG [I]> = 32 & MSG [I] <255)
{
Strcontent. Format ("% C", (unsigned char) MSG [I]); strlog + = strcontent;
}
Else
{
Strcontent. Format ("."); strlog + = strcontent;
}
}
Strtmp. Format ("/R/n/R/N"); strlog + = strtmp;
}


If (g_rawsniffer-> m_ipheader.proto = ipproto_icmp & g_rawsniffer-> m_bcapicmp)
{
Nicmpcnt ++;
G_rawsniffer-> m_icmpheader = * (icmpheader *) (recvbuf + iiphlen );
Strtmp. Format ("Get % d ICMP packet", nicmpcnt); strlog + = strtmp;
Strtmp. Format ("Protocol: % S/R/N", getprotocol (g_rawsniffer-> m_ipheader.proto); strlog + = strtmp;
Strtmp. Format ("IP Source Address: % S/R/N", inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.sourceip); strlog + = strtmp;
Strtmp. Format ("ip Destination Address: % S/R/N", inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.destip); strlog + = strtmp;
Strtmp. Format ("ICMP return type: % d/R/N", g_rawsniffer-> m_icmpheader. I _type); strlog + = strtmp;
Strtmp. Format ("ICMP return code: % d/R/N", g_rawsniffer-> m_icmpheader. I _code); strlog + = strtmp;
Strtmp. Format ("Packet Length: % d/R/n/R/N", ntohs (g_rawsniffer-> m_ipheader.total_len); strlog + = strtmp;
}

If (g_rawsniffer-> m_ipheader.proto = ipproto_udp & g_rawsniffer-> m_bcapudp)
{
Nudpcnt ++;
G_rawsniffer-> m_udpheader = * (udpheader *) (recvbuf + iiphlen );
Strtmp. Format ("Get % d UDP packet", nudpcnt); strlog + = strtmp;
Strtmp. Format ("Protocol: % S/R/N", getprotocol (g_rawsniffer-> m_ipheader.proto); strlog + = strtmp;
Strtmp. Format ("IP Source Address: % S/R/N", inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.sourceip); strlog + = strtmp;
Strtmp. Format ("ip Destination Address: % S/R/N", inet_ntoa (* (in_addr *) & g_rawsniffer-> m_ipheader.destip); strlog + = strtmp;
Strtmp. Format ("UDP source port: % d/R/N", g_rawsniffer-> m_udpheader.uh_sport); strlog + = strtmp;
Strtmp. Format ("UDP destination port: % d/R/N", g_rawsniffer-> m_udpheader.uh_dport); strlog + = strtmp;
Strtmp. Format ("Packet Length: % d/R/N", ntohs (g_rawsniffer-> m_ipheader.total_len); strlog + = strtmp;
Strtmp. Format ("UDP packet content:/R/N"); strlog + = strtmp;

PTR = recvbuf + iiphlen + 8;
Cpysize = ntohs (g_rawsniffer-> m_ipheader.total_len)-(iiphlen + 8 );
Memcpy (MSG, PTR, cpysize );

Strtmp. Format ("ASCII format:/R/N ");
For (INT I = 0; I <cpysize; I ++)
{
If (MSG [I]> = 32 & MSG [I] <255)
{
Strcontent. Format ("% C", (unsigned char) MSG [I]); strlog + = strcontent;
}
Else
{
Strcontent. Format ("."); strlog + = strcontent;
}
}
Strtmp. Format ("/R/n/R/N"); strlog + = strtmp;

Strtmp. Format ("hexadecimal format:/R/N"); strlog + = strtmp;
For (I = 0; I <cpysize; I ++)
{
Strtmp. Format ("% 2.2x", (unsigned char) MSG [I]); strlog + = strtmp;
}
Strtmp. Format ("/R/n/R/N"); strlog + = strtmp;

}

If (g_rawsniffer-> m_capturefunc! = NULL & strlog. getlength ()> 0 & strcontent. getlength ()> 0)
G_rawsniffer-> m_capturefunc (strlog );

Sleep (10 );
}
}

// Close the record file
// If (blogfile)
// Flog. Close ();

Return 0;
}

Bool yrawsniffer: capture (capturedef capturefunc/* = NULL */)
{
Startall ();

If (capturefunc! = NULL)
M_capturefunc = capturefunc;

// Create a thread to capture the package
M_bexitcapture = false;
M_hcapturethread = createthread (null, 0, capturethread, null, 0, null );
If (null = m_hcapturethread)
Trace1 ("/" m_hcapturethread = createthread (null, 0, capturethread, null, 0, null)/"failed! % D ", getlasterror ());

Return true;
}

Bool yrawsniffer: stopcapture ()
{
Return exitall ();
}

This class is easy to use. Declare a Global Object (or member variable) and use its capture and stopcapture. Remember to call stopcapture when the program exits.

When calling the capture function, you need to assign some filtering conditions to it:

// Filter Condition
G_sniffer.m_bcaptcp = m_bcaptcp; // capture a TCP packet. True indicates capture, and false indicates no capture.
G_sniffer.m_bcapudp = m_bcapudp; // capture a UDP packet. True indicates the packet is captured, and false indicates the packet is not captured.
G_sniffer.m_bcapicmp = m_bcapicmp; // capture ICMP packets. True indicates capture, and false indicates no capture.
G_sniffer.m_strsrcip = m_strsrcip; // The Source IP address string of the package. It is null and is not limited.
G_sniffer.m_strdstip = m_strdstip; // the destination IP address string of the package. null is not limited.

G_sniffer.capture (capfunc );

The captured package will be formatted and passed to you in a callback function.

For example, my callback function is as follows:

Int callback capfunc (cstring & strlog)
{
G_rawdlg-> addlog (strlog); // output the captured package in an edit box of the DLG.
G_log.writelogfileraw (strlog); // enter a log file.

Return 0;
}

With the above knowledge, you can use this class to implement a sniffer. It is very easy to do three steps: 1. Add the class to the project. 2. Include the header file, declare object 3. Use the capture and stopcapture of this object.

The above shows that my original design is to put the record Package function in the class. However, I think this class should not do so much work, so let the record package work on the upper layer. So the callback function is used.

Through the study of the above Code, you should understand the original socket, this technology can not only do sniffer, but also realize flood attacks and so on (because you can build your own IP packet ).

Finally, I will provide a program interface implemented using this class. Of course, you need to handle the logic of the interface. If you need a friend, please leave the address and I will send you the routine.

That's all, happy every day!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.