Raw socket

This is a discussion on Raw socket within the Networking/Device Communication forums, part of the General Programming Boards category; This code basicly tries to open a raw socket and send data with a self made IP header and TCP ...

  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    48

    Raw socket

    This code basicly tries to open a raw socket and send data with a self made IP header and TCP header.
    A tutorial found on the internet. However i can't make it working. Sendto returns -1.
    Wireshark doesn't capture anything. Can anyone find the code error in it? Thanks

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    #include <iostream>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    using namespace std;
    #define P 25		
    
    unsigned short		
    csum (unsigned short *buf, int nwords)
    {
      unsigned long sum;
      for (sum = 0; nwords > 0; nwords--)
        sum += *buf++;
      sum = (sum >> 16) + (sum & 0xffff);
      sum += (sum >> 16);
      return ~sum;
    }
    
    struct ip {
     unsigned char ip_hl:4, ip_v:4; 
     unsigned char ip_tos;
     unsigned short int ip_len;
     unsigned short int ip_id;
     unsigned short int ip_off;
     unsigned char ip_ttl;
     unsigned char ip_p;
     unsigned short int ip_sum;
     unsigned int ip_src;
     unsigned int ip_dst;
    }; 
    
    
    
    
    
    struct tcphdr {
     unsigned short int th_sport;
     unsigned short int th_dport;
     unsigned int th_seq;
     unsigned int th_ack;
     unsigned char th_x2:4, th_off:4;
     unsigned char th_flags;
     unsigned short int th_win;
     unsigned short int th_sum;
     unsigned short int th_urp;
    }; /* total tcp header length: 20 bytes (=160 bits) */
    
    
    
    
    int 
    main (void)
    {
      int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);	/* open raw socket */
      char datagram[4096];	/* this buffer will contain ip header, tcp header,
    			   and payload. we'll point an ip header structure
    			   at its beginning, and a tcp header structure after
    			   that to write the header values into it */
      struct ip *iph = (struct ip *) datagram;
      struct tcphdr *tcph = (struct tcphdr *) datagram + sizeof (struct ip);
      struct sockaddr_in sin;
    			/* the sockaddr_in containing the dest. address is used
    			   in sendto() to determine the datagrams path */
    
      sin.sin_family = AF_INET;
      sin.sin_port = htons (P);/* you byte-order >1byte header values to network
    			      byte order (not needed on big endian machines) */
      sin.sin_addr.s_addr = inet_addr ("1.1.1.1");
    
      memset (datagram, 0, 4096);	/* zero out the buffer */
    
    /* we'll now fill in the ip/tcp header values, see above for explanations */
      iph->ip_hl = 5;
      iph->ip_v = 4;
      iph->ip_tos = 0;
      iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr);	/* no payload */
      iph->ip_id = htonl (54321);	/* the value doesn't matter here */
      iph->ip_off = 0;
      iph->ip_ttl = 255;
      iph->ip_p = 6;
      iph->ip_sum = 0;		/* set it to 0 before computing the actual checksum later */
      iph->ip_src = inet_addr ("1.2.3.4");/* SYN's can be blindly spoofed */
      iph->ip_dst = sin.sin_addr.s_addr;
      tcph->th_sport = htons (1234);	/* arbitrary port */
      tcph->th_dport = htons (P);
      tcph->th_seq = 3;/* in a SYN packet, the sequence is a random */
      tcph->th_ack = 0;/* number, and the ack sequence is 0 in the 1st packet */
      tcph->th_x2 = 0;
      tcph->th_off = 0;		/* first and only tcp segment */
      tcph->th_flags = 0;	/* initial connection request */
      tcph->th_win = htonl (65535);	/* maximum allowed window size */
      tcph->th_sum = 0;/* if you set a checksum to zero, your kernel's IP stack
    		      should fill in the correct checksum during transmission */
      tcph->th_urp = 0;
    
      iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1);
    
    /* finally, it is very advisable to do a IP_HDRINCL call, to make sure
       that the kernel knows the header is included in the data, and doesn't
       insert its own header into the packet before our data */
    
      {				/* lets do it the ugly way.. */
        int one = 1;
        const int *val = &one;
        if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, "1", sizeof ("1")) < 0)
          printf ("Warning: Cannot set HDRINCL!\n");
      }
    
      while (1)
        {
          if (sendto (s,		/* our socket */
    		  datagram,	/* the buffer containing headers and data */
    		  iph->ip_len,	/* total length of our datagram */
    		  0,		/* routing flags, normally always 0 */
    		  (struct sockaddr *) &sin,	/* socket addr, just like in */
    		  sizeof (sin)) < 0)		/* a normal send() */
    	printf ("error\n");
          else
    	printf (".");
        }
    
      return 0;
    }

  2. #2
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,265
    You need to call WSAStartup() somewhere.

  3. #3
    30 Helens Agree neandrake's Avatar
    Join Date
    Jan 2002
    Posts
    640
    I was under the impression that windows does not allow access to raw sockets -- could someone verify/clarify?
    Environment: OS X, GCC / G++
    Codes: Java, C#, C/C++
    AOL IM: neandrake, Email: neandrake (at) gmail (dot) com

  4. #4
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,265
    Windows allows the use of Raw sockets. The use can be limited depending on what version of Windows is being used though.

    From MSDN:
    On Windows XP with Service Pack 2 (SP2) and Windows Vista, the ability to send traffic over raw sockets has been restricted in several ways:

    * TCP data cannot be sent over raw sockets.
    * UDP datagrams with an invalid source address cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. This change was made to limit the ability of malicious code to create distributed denial-of-service attacks and limits the ability to send spoofed packets (TCP/IP packets with a forged source IP address).
    * A call to the bind function with a raw socket is not allowed.

    These above restrictions do not apply to Windows Server 2003 and Windows Server 2008 or to versions of the operating system earlier than Windows XP with SP2.

  5. #5
    Registered User
    Join Date
    Sep 2008
    Posts
    48
    i'm pretty sure i managed to send packets with modified header using scapy on windows xp sp3

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Linux raw socket programming
    By cnb in forum Networking/Device Communication
    Replies: 17
    Last Post: 11-08-2010, 08:56 AM
  2. socket programming question, closing sockets...
    By ursula in forum Networking/Device Communication
    Replies: 2
    Last Post: 05-31-2009, 06:17 PM
  3. Raw socket and sendto()
    By matB in forum Networking/Device Communication
    Replies: 4
    Last Post: 07-10-2008, 06:07 PM
  4. when to close a socket
    By Wisefool in forum Networking/Device Communication
    Replies: 5
    Last Post: 11-02-2003, 10:33 AM
  5. socket newbie, losing a few chars from server to client
    By registering in forum Linux Programming
    Replies: 2
    Last Post: 06-07-2003, 12:48 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21