Raw socket and a three-way handshake issue

What's the best way to setup a home network? Why should I care about BGP?

Raw socket and a three-way handshake issue

Post by Borza on Mon Jan 17, 2011 6:02 am
([msg=52286]see Raw socket and a three-way handshake issue[/msg])

Hi, I'm a new user, first time posting... ;) (Well second time, originally posted this as a response to an old thread and it got sacked to Graveyard, got a warning with it too).
(Sorry Goatboy, I thought it was more convenient to post it as a follow-up... I guess not).


Well, to cut the long story short, I have a seminar in Computer security comming up. I'm writing a raw socket to establish the three-way handshake. I found an example of the code and decided to adjust it for my needs. After some tweaks (IP spoofing) I was able to send the SYN packet to my server. My problem is that I can't, however, seem to get a SYN/ACK response from it.

A bit about the environment:
The socket program runs on a Ubuntu 10.04 in a virtual machine (in Virtualbox) and the server is Apache on WinXP, also in a virtual machine. They are networked internally and I hosted a small website on the server which I am able to access from a browser (three-way handshake succesful).

I have compared the packets info in Wireshark. My SYN packet is not much different from the one Firefox uses. The main difference is that mine doesn't have SACK permitted option enabled. Should this matter?

The code:
You'll notice weird comments mostly in Croatian, it's my native language so don't get frightened or anything :lol:
Wasn't exactly sure about all the includes needed, so there are probably a few extras unnecessary.

Code: Select all
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<sys/socket.h>
#include<linux/if_packet.h>
#include<linux/if_ether.h>
#include<errno.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<net/if.h>
#include<net/ethernet.h>
#include<unistd.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<features.h>
#define __FAVOR_BSD
#include<netinet/tcp.h>



#define P 80        /* Port koji cemo preplaviti */

unsigned short chksum (unsigned short *buff, int nwords)            /* Funkcija za generiranje cheksume */
{
    unsigned long sum;
    for (sum=0; nwords > 0; nwords--)
        sum += *buff++;
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
}


int randint (int max)                /* Generira pseudonasumican broj izmedju 0 i max */
{
    return (max*rand()/(RAND_MAX+1.0));
}

void spoof (char* adresa)
{
    int prvi, drugi, treci, cetvrti;
    char a[5], b[5], c[5], d[5];

    //srandom (time(0));
   
    prvi = rand() % 255 + 1;
        if (prvi==127 || prvi ==255 || prvi == 10 || prvi ==192)    prvi =126;    //localhost i broadcast...
    drugi = rand() % 255 + 1;
    treci = rand() % 255 + 1;
    cetvrti = rand() % 254 + 1;        /* Generirali smo nasumicne vrijednosti do 255 */

    /******** Sada ih pretvaramo u stringove koje cemo poslije konkatenirati *********/

    sprintf(a, "%i", prvi);   
    sprintf(b, "%i", drugi);
    sprintf(c, "%i", treci);
    sprintf(d, "%i", cetvrti);

    /********* Konkatenacija **********/

    strcpy (adresa, a);   
    strcat (adresa, ".");                       
    strcpy (adresa, b);   
    strcat (adresa, ".");
    strcat (adresa, c);
    strcat (adresa, ".");
    strcat (adresa, d);       
}

int main (void)
{
    int rawsock;
    rawsock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);   // stvori novi raw socket
    char paket [4096];                 // ovo je spremnik koji ce postat paket, dakle u njega spremam IP i TCP header te neke dodatne podatke

                                       // potrebno je jos napraviti pointere koji ce pokazivati na pocetak pojedinih zaglavlja (u nastavku)
    struct ip *iph = (struct ip*) paket;
    struct tcphdr *tcph = (struct tcphdr *)(paket + sizeof (struct ip));

    struct sockaddr_in sin;

    sin.sin_family = AF_INET;
    sin.sin_port = htons (P);                            // prevest port sa little na big endian
    sin.sin_addr.s_addr = inet_addr ("192.168.56.11");       // postavit odredisnu adresu adresu na lokalno racunalo (localhost)
    memset (paket, 0, 4096);                               // postavit buffer u nule
   

    /*************** Postavljanje vrijednosti IP headera  ***************/

    iph->ip_hl = 5;                                     /* velieina zaglavlja u bajtovima je jednaka ip_hl * 4 */
    iph->ip_v = 4;                                    /* verzija protokola koji koristimo za prijenos, ovdje IPv4 */
    iph->ip_tos = 0;                                        /* Type of Service - odnosi se na prioritet paketa, 0 je defaultna vrijednost */
    iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr);            /* Ukupna duljina PDU-a zaglavljem, bez podataka */
    iph->ip_id = htonl(1950);                                /* Nije bitno, samo ako je PDU fragmentiran */
    iph->ip_off = 0;                                    /* Offset, bitno samo kod fragmentiranih PDU-ova */
    iph->ip_ttl = 255;                                    /* Broj skokova koje može "preživjeti" */
    iph->ip_p = 6;                                    /* Oznaeava protokol prijenosne razine, 6 za TCP */
    iph->ip_sum = 0;                                    /* Poeetna checksum, stvarna ae se raeunati poslije */


    /*************** Postavljanje vrijednosti TCP headera  ***************/

    tcph->th_sport = htons(10425);        /* Proizvoljni izvorisni port */
    tcph->th_dport = htons (P);            /* Odredisni port, gore je u DEFINE */
    tcph->th_seq = random();            /* Poeetni broj sekvence, kod SYN paketa je nasumiean */
    tcph->th_ack = 0;                 /* Kod prvog paketa ACK je 0 */
    //tcph->th_x2 = 0;    /* Zastarjelo ?!?*/            /* BZVZ */
    tcph->th_off = 5;                /* Prvi i jedini TCP header, zato je offset nula */
    tcph->th_flags = TH_SYN;            /* Postavili smo zastavice tako da klijent dâ do znanja da želi uspostavti novu konekciju s odr. portom */
    tcph->th_win = htons(5840);         /* TCP prozor; stavimo MAX broj bajtova koje možemo poslati prije dobivanja ACK da bi mogli opet slati */
    tcph->th_sum = 0;                /* Kada je cheksum nula, OS prilikom prijenosa unese tocnu vrijednost */
    tcph->th_urp = 0;                /* Urgent zastavica, nebitno */
   

    iph->ip_sum = chksum ((unsigned short *) paket, iph->ip_len >> 1);


    /********************* Poziv IP_HDRINCL ************************/
    /******** Kako bi kernel znao da je header vec ukljucen ********/


    {
       int one = 1;
        const int *val = &one;
    if (setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
              printf ("Warning: Cannot set HDRINCL!\n");
      }
    int two = 2;
        const int *lala = &two;

    if (setsockopt (rawsock, IPPROTO_TCP, TCPOPT_SACK_PERMITTED, lala, sizeof (two)))
        printf ("Nece!\n");
   
    srand (time(0));
    float paketBr=0;   
    int i=1;

      while (i!=0)
        {
                /******* Spoof ***********/

        char spoofAddr[16];       
        spoof(spoofAddr);       
        // printf("Adresa: %s", spoofAddr);
       
        iph->ip_src.s_addr = inet_addr (spoofAddr);                    /* Adresa posiljatelja; OVO CE SE SPOOFAT */
        iph->ip_dst.s_addr = sin.sin_addr.s_addr;                     /* Vec je gori postavljena vrijednost */ 


              if (sendto (    rawsock,            /* nas socket */
                paket,           
                  iph->ip_len,            /* ukupna duzina paketa */
                  0,                   /* zastavice za routanje */
                  (struct sockaddr *) &sin,   
                  sizeof (sin)) < 0)        /* a normal send() */
                                   
                {     
                    printf ("error\n");
                    break;
                }
                   
               
             else
            {
            paketBr++;
            printf ("OK! Sent from: %s  -----  Package number %f \n", spoofAddr, paketBr);
            }
        i--;
        }

  return 0;
}


And the original code:
http://mixter.void.ru/rawip.html

Please help!
Thanks
Borza
New User
New User
 
Posts: 6
Joined: Sun Jan 16, 2011 2:56 pm
Blog: View Blog (0)


Re: Raw socket and a three-way handshake issue

Post by neuromanta on Mon Jan 17, 2011 7:01 am
([msg=52289]see Re: Raw socket and a three-way handshake issue[/msg])

Did you check if raw IP packet sending is allowed by the OS? Some systems don't allow that, but I don't know what is the case with Ubuntu 10.4. Does the other system (WinXP) gets the packet? You should backtrace the problem (I don't know how, I didn't do anything like this in a real environment before (only with Omnet++), sorry).
User avatar
neuromanta
Poster
Poster
 
Posts: 302
Joined: Mon Nov 30, 2009 9:29 am
Location: Hungary
Blog: View Blog (0)


Re: Raw socket and a three-way handshake issue

Post by Borza on Mon Jan 17, 2011 2:46 pm
([msg=52317]see Re: Raw socket and a three-way handshake issue[/msg])

Hey thanks for the input!

Yeah, well, the reason I wrote the program in a Linux environment is that it allows raw packet sending (you just have to be root).
I guess I'll have to backtrace and find out if the OS IS actually getting the packets and, maybe, dropping them. Tried googling how to do it, but so far Google mocks me with bad search results. :D

Surely someone here wrote a similar program once?
Could it be the fact that I'm using a raw socket on the Ubuntu side and a "regular" socket on the server side? It shouldn't mater?
Borza
New User
New User
 
Posts: 6
Joined: Sun Jan 16, 2011 2:56 pm
Blog: View Blog (0)


Re: Raw socket and a three-way handshake issue

Post by Reason7194 on Tue Jan 18, 2011 2:52 am
([msg=52356]see Re: Raw socket and a three-way handshake issue[/msg])

I am actully just learning about sockets. It would be great if you could point me in the direction where you started to learn about them. Right now i am going off what Oracle is telling me about. + i would rather get into some hand-on experiments with sockets, so ideas please^_^
I study Gotafu.
Reason7194
Poster
Poster
 
Posts: 215
Joined: Fri Jan 07, 2011 5:01 pm
Blog: View Blog (0)


Re: Raw socket and a three-way handshake issue

Post by neuromanta on Tue Jan 18, 2011 5:31 am
([msg=52360]see Re: Raw socket and a three-way handshake issue[/msg])

As I said I'm not an expert, but your problem gave me the incentive to read up on the subject. The code looks okay (but again, I never did anything like this myself, just compared it to other implementations), and it shouldn't be a problem that you make a raw socket on one side, and use the standard socket API on the other. The API makes and parses sockets the same way you did, it just implements helper functions to ease your work.
I think you should use a sniffer program to look at the actual byte stream, what goes out on linux side, and what comes in on winxp side. If the two are identical, then the problem is with WinXP.
User avatar
neuromanta
Poster
Poster
 
Posts: 302
Joined: Mon Nov 30, 2009 9:29 am
Location: Hungary
Blog: View Blog (0)


Re: Raw socket and a three-way handshake issue

Post by insomaniacal on Tue Jan 18, 2011 7:16 am
([msg=52364]see Re: Raw socket and a three-way handshake issue[/msg])

You said you didn't get any SYN/ACK response. Where were you looking for it? I know this sounds kinda rudimentary, but the response would be sent to whatever the spoofed IP address is.

Sniffers on both ends are a good starting point, especially from the machine that's supposed to be sending the response.
It's not who votes that counts, it's who counts the votes
insomaniacal.blog.com
User avatar
insomaniacal
Addict
Addict
 
Posts: 1210
Joined: Sun May 24, 2009 10:21 am
Blog: View Blog (0)


Re: Raw socket and a three-way handshake issue

Post by Borza on Tue Jan 18, 2011 8:13 am
([msg=52369]see Re: Raw socket and a three-way handshake issue[/msg])

insomaniacal wrote:You said you didn't get any SYN/ACK response. Where were you looking for it? I know this sounds kinda rudimentary, but the response would be sent to whatever the spoofed IP address is.

Sniffers on both ends are a good starting point, especially from the machine that's supposed to be sending the response.


It's my understanding that sniffing... sniffs ( :) ) the very interface which the packets go through, so I should see all the packets, regardless of the IP. Theoretically, sniffers on both ends should show the same packages because they're sniffing the same interface (and they do show it).

That being said, I didn't leave anything to chance so I've installed Wireshark on both machines. None have shown my beloved SYN/ACK package.

Maybe I should let it loose from a controlled environment and try it on a live web page on the net? :twisted:

-- Tue Jan 18, 2011 10:57 am --

Reason7194 wrote:I am actully just learning about sockets. It would be great if you could point me in the direction where you started to learn about them. Right now i am going off what Oracle is telling me about. + i would rather get into some hand-on experiments with sockets, so ideas please^_^


Well I've only had a couple of introductory lectures in college regarding what they do, binding to a port, what happens when a socket is listening, the basic structures used in the code, functions for sending and receiving, etc.

We also wrote two simple sockets for sending and receiving data, they were standard sockets, not raw, but nevertheless...
I would send you some presentations, but they're not in English unfortunately.
I guess some solid understanding of the network levels concept, packet switching and that kind of stuff would be a good foundation for learning (If you don't have it already).
I'll see if I can dig up some resources and post it.

Thing is, I haven't had any experience with setting up a server beforehand, so this is all a kind of uncharted territory for me. I've got obstacles at every corner it seems. :roll:
Borza
New User
New User
 
Posts: 6
Joined: Sun Jan 16, 2011 2:56 pm
Blog: View Blog (0)


Re: Raw socket and a three-way handshake issue

Post by Reason7194 on Wed Jan 19, 2011 9:17 am
([msg=52428]see Re: Raw socket and a three-way handshake issue[/msg])

Well that would be helpful, thank you. Right now i am learning the steps with java to set up a socket with another machine on my network. Instead just copy and pasting then editing what i need..i am trying to figure out what is going on between the two machines.
I study Gotafu.
Reason7194
Poster
Poster
 
Posts: 215
Joined: Fri Jan 07, 2011 5:01 pm
Blog: View Blog (0)


Re: Raw socket and a three-way handshake issue

Post by Borza on Thu Jan 20, 2011 6:54 pm
([msg=52542]see Re: Raw socket and a three-way handshake issue[/msg])

Also, it would be a grave mistake not to mention the most awesome and comprehensive "Beej's guide to Network Programming Using Internet Sockets":

http://beej.us/guide/bgnet/output/html/ ... index.html

Have fun!

As for my program, I've found that the OS won't calculate the proper TCP checksum for me if I set the checksum field to zero. Wireshark didn't object as the checksum was "offloaded". I guess the server on the receiving end just dropped them due to incorrect checksum . Had to insert a function for calculating it and it works now.
Hooray!
Borza
New User
New User
 
Posts: 6
Joined: Sun Jan 16, 2011 2:56 pm
Blog: View Blog (0)



Return to Networking

Who is online

Users browsing this forum: No registered users and 0 guests