Page 1 of 1

Winsock studies

Posted: Wed Jun 25, 2008 11:53 am
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");
    }
}

Re: Winsock studies

Posted: Wed Jun 25, 2008 12:15 pm
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

Re: Winsock studies

Posted: Wed Jun 25, 2008 1:30 pm
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

Re: Winsock studies

Posted: Wed Jun 25, 2008 2:04 pm
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.

Re: Winsock studies

Posted: Wed Jun 25, 2008 2:23 pm
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.

Re: Winsock studies

Posted: Thu Jun 26, 2008 7:39 pm
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;
}

Re: Winsock studies

Posted: Fri Jun 27, 2008 4:19 am
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.

Re: Winsock studies

Posted: Fri Jun 27, 2008 2:09 pm
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.

Re: Winsock studies

Posted: Fri Jun 27, 2008 2:17 pm
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.

Re: Winsock studies

Posted: Sat Jun 28, 2008 1:53 am
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.

Re: Winsock studies

Posted: Sun Jun 29, 2008 2:57 am
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.

Re: Winsock studies

Posted: Sun Jun 29, 2008 11:29 am
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/