Winsock studies

Programming, for all ages and all languages.
Post Reply
chezzestix
Member
Member
Posts: 118
Joined: Mon May 05, 2008 5:51 pm

Winsock studies

Post by chezzestix »

I'm working on understanding sockets and being under windows that includes winsock. I got the basic code idea down I'm pretty sure but the problem comes in the packet. When I TCP connect to http://www.google.com:80 I get some 45:0 packets which I assume is some HTTP stuff (if anyone can help interpret those that would be cool too). But then when I send my self-crafted ping packet I get back a 45:0 containing some HTML code for a "Bad or Malformed Request" page. That means the packet is hitting the server but where am I going wrong in making it? My first guess would be the checksum but Im not real sure what all is supposed to be checksumed so I borrowed the value from another program.

PS: I know the recv code is bad, it was hastily done and never has worked. I just use ip tools to moniter incoming packets. Also excuse the server IP I know thats not google.com I was using their talk server IP for a second test. Same results different except a different page is returned when I send the packet.

Code: Select all

#include <sys/types.h>
#include <winsock.h>
#include <stdio.h>

int main()
{
    WSADATA wsaData;
    SOCKADDR_IN sin;
    SOCKADDR sina;
    int sina_size;
    int iResult;
    hostent* localHost;
    char* localIP;
    char *message, *rec;
    int rec_size;
    
    
    system("pause");
    
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
       printf("WSAStartup failed: %d\n", iResult);
       return 1;
    }
    //get a free socket
    int socknumb = socket(AF_INET, SOCK_STREAM, 0);
    printf("%i\n", socknumb);
    
    localHost = gethostbyname("");
    localIP = inet_ntoa (*(struct in_addr *)*localHost->h_addr_list);

    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr(localIP);
    sin.sin_port = htons(1024);
    //bind the socket
    int bindresult = bind(socknumb, (LPSOCKADDR)&sin, sizeof(sin));
    printf("%i\n", bindresult);
    
    sockaddr_in server; 
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr( "216.239.51.125" );
    server.sin_port = htons( 80 );
    //connect to the server
    int connectresult = connect(socknumb, (LPSOCKADDR)&server, sizeof(server));
    printf("%d\n", connectresult);

    while( 1 == 1 )
    {    
    //start message crafting here
    message = (char*) malloc (12);
    message[0] = char( 8 );
    message[1] = char( 0 );
    message[2] = char( 48 );
    message[3] = char( 0x5c );
    message[4] = char( 1 );
    message[5] = char( 0 );
    message[6] = char( 4 );
    message[7] = char( 0 );
     //end message craft  and send the packet
    int sendresult = send(socknumb, message, 32, MSG_DONTROUTE);
    printf("%d\n", sendresult);
    
    shutdown(socknumb, SD_SEND);
    //recv code
    int recresult = 1;
    rec = (char*) malloc (rec_size);
    recresult = recv(socknumb, rec, rec_size, 0); 
    int err = WSAGetLastError();
    printf("%d %d\n", recresult, err);
    int x = 0;
    while(x < rec_size)
    {
         printf("%i ", int(rec[x]));
         x++;
    }
    printf("\n");
    
    system("pause");
    }
}
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: Winsock studies

Post by JamesM »

Hi,

Firstly you shouldn't receive any packets from the server until you send one (for HTTP). And that's the second thing - you're connecting via TCP/IP to the HTTP standard port then sending an ICMP packet and expecting it to work.

It doesn't work like that, I'm afraid! ICMP is on a much lower layer than TCP in the network stack. You need to specify SOCK_RAW instead of SOCK_STREAM. This does however bring its own can of worms - when I was doing winsock programming (when I was 14, circa 2001) I couldn't find the correct header files under windows for raw packet sending - all the tutorials I found were for linux.

I wish you better luck than I had!

Cheers,

James
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: Winsock studies

Post by 01000101 »

I think this might help you out a bit, some good little ICMP factoids for windows programmers.
http://www.kbcafe.com/articles/HowTo.PING.pdf
User avatar
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Re: Winsock studies

Post by Omega »

Just turn on Ethreal and do the ping from cmd and see what it does and you will know what to do based on that. All those packets you see is just the handshake and the contents of the page probably. You shouldn't need to make a TCP connection to ping btw.
Free energy is indeed evil for it absorbs the light.
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Re: Winsock studies

Post by Dex »

If i understand you right, you are trying to do raw packets, now under XP sp2 you can only receive raw packets, not send any.
If you just want to get googles page your best use these function in this order
InternetOpen
InternetOpenUrl
InternetReadFile
MessageBox
InternetCloseHandle
InternetCloseHandle
ExitProcess

To do what you want.
Dex.
chezzestix
Member
Member
Posts: 118
Joined: Mon May 05, 2008 5:51 pm

Re: Winsock studies

Post by chezzestix »

@JamesM
The "packets" I am getting are handshake just as vst_0201 said. As far as the SOCK_RAW goes I will look into it but the MSDN tutorials use STREAM so thats why Im using it.

@01000101
Informative

@vst_0201
For some goofy reason I cant properly Winsock any pinging program so I am left in the dark. I imagine they might use UDP though...

@dex
There is not real goal of this, I am just studying sockets.

@Everyone
So now Im making code to construct TCP packets. Its about halfway done:

Code: Select all

int int_char2(unsigned int tohex, char *ctwo)
{
    int remainder;
    int x = 4;
    int hex[x];
    x--;
    ctwo = (char*) malloc (2);
    while(x >= 0)
    {
         remainder = tohex % int(pow(float(16) , float(x)));
         if(remainder < tohex)
         {
              tohex = tohex - remainder;
              tohex = tohex / int(pow(float(16) , float(x)));
              if(tohex < 10)
              {
                   hex[x] = tohex;    
              }
              else
              {
                   hex[x] = tohex;
              }
         }
         else
         {
             hex[x] = 0;
         }
         tohex = remainder;
         x--;
    }
    
    ctwo[0] = (hex[3] * 16) + hex[2];
    ctwo[1] = (hex[1] * 16) + hex[0];
    return 0;
}

int int_char4(unsigned long tohex, char *cfour)
{
    int remainder;
    int x = 8;
    int hex[x];
    x--;
    cfour = (char*) malloc (4);
    while(x >= 0)
    {
         remainder = tohex % int(pow(float(16) , float(x)));
         if(remainder < tohex)
         {
              tohex = tohex - remainder;
              tohex = tohex / int(pow(float(16) , float(x)));
              if(tohex < 10)
              {
                   hex[x] = tohex;    
              }
              else
              {
                   hex[x] = tohex;
              }
         }
         else
         {
             hex[x] = 0;
         }
         tohex = remainder;
         x--;
    }
    
    cfour[0] = (hex[7] * 16) + hex[6];
    cfour[1] = (hex[5] * 16) + hex[4];
    cfour[3] = (hex[3] * 16) + hex[2];
    cfour[4] = (hex[1] * 16) + hex[0];
    return 0;
}

int TCP_to96(char* packet, unsigned int Source_Port, unsigned int Destination_Port, unsigned long Sequence_Number, unsigned long ACK_Number)
{
     char dummyt[2], dummyf[4];
     
     packet = (char*) malloc (12);
     int packet_size = sizeof(packet);
     
     int_char2(Source_Port, dummyt);
     packet[0] = dummyt[0];
     packet[1] = dummyt[1];
     
     int_char2(Destination_Port, dummyt);
     packet[2] = dummyt[0];
     packet[3] = dummyt[1];
     
     int_char4(Sequence_Number, dummyf);
     packet[4] = dummyf[0];
     packet[5] = dummyf[1];
     packet[6] = dummyf[2];
     packet[7] = dummyf[3];
     
     int_char4(ACK_Number, dummyf);
     packet[8] = dummyf[0];
     packet[9] = dummyf[1];
     packet[10] = dummyf[2];
     packet[11] = dummyf[3];
     
     return packet_size;
}
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: Winsock studies

Post by JamesM »

chezzestix wrote:@JamesM
The "packets" I am getting are handshake just as vst_0201 said. As far as the SOCK_RAW goes I will look into it but the MSDN tutorials use STREAM so thats why Im using it.

@01000101
Informative

@vst_0201
For some goofy reason I cant properly Winsock any pinging program so I am left in the dark. I imagine they might use UDP though...

@dex
There is not real goal of this, I am just studying sockets.

@Everyone
So now Im making code to construct TCP packets. Its about halfway done:

Code: Select all

int int_char2(unsigned int tohex, char *ctwo)
{
    int remainder;
    int x = 4;
    int hex[x];
    x--;
    ctwo = (char*) malloc (2);
    while(x >= 0)
    {
         remainder = tohex % int(pow(float(16) , float(x)));
         if(remainder < tohex)
         {
              tohex = tohex - remainder;
              tohex = tohex / int(pow(float(16) , float(x)));
              if(tohex < 10)
              {
                   hex[x] = tohex;    
              }
              else
              {
                   hex[x] = tohex;
              }
         }
         else
         {
             hex[x] = 0;
         }
         tohex = remainder;
         x--;
    }
    
    ctwo[0] = (hex[3] * 16) + hex[2];
    ctwo[1] = (hex[1] * 16) + hex[0];
    return 0;
}

int int_char4(unsigned long tohex, char *cfour)
{
    int remainder;
    int x = 8;
    int hex[x];
    x--;
    cfour = (char*) malloc (4);
    while(x >= 0)
    {
         remainder = tohex % int(pow(float(16) , float(x)));
         if(remainder < tohex)
         {
              tohex = tohex - remainder;
              tohex = tohex / int(pow(float(16) , float(x)));
              if(tohex < 10)
              {
                   hex[x] = tohex;    
              }
              else
              {
                   hex[x] = tohex;
              }
         }
         else
         {
             hex[x] = 0;
         }
         tohex = remainder;
         x--;
    }
    
    cfour[0] = (hex[7] * 16) + hex[6];
    cfour[1] = (hex[5] * 16) + hex[4];
    cfour[3] = (hex[3] * 16) + hex[2];
    cfour[4] = (hex[1] * 16) + hex[0];
    return 0;
}

int TCP_to96(char* packet, unsigned int Source_Port, unsigned int Destination_Port, unsigned long Sequence_Number, unsigned long ACK_Number)
{
     char dummyt[2], dummyf[4];
     
     packet = (char*) malloc (12);
     int packet_size = sizeof(packet);
     
     int_char2(Source_Port, dummyt);
     packet[0] = dummyt[0];
     packet[1] = dummyt[1];
     
     int_char2(Destination_Port, dummyt);
     packet[2] = dummyt[0];
     packet[3] = dummyt[1];
     
     int_char4(Sequence_Number, dummyf);
     packet[4] = dummyf[0];
     packet[5] = dummyf[1];
     packet[6] = dummyf[2];
     packet[7] = dummyf[3];
     
     int_char4(ACK_Number, dummyf);
     packet[8] = dummyf[0];
     packet[9] = dummyf[1];
     packet[10] = dummyf[2];
     packet[11] = dummyf[3];
     
     return packet_size;
}
You don't seem to have understood what we said.

Using SOCK_STREAM means that winsock automatically packetises the byte data you send down the socket into TCP packets. If you make your own TCP packets, they will actually get packetised themselves and be rendered useless. This is why you need SOCK_RAW!

As for handshaking packets, you shouldn't receive any handshake packets through that socket, it should be handled internally by winsock.
chezzestix
Member
Member
Posts: 118
Joined: Mon May 05, 2008 5:51 pm

Re: Winsock studies

Post by chezzestix »

Hymmmm....
MSDN wrote:TCP data cannot be sent over raw sockets.
It would seem it is both easier and goofier to send packets than previously though. It would also seem that there is alot less to learn than previously thought I guess I will come up with a project for myself to do in the coming days. Maybe an HTTP server that uses SCTP or something odd like that.
User avatar
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Re: Winsock studies

Post by Omega »

Hey, just use WinPcap and build your own packets that way:

Code: Select all

#include <stdlib.h>
#include <stdio.h>

#include <pcap.h>


int main(int argc, char **argv)
{
	pcap_t *fp;
	char errbuf[PCAP_ERRBUF_SIZE];
	u_char packet[100];
	int i;
	
	/* Check the validity of the command line */
	if (argc != 2)
	{
		printf("usage: %s interface", argv[0]);
		return 1;
	}
    
	/* Open the adapter */
	if ((fp = pcap_open_live(argv[1],		// name of the device
							 65536,			// portion of the packet to capture. It doesn't matter in this case 
							 1,				// promiscuous mode (nonzero means promiscuous)
							 1000,			// read timeout
							 errbuf			// error buffer
							 )) == NULL)
	{
		fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]);
		return 2;
	}

	/* Supposing to be on ethernet, set mac destination to 1:1:1:1:1:1 */
	packet[0]=1;
	packet[1]=1;
	packet[2]=1;
	packet[3]=1;
	packet[4]=1;
	packet[5]=1;
	
	/* set mac source to 2:2:2:2:2:2 */
	packet[6]=2;
	packet[7]=2;
	packet[8]=2;
	packet[9]=2;
	packet[10]=2;
	packet[11]=2;

       //build the rest of the headers here. 
	
	/* Fill the rest of the packet */
	for(i=12;i<100;i++)
	{
		packet[i]=i%256;
	}

	/* Send down the packet */
	if (pcap_sendpacket(fp,	// Adapter
		packet,				// buffer with the packet
		100					// size
		) != 0)
	{
		fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(fp));
		return 3;
	}

	pcap_close(fp);	
	return 0;
}
This is code taken right out of the WinPcap example section of their download. Just use ethereal to capture a ICMP packet from ping.exe and then form yours to look just like that and your done, very simple; I even put a comment in there for you so you know where to start building the rest of the headers. Good luck.
Free energy is indeed evil for it absorbs the light.
User avatar
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Re: Winsock studies

Post by Omega »

I guess they use UDP? They use ICMP. Only ICMP. You are looking at this all wrong. A Packet is whatever you want it to be. The fancy names given to them only describe its protocol. TCP, UDP, ARP, SMB, ICMP, etc all have there own protocol. What defines the packet is its protocol, where it is going (IP, PORT), and headers. You always have an:

Ethernet Header (Hardware): Here is where you grep the mac address or supply it (eehhmm . . . *hint*)
<PROTOCOL> Header (SOFTWARE): Your drivers parse these (WINSOCK) and they describe the DEST IP, SRC IP, PORT, CONTENT

You may even have more headers to deal with depending on the protocol. I think IM has multiple headers both UDP and TCP? Who cares, the point is that the magic comes from the Ethernet Header which you can't touch in Winsock, so you need to use WinPcap if you want to truly create packets.

So, to recap: ICMP is different than UDP and TCP, it has different headers, protocol, etc. If you go the WinPcap route you will need to write filters to filter out ARP, SMB, ICMP, etc packets if you're looking for a specific packet such as let's say TCP. You could grep the URI and spy on your little brother or something. Your best packet resource is Ethereal. I think you are right about Winsock not seeing ICMP packets because it looks for only TCP/UDP ones, so again you need Ethereal. Don't write a HTTP server, that's lame. Write a tool that detects rogue APs or Clients , spam filter, honey pot, ARP Poison Detection, or something cool like that. Be creative. Good luck.
Free energy is indeed evil for it absorbs the light.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Winsock studies

Post by pcmattman »

I've done lots of work with the Winsock libraries, and SOCK_RAW is for creating your own packets (no TCP, UDP, or anything, just above the ethernet layer), SOCK_DGRAM is for UDP, and SOCK_STREAM is for TCP. If you create a SOCK_STREAM socket you do not need to do any TCP initialisation stuff - Winsock does it for you on your connect() call.

If you're doing anything with HTTP I highly suggest using SOCK_STREAM unless you want to try writing your own TCP code, in which case Winsock probably isn't the library you want.
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Re: Winsock studies

Post by Brynet-Inc »

Note, resist the urge to use and "Winsock-only" API's, if you keep it semi-compatible you'll be able to port your code to other platforms.

Fortunately most OS's implement at least a subset of the Berkeley Sockets API.

Best introductory tutorial available: http://www.beej.us/guide/bgnet/
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
Post Reply