Raw sockets - C++

Bad threads go here

Raw sockets - C++

Post by Orion001 on Sun Jan 18, 2009 4:05 am
([msg=16488]see Raw sockets - C++[/msg])

Hey guys, I dont know if this should be in the Programming Forum but here goes..

Ive created some socket programs in c++ before and used beej's guide, and I have decided to advance towards raw sockets. Im trying to work through this tutorial: http://mixter.void.ru/rawip.html but so far, I have been unsuccessfull.
I understand the theory behind this fairly well, although I have some questions:
1. can some one please post working source code for a raw socket client (& server) or tell me what is wrong with the code at http://mixter.void.ru/rawip.html? my code so far (copied and pasted from the tutorial, except for the libraries):
Code: Select all
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <iostream>
#define Port 25


using namespace std;

int main ( void )
{
   cout << "hello world\n";


   //create socket:
   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 */


   return 0;
}

compile errors (g++):
Code: Select all
sourcefile.cpp: In function ‘int main()’:
sourcefile.cpp:30: error: invalid application of ‘sizeof’ to incomplete type ‘ip’
sourcefile.cpp:30: error: invalid use of incomplete type ‘struct tcphdr’
sourcefile.cpp:30: error: forward declaration of ‘struct tcphdr’


2. With a raw socket server, how would one listen() and read the packet being recved (to verify which IP it came from etc)? also, how do you fill out the ip header and tcp header structures (from an incoming packet)?

3. How do you find the MAC address of the sender of a packet without using arp tables? because the Physical Layer is above the TCP/IP layer, which means when the kernel gives the packet to my program, it will not have the source and destination MAC addresses correct?

Also, if anyone has found a better tutorial for raw sockets, I would appreciate a link :) I have searched google a lot, and read about raw sockets and tutorials for it. Better yet, would anyone like to write a mini-tutorial for me? Im not expecting that, but it would be great.

Thanks for any help given!

PS. I run Fedora 10, not particularly familiar on the linux OS yet.
Orion001
New User
New User
 
Posts: 36
Joined: Tue Sep 09, 2008 5:44 am
Blog: View Blog (0)


Re: Raw sockets - C++

Post by 193zaitsev on Sun Jan 18, 2009 3:35 pm
([msg=16513]see Re: Raw sockets - C++[/msg])

1.
Your code is only missing two headers (defining struct ip and struct tcphdr)
#include <netinet/ip.h>
#include <netinet/tcp.h>
Check these files in your /usr/include/netinet if your interested in the structures of the packet headers.
When I was first learning some raw socket programming, I used this webpage.
http://www.tenouk.com/Module43a.html
The explanations are not elaborate but if you have read Beej, you should be able to follow the code. He shows creating a raw UDP and TCP socket including creating and filling in the header structs. You can fill in the structures with whatever information depending on the type packet you want to send.
Additional links:
http://en.wikipedia.org/wiki/Ip_(struct)
http://en.wikipedia.org/wiki/Tcphdr

2.
I have no idea how binding a raw socket would work or if it's possible. When you have an incoming packet, you do not know if it originated from a raw socket or regular socket. (i.e. an incoming udp packet could be from a SOCK_DGRAM or raw socket, but you wont know). When testing things myself, I've always known what was coming (i.e. my raw socket client was sending raw socket tcp so my server would listen on a tcp socket, etc...) Someone else will have to help or you could try some stuff or search more.

3.
I can't help here. Checking arp tables is only way I know (# arp -a). The only MAC addresses you will know will be ones of hosts connected directly to you (if connected to a switch, then probably the only MAC address you will know). All outside packets will seem to originate from the switch from the MAC point of view. I'm not quite sure what use the MAC would be to you though unless your connected to the host (check arp table).

I am no professional on this subject so it's possible I am incorrect on some this information. You may want to check other sources.
193zaitsev
New User
New User
 
Posts: 36
Joined: Wed May 21, 2008 10:28 pm
Location: USA
Blog: View Blog (0)


Re: Raw sockets - C++

Post by Orion001 on Sun Jan 18, 2009 6:59 pm
([msg=16538]see Re: Raw sockets - C++[/msg])

Thanks :) Id already seen the tenouk site, it was pretty good. Thanks for the help regarding the include files :) i just included the files shown in Module43b from the tenouk site you had shown.
Ill look those files up, have a squiz at them.
Im not sure what the difference is between a router/switch/gateway (the definitions i find are hard to understand), but I am connected to a router, which sounds like it could do what you say, ill check my arp tables..

so you made a socket stream server, with a raw socket client?

scenario: client sends out a tcp packet (raw), and a tcp server waits for a packet, If the incoming packet sent from the client is a SYN packet, respond with a SYN/ACK packet etc.
So I want to handle any connections manually. I shouldnt need to worry about a udp connections as my server is tcp (i dont mind if the server would break if it got a udp packet)

-edit-
yeh, when I check my arp tables (using arp -a like you said) I only get 1 entry:
Code: Select all
my.router (192.168.2.1) at 00:11:22:33:44:55 [ether] on eth1

of course, thats not the MAC that it says, i just edited it

-- Mon Jan 19, 2009 10:22 pm --

So in basic terms, how do you..
1. Find out what packet a box sent you (a SYN/ACK packet for egsample)
2. Find out what the MAC address is of a remote box, when Im behind a router (arp -a returns only 1 MAC address.)

help is appreciated :D
Orion001
New User
New User
 
Posts: 36
Joined: Tue Sep 09, 2008 5:44 am
Blog: View Blog (0)


Re: Raw sockets - C++

Post by 193zaitsev on Mon Jan 19, 2009 1:30 pm
([msg=16596]see Re: Raw sockets - C++[/msg])

1. Find out what packet a box sent you (a SYN/ACK packet for egsample)


libpcap might be what you're looking for. It allows sniffing out packets including all their headers. I've never used it before so I'm not positive, but it looks useful. I'll probably check it out some when I get a little free time.

http://yuba.stanford.edu/~casado/pcap/section1.html
This tutorial may be useful to capture the packets, read the headers, then you could send out whatever packet on a raw socket to have essential communication between two raw sockets. There is possibly a better way though, someone else may have better info.
193zaitsev
New User
New User
 
Posts: 36
Joined: Wed May 21, 2008 10:28 pm
Location: USA
Blog: View Blog (0)


Re: Raw sockets - C++

Post by Orion001 on Mon Jan 19, 2009 5:54 pm
([msg=16615]see Re: Raw sockets - C++[/msg])

I see, I had a read of that tutorial, although I dont want to use 3rd party programs to get the returning packet. Id like to learn how it works, rather than just get another program to do it for me (unless its beyond my capability).

..maybe ill have a look at nmap's source code, I hope ill understand it. :S

--edit--
hmm, looks like you need kernal support + root/admin privileges to capture packets, so I guess Ill use libpcap.

-- Tue Jan 20, 2009 11:26 am --

I just found out how to make a server/sniffer using c++ raw sockets. code is here:http://security-freak.net/raw-sockets/sniffer.c
tutorial is here: http://security-freak.net/raw-sockets/raw-sockets.html
For anyone that is interested.
Orion001
New User
New User
 
Posts: 36
Joined: Tue Sep 09, 2008 5:44 am
Blog: View Blog (0)


Re: Raw sockets - C++

Post by 193zaitsev on Tue Jan 20, 2009 10:59 pm
([msg=16698]see Re: Raw sockets - C++[/msg])

Ah, I see you found some stuff. Thanks for the posts. I found a few things as well.

I cut up some of a sniffer I found as well.
src: http://packetstormsecurity.org/sniffers ... uction.txt
(Also provides a "tutorial" for the short code; code is for sniffing TCP though easily changed by modifying IPPROTO_TCP)
I know there's an IPPROTO_IP and IPPROTO_RAW, though I couldn't figure out how they were used correctly. I might check out that ETH_P_IP that your link has, it looks interesting.

Code: Select all
#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>

struct ip {
  unsigned int        ip_length:4;         /* length of ip-header in 32-bit
                                                 words*/
  unsigned int        ip_version:4;        /* set to "4", for Ipv4 */
  unsigned char       ip_tos;              /* type of service*/
  unsigned short      ip_total_length;     /* Total length of ip datagram in
                                                  bytes */
  unsigned short      ip_id;               /*identification field*/
  unsigned short      ip_flags;
  unsigned char       ip_ttl;              /*time-to-live, sets upper limit
                                                   for max number of routers to
                                                   go through before the packet is
                                                   discarded*/
 
  unsigned char       ip_protocol;         /*identifies the correct transport
                                                    protocol */
  unsigned short      ip_cksum;            /*calculated for the ip header ONLY*/
  unsigned int        ip_source;           /*source ip */
  unsigned int        ip_dest;             /*dest ip*/
};

struct tcp {
  unsigned short     tcp_source_port; /*tcp source port*/
  unsigned short     tcp_dest_port;   /*tcp dest port*/
  unsigned int       tcp_seqno;       /*tcp sequence number,
                                        identifies the byte in the
                                        stream of data*/
  unsigned int       tcp_ackno;       /*contains the next seq num that
                                        the sender expects to recieve*/
  unsigned int       tcp_res1:4,      /*little-endian*/
                     tcp_hlen:4,      /*length of tcp header in 32-bit
                                        words*/
                   tcp_fin:1,       /*Finish flag "fin"*/
                   tcp_syn:1,       /*Synchronize sequence
                                       numbers to start a connection*/
                   tcp_rst:1,       /*Reset flag */
                    tcp_psh:1,       /*Push, sends data to the
                                      application*/
                   tcp_ack:1,       /*acknowledge*/
                    tcp_urg:1,       /*urgent pointer*/
                    cp_res2:2;
  unsigned short     tcp_winsize;     /*maxinum number of bytes able
                                   to recieve*/
  unsigned short     tcp_cksum;       /*checksum to cover the tcp
                                             header and data portion of the
                                             packet*/
 
  unsigned short     tcp_urgent;     /*vaild only if the urgent flag is
                                                    set, used to transmit
                                                    emergency data */
};

int main(){

  char buf[1024];
  int socket_fd;

  socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  if (socket_fd == -1){
    printf("socket()");
    return -1;
  }

  struct sockaddr_in remote;
  socklen_t addr_len = sizeof(struct sockaddr_in);

  int bytes_recv = recvfrom(socket_fd, (void*) buf, (size_t) 1024, 0,
             (struct sockaddr *) &remote,
             (socklen_t *) &addr_len);


  struct ip *ip_header;
  struct tcp *tcp_header;
  ip_header = (struct ip*) buf;
  tcp_header = (struct tcp *)(buf + (4*ip_header->ip_length));

  printf("%d\n", ip_header->ip_version);
  printf("%d\n", ip_header->ip_protocol);
  printf("%d\n", tcp_header->tcp_source_port);

  return 0;
}


Note: it is a quick patchwork job from that link, therefore, it's very rough and some of the stuff (headers) might not be necessary.

The last 3 printf's show how one could access various parts of the headers.


hmm, looks like you need kernal support + root/admin privileges to capture packets

I think root is needed for anything with raw sockets. Not positive on that though
193zaitsev
New User
New User
 
Posts: 36
Joined: Wed May 21, 2008 10:28 pm
Location: USA
Blog: View Blog (0)


Re: Raw sockets - C++

Post by Orion001 on Tue Jan 20, 2009 11:33 pm
([msg=16701]see Re: Raw sockets - C++[/msg])

thanks for the reply,
Ive found several places that Im trying to use to get my testsniffer program working... to no avail.
some links:
http://forums.techpowerup.com/showthread.php?p=820319
http://www.unix.com/high-level-programming/13844-getting-ack-raw-syn-packet.html
http://www.winlab.rutgers.edu/~zhibinwu/html/c_prog.htm
but anyways, my program does this:
1. creates a raw socket
2. bind that socket (port 55000)
3. create another raw socket
4. fill the iphdr and tcphdr structures
5. send that packet
6. wait for 2 secs
7. recv the data

I have posted my code here: http://www.cplusplus.com/forum/general/7109/ (150 lines so I wont post it here)
I dont seam to recv the whole packet, when I go to print out the packet I have just recieved, it prints 'E'. Thats it. Just the letter E. This is very frustrating, and I have no idea how to fix it.
I *believe* that the problem arises here:
Code: Select all
bzero((char *)& sin, sizeof(sin));
   sin.sin_family = AF_INET;
   sin.sin_port = htons(55000);   //port to send packet to
   sin.sin_addr.s_addr = inet_addr("127.0.0.1");   //IP to send packet to


/* Other Code Goes Here*/


char recvPacket[4096] = "";
/* I believe that I am supposed to recvfrom() instead of just using recv()
recv() compiles fine, but only returns "E", where as using recvfrom() does not compile (see below) */
   //int newData = recv(bindSocket,recvPacket,sizeof(recvPacket),0);
   int newData = recvfrom(bindSocket, (void*)recvPacket,sizeof(recvPacket),0,(struct sockaddr *)&sin, sizeof(struct sockaddr_in));
   if (newData <=0)
   {
      cout << newData << " returned by recv! :(\n";
      exit(1);
   }else{
      cout << "<" << newData << "> RECIEVE SUCCESSFULL!!   :-D\n";
      cout << recvPacket << endl;
   }


With this code (using recvfrom instead of just recv), I get the following compile errors:
Code: Select all
testsniffer.cpp: In function ‘int main(int, char**)’:
testsniffer.cpp:141: error: invalid conversion from ‘unsigned int’ to ‘socklen_t*’
testsniffer.cpp:141: error:   initializing argument 6 of ‘ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*)’

(line 141 is the int newData = recvfrom() call)

So does anyone know the *right* way of receiving a packet? (and/or the correct syntax for my recvfrom()?)

Anyways, hope some one figures it out, cause im awfully confused..

-- Wed Jan 21, 2009 2:45 pm --

Also, kinda off-topic, but regarding ARP spoofing, the arp table has a list of IP address : MAC address entries right?

Well, when you spoof, you tell the server that IPclient:MACclient is actually IPclient:MACattacker correct? If so, then wont the packet be sent to the client based off the IP address? and then the client's OS would read the MAC address and discard the packet (because the OS does not accept packets which dont have its MAC address)?

wouldnt it be more sensible to say that IPclient = IPattacker, and MACclient remains unchanged? that way the packet will be routed to attacker (based of its IP) who's OS does not discard it because it is in promiscus mode.

Am I missing something?

Sorry, maybe I should make another thread?
Orion001
New User
New User
 
Posts: 36
Joined: Tue Sep 09, 2008 5:44 am
Blog: View Blog (0)


Re: Raw sockets - C++

Post by 193zaitsev on Sun Jan 25, 2009 2:49 pm
([msg=16990]see Re: Raw sockets - C++[/msg])

Sorry for the delay.

Orion001 wrote:I dont seam to recv the whole packet, when I go to print out the packet I have just recieved, it prints 'E'. Thats it. Just the letter E. This is very frustrating, and I have no idea how to fix it.

Ah, yes, I came across this when I was creating my above short program. You likely are recieving everything. The problem your getting comes from your use of character strings. You'll remember that character strings are ended in a '\0' character which in hex would be 0x00. When your attempting to print out the packet your recieving, your getting the first part of the IP header. The first four bits of the header are the IP version: 0x4 (IPv4). The next 4 bits are the length of the header 0x5 (5 x 32 bits). The next 8 bits are some extra IP options, usually 0x00. So when your printing out the buffer containing the packet. It finds 0x45 which is 'E' in ASCII, then 0x00, the null terminating character.

I casted the packet buffer as structs in my previous post, which is one way to see each possible way. There's probably an outputting function that will force output for a certain number of characters ignoring the null character, though I don't know what it is.
193zaitsev
New User
New User
 
Posts: 36
Joined: Wed May 21, 2008 10:28 pm
Location: USA
Blog: View Blog (0)


Re: Raw sockets - C++

Post by Orion001 on Sat Feb 07, 2009 12:51 am
([msg=17488]see Re: Raw sockets - C++[/msg])

193zaitsev wrote:Sorry for the delay.

Orion001 wrote:I dont seam to recv the whole packet, when I go to print out the packet I have just recieved, it prints 'E'. Thats it. Just the letter E. This is very frustrating, and I have no idea how to fix it.

Ah, yes, I came across this when I was creating my above short program. You likely are recieving everything. The problem your getting comes from your use of character strings. You'll remember that character strings are ended in a '\0' character which in hex would be 0x00. When your attempting to print out the packet your recieving, your getting the first part of the IP header. The first four bits of the header are the IP version: 0x4 (IPv4). The next 4 bits are the length of the header 0x5 (5 x 32 bits). The next 8 bits are some extra IP options, usually 0x00. So when your printing out the buffer containing the packet. It finds 0x45 which is 'E' in ASCII, then 0x00, the null terminating character.

I casted the packet buffer as structs in my previous post, which is one way to see each possible way. There's probably an outputting function that will force output for a certain number of characters ignoring the null character, though I don't know what it is.



Thanks, I re-read your previous post. This fixed the problem :) now I just need to work out nt the data in a human-readable format (eg. the ip source/destination address displays as some wierd 10-ish digit number)
Orion001
New User
New User
 
Posts: 36
Joined: Tue Sep 09, 2008 5:44 am
Blog: View Blog (0)


Re: Raw sockets - C++

Post by 193zaitsev on Mon Feb 09, 2009 3:20 pm
([msg=17573]see Re: Raw sockets - C++[/msg])

Orion001 wrote:Thanks, I re-read your previous post. This fixed the problem :) now I just need to work out nt the data in a human-readable format (eg. the ip source/destination address displays as some wierd 10-ish digit number)


The IP is stored as a binary number so you have to convert it to quartet notation. This can be done with
char *inet_ntoa(struct in_addr in);

i.e.
in your code from your cplusplus.com link, to get the IP in readable format, you could use
myStr = inet_ntoa(sin.sin_addr);

To understand the rest of the data, you can just look at what each field means on the wiki for "IPv4"
193zaitsev
New User
New User
 
Posts: 36
Joined: Wed May 21, 2008 10:28 pm
Location: USA
Blog: View Blog (0)


Next

Return to Graveyard

Who is online

Users browsing this forum: No registered users and 0 guests