Code raw sockets in C on Linux
Kamis, 27 Juni 2013
0
komentar
http://www.binarytides.com/raw-sockets-c-code-linux
But there are other cases when an application needs to set its own headers. Raw sockets are used in security related applications like nmap , packets sniffer etc. In this article we are going to program raw sockets on linux using native sockets. Windows for example does not support raw socket programming directly. To program raw sockets on windows a packet crafting library like winpcap has to be used.
In this article we are going to do some raw socket programming by constructing a raw TCP packet and sending it over the network. Before programming raw sockets, it is recommended that you learn about the basics of socket programming in c.
 
Packet = IP Header + TCP Header + Data
The plus means to attach the binary data side by side. So when making a raw tcp packet we need to know how to construct the headers properly. The structures of all headers are established standards which are described in RFCs.
 
 
The "Source Address" field stores the ip address of the system  sending the packet and the "Destination Address" contains the ip address  of the destination system. Ip addresses are stored in long number  format. The "Protocol" field stores a number that indicates the  protocol, which is TCP in this case. 
 
 
So we need to construct the headers according to the formats specified above.
 
 
The above function call creates a raw socket of protocol TCP. This  means that we have to provide the TCP header along with the data. The  kernel or the network stack of Linux shall provide the IP header.
If we want to provide the IP header as well then there are 2 ways of doing this
1. Use protocol IPPROTO_RAW - This will allow to specify the IP header and everything that is contained in the packet.
 
2. Set the IP_HDRINCL socket option to 1 - This is same as the above. Just another way of doing.
 
When using the IP_HDRINCL the protocol used in the socket function is effectively of no use.
 
 
Use a packet sniffer like wireshark to check the output and verify that the packets have actually been generated and send over the network. Also note that if some kind of firewall like firestarter is running then it might block raw packets.
 
Raw tcp sockets in C
Raw sockets can be used to construct a packet manually inside an application. In normal sockets when any data is send over the network, the kernel of the operating system adds some headers to it like IP header and TCP header. So an application only needs to take care of what data it is sending and what reply it is expecting.But there are other cases when an application needs to set its own headers. Raw sockets are used in security related applications like nmap , packets sniffer etc. In this article we are going to program raw sockets on linux using native sockets. Windows for example does not support raw socket programming directly. To program raw sockets on windows a packet crafting library like winpcap has to be used.
In this article we are going to do some raw socket programming by constructing a raw TCP packet and sending it over the network. Before programming raw sockets, it is recommended that you learn about the basics of socket programming in c.
Raw TCP packets
A TCP packet is constructed like thisPacket = IP Header + TCP Header + Data
The plus means to attach the binary data side by side. So when making a raw tcp packet we need to know how to construct the headers properly. The structures of all headers are established standards which are described in RFCs.
Ip header
The structure of IP Header as given by RFC 791| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Version|  IHL  |Type of Service|          Total Length         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|         Identification        |Flags|      Fragment Offset    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|  Time to Live |    Protocol   |         Header Checksum       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                       Source Address                          |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    Destination Address                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    Options                    |    Padding    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
Structure of tcp header
The structure of a TCP header as given by RFC 793| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|          Source Port          |       Destination Port        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                        Sequence Number                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    Acknowledgment Number                      |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|  Data |           |U|A|P|R|S|F|                               || Offset| Reserved  |R|C|S|S|Y|I|            Window             ||       |           |G|K|H|T|N|N|                               |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|           Checksum            |         Urgent Pointer        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    Options                    |    Padding    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                             data                              |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
Raw tcp sockets
Create a raw socket like this| 1 | ints = socket (AF_INET, SOCK_RAW, IPPROTO_TCP); | 
If we want to provide the IP header as well then there are 2 ways of doing this
1. Use protocol IPPROTO_RAW - This will allow to specify the IP header and everything that is contained in the packet.
| 1 | ints = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); | 
| 1 2 3 4 5 6 7 8 9 | ints = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);intone = 1;constint*val = &one;if(setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0){    printf("Error setting IP_HDRINCL. Error number : %d . Error message : %s \n", errno, strerror(errno));    exit(0);} | 
In this example we are creating raw sockets  where we specify the Ip header and TCP header. The packet that moves out  of the machine actually has 1 more header attached to it called the  Ethernet header. So the actual packet structure is somewhat like this.
Packet = Ethernet header + Ip header + TCP header + Data
Take a look at the packets sniffed by wireshark to understand this better. It is important to note here that the Ethernet header is provided by the OS kernel and we do not have to construct it. However it is possible to make such raw packets where we can even specify the ethernet header, but we shall look into those in a separate article.
Below is an example code which constructs a raw TCP packet with some dataPacket = Ethernet header + Ip header + TCP header + Data
Take a look at the packets sniffed by wireshark to understand this better. It is important to note here that the Ethernet header is provided by the OS kernel and we do not have to construct it. However it is possible to make such raw packets where we can even specify the ethernet header, but we shall look into those in a separate article.
Final Code
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | /*    Raw TCP packets    Silver Moon (m00n.silv3r@gmail.com)*/#include#include#include#include#include#include#include/*     96 bit (12 bytes) pseudo header needed for tcp header checksum calculation */structpseudo_header{    u_int32_t source_address;    u_int32_t dest_address;    u_int8_t placeholder;    u_int8_t protocol;    u_int16_t tcp_length;};/*    Generic checksum calculation function*/unsigned shortcsum(unsigned short*ptr,intnbytes) {    registerlongsum;    unsigned shortoddbyte;    registershortanswer;    sum=0;    while(nbytes>1) {        sum+=*ptr++;        nbytes-=2;    }    if(nbytes==1) {        oddbyte=0;        *((u_char*)&oddbyte)=*(u_char*)ptr;        sum+=oddbyte;    }    sum = (sum>>16)+(sum & 0xffff);    sum = sum + (sum>>16);    answer=(short)~sum;        return(answer);}intmain (void){    //Create a raw socket    ints = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);        if(s == -1)    {        //socket creation failed, may be because of non-root privileges        perror("Failed to create socket");        exit(1);    }        //Datagram to represent the packet    chardatagram[4096] , source_ip[32] , *data , *pseudogram;        //zero out the packet buffer    memset(datagram, 0, 4096);        //IP header    structiphdr *iph = (structiphdr *) datagram;        //TCP header    structtcphdr *tcph = (structtcphdr *) (datagram + sizeof(structip));    structsockaddr_in sin;    structpseudo_header psh;        //Data part    data = datagram + sizeof(structiphdr) + sizeof(structtcphdr);    strcpy(data , "ABCDEFGHIJKLMNOPQRSTUVWXYZ");        //some address resolution    strcpy(source_ip , "192.168.1.2");    sin.sin_family = AF_INET;    sin.sin_port = htons(80);    sin.sin_addr.s_addr = inet_addr ("1.2.3.4");        //Fill in the IP Header    iph->ihl = 5;    iph->version = 4;    iph->tos = 0;    iph->tot_len = sizeof(structiphdr) + sizeof(structtcphdr) + strlen(data);    iph->id = htonl (54321); //Id of this packet    iph->frag_off = 0;    iph->ttl = 255;    iph->protocol = IPPROTO_TCP;    iph->check = 0;      //Set to 0 before calculating checksum    iph->saddr = inet_addr ( source_ip );    //Spoof the source ip address    iph->daddr = sin.sin_addr.s_addr;        //Ip checksum    iph->check = csum ((unsigned short*) datagram, iph->tot_len);        //TCP Header    tcph->source = htons (1234);    tcph->dest = htons (80);    tcph->seq = 0;    tcph->ack_seq = 0;    tcph->doff = 5;  //tcp header size    tcph->fin=0;    tcph->syn=1;    tcph->rst=0;    tcph->psh=0;    tcph->ack=0;    tcph->urg=0;    tcph->window = htons (5840); /* maximum allowed window size */    tcph->check = 0; //leave checksum 0 now, filled later by pseudo header    tcph->urg_ptr = 0;        //Now the TCP checksum    psh.source_address = inet_addr( source_ip );    psh.dest_address = sin.sin_addr.s_addr;    psh.placeholder = 0;    psh.protocol = IPPROTO_TCP;    psh.tcp_length = htons(sizeof(structtcphdr) + strlen(data) );        intpsize = sizeof(structpseudo_header) + sizeof(structtcphdr) + strlen(data);    pseudogram = malloc(psize);        memcpy(pseudogram , (char*) &psh , sizeof(structpseudo_header));    memcpy(pseudogram + sizeof(structpseudo_header) , tcph , sizeof(structtcphdr) + strlen(data));        tcph->check = csum( (unsigned short*) pseudogram , psize);        //IP_HDRINCL to tell the kernel that headers are included in the packet    intone = 1;    constint*val = &one;        if(setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)    {        perror("Error setting IP_HDRINCL");        exit(0);    }        //loop if you want to flood :)    while(1)    {        //Send the packet        if(sendto (s, datagram, iph->tot_len ,  0, (structsockaddr *) &sin, sizeof(sin)) < 0)        {            perror("sendto failed");        }        //Data send successfully        else        {            printf("Packet Send. Length : %d \n", iph->tot_len);        }    }        return0;}//Complete | 
Compile and Run
Compile by program by doing a gcc raw_socket.c at the terminal. Remember to run the program with root privileges. Raw sockets require root privileges. Note the while loop in the above program. It has been put for testing purpose and should be removed if you dont intend to flood the target.Use a packet sniffer like wireshark to check the output and verify that the packets have actually been generated and send over the network. Also note that if some kind of firewall like firestarter is running then it might block raw packets.
Resources
http://linux.die.net/man/7/rawTERIMA KASIH ATAS KUNJUNGAN SAUDARA
Judul: Code raw sockets in C on Linux
Ditulis oleh Unknown
Rating Blog 5 dari 5
Semoga artikel ini bermanfaat bagi saudara. Jika ingin mengutip, baik itu sebagian atau keseluruhan dari isi artikel ini harap menyertakan link dofollow ke https://androidblackberries.blogspot.com/2013/06/code-raw-sockets-in-c-on-linux.html. Terima kasih sudah singgah membaca artikel ini.Ditulis oleh Unknown
Rating Blog 5 dari 5
 
0 komentar:
Posting Komentar