现在的位置: 首页 > 综合 > 正文

Advanced TCP/IP – THE RAW SOCKET PROGRAM EXAMPLES Send a raw Ethernet frame in Linux (zz)

2018年05月12日 ⁄ 综合 ⁄ 共 9515字 ⁄ 字号 评论关闭

zz

http://www.tenouk.com/Module43a.html

Also Refer

1 http://csis.bits-pilani.ac.in/faculty/dk_tyagi/Study_stuffs/raw.html

2 Send a raw Ethernet frame in Linux (zz)


This is a continuation from Part IV series,Advanced TCP/IP Programming Tutorial.  Working
program examples if any compiled usinggcc, tested using the public IPs, run onFedora Core 3, with several times
of update, as root or SUID 0.  The Fedora machine used for the testing having the
"No Stack Execute"
disabled and the SELinux set to default configuration.

 

Building and injecting RAW datagrams program examples

[root@bakawali testraw]#
cat rawudp.c

// ----rawudp.c------

// Must be run by root lol! Just datagram, no payload/data

#include <unistd.h>

#include <stdio.h>

#include <sys/socket.h>

#include <netinet/ip.h>

#include <netinet/udp.h>

 

// The packet length

#define PCKT_LEN 8192

 

// Can create separate header file (.h) for all headers' structure

// The IP header's structure

struct ipheader {

 unsigned char      iph_ihl:5, iph_ver:4;

 unsigned char      iph_tos;

 unsigned short int iph_len;

 unsigned short int iph_ident;

 unsigned char      iph_flag;

 unsigned short int iph_offset;

 unsigned char      iph_ttl;

 unsigned char      iph_protocol;

 unsigned short int iph_chksum;

 unsigned int       iph_sourceip;

 unsigned int       iph_destip;

};

 

// UDP header's structure

struct udpheader {

 unsigned short int udph_srcport;

 unsigned short int udph_destport;

 unsigned short int udph_len;

 unsigned short int udph_chksum;

};

// total udp header length: 8 bytes (=64 bits)

 

// Function for checksum calculation. From the RFC,

// the checksum algorithm is:

//  "The checksum field is the 16 bit one's complement of the one's

//  complement sum of all 16 bit words in the header.  For purposes of

//  computing the checksum, the value of the checksum field is zero."

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 (unsigned short)(~sum);

}

// Source IP, source port, target IP, target port from the command line arguments

int main(int argc, char *argv[])

{

int sd;

// No data/payload just datagram

char buffer[PCKT_LEN];

// Our own headers' structures

struct ipheader *ip = (struct ipheader *) buffer;

struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));

// Source and destination addresses: IP and port

struct sockaddr_in sin, din;

int one = 1;

const int *val = &one;

 

memset(buffer, 0, PCKT_LEN);

 

if(argc != 5)

{

printf("- Invalid parameters!!!\n");

printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);

exit(-1);

}

 

// Create a raw socket with UDP protocol

sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);

if(sd < 0)

{

perror("socket() error");

// If something wrong just exit

exit(-1);

}

else

printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");

 

// The source is redundant, may be used later if needed

// The address family

sin.sin_family = AF_INET;

din.sin_family = AF_INET;

// Port numbers

sin.sin_port = htons(atoi(argv[2]));

din.sin_port = htons(atoi(argv[4]));

// IP addresses

sin.sin_addr.s_addr = inet_addr(argv[1]);

din.sin_addr.s_addr = inet_addr(argv[3]);

 

// Fabricate the IP header or we can use the

// standard header structures but assign our own values.

ip->iph_ihl = 5;

ip->iph_ver = 4;

ip->iph_tos = 16;
// Low delay

ip->iph_len = sizeof(struct ipheader) + sizeof(struct udpheader);

ip->iph_ident = htons(54321);

ip->iph_ttl = 64;
// hops

ip->iph_protocol = 17;
// UDP

// Source IP address, can use spoofed address here!!!

ip->iph_sourceip = inet_addr(argv[1]);

// The destination IP address

ip->iph_destip = inet_addr(argv[3]);

 

// Fabricate the UDP header. Source port number, redundant

udp->udph_srcport = htons(atoi(argv[2]));

// Destination port number

udp->udph_destport = htons(atoi(argv[4]));

udp->udph_len = htons(sizeof(struct udpheader));

// Calculate the checksum for integrity

ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct udpheader));

// Inform the kernel do not fill up the packet structure. we will build our own...

if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)

{

perror("setsockopt() error");

exit(-1);

}

else

printf("setsockopt() is OK.\n");

 

// Send loop, send for every 2 second for 100 count

printf("Trying...\n");

printf("Using raw socket and UDP protocol\n");

printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));

 

int count;

for(count = 1; count <=20; count++)

{

if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)

// Verify

{

perror("sendto() error");

exit(-1);

}

else

{

printf("Count #%u - sendto() is OK.\n", count);

sleep(2);

}

}

close(sd);

return 0;

}

 

[root@bakawali testraw]#gcc rawudp.c -o rawudp

[root@bakawali testraw]#./rawudp

- Invalid parameters!!!

- Usage ./rawudp <source hostname/IP> <source port> <target hostname/IP> <target port>

[root@bakawali testraw]# ./rawudp 192.168.10.10 21 203.106.93.91 8080

socket() - Using SOCK_RAW socket and UDP protocol is OK.

setsockopt() is OK.

Trying...

Using raw socket and UDP protocol

Using Source IP: 192.168.10.10 port: 21, Target IP: 203.106.93.91 port: 8080.

Count #1 - sendto() is OK.

Count #2 - sendto() is OK.

Count #3 - sendto() is OK.

Count #4 - sendto() is OK.

Count #5 - sendto() is OK.

Count #6 - sendto() is OK.

Count #7 - sendto() is OK.

...

 

 

You can use network monitoring tools to capture the raw socket datagrams at the target machine to see the effect.  The following is a raw socket and tcp program example.

[root@bakawali testraw]#
cat rawtcp.c

//---cat rawtcp.c---

// Run as root or SUID 0, just datagram no data/payload

#include <unistd.h>

#include <stdio.h>

#include <sys/socket.h>

#include <netinet/ip.h>

#include <netinet/tcp.h>

// Packet length

#define PCKT_LEN 8192

 

// May create separate header file (.h) for all

// headers' structures

// IP header's structure

struct ipheader {

 unsigned char      iph_ihl:5,/* Little-endian */

                    iph_ver:4;

 unsigned char      iph_tos;

 unsigned short int iph_len;

 unsigned short int iph_ident;

 unsigned char      iph_flags;

 unsigned short int iph_offset;

 unsigned char      iph_ttl;

 unsigned char      iph_protocol;

 unsigned short int iph_chksum;

 unsigned int       iph_sourceip;

 unsigned int       iph_destip;

};

 

/* Structure of a TCP header */

struct tcpheader {

 unsigned short int tcph_srcport;

 unsigned short int tcph_destport;

 unsigned int       tcph_seqnum;

 unsigned int       tcph_acknum;

 unsigned char      tcph_reserved:4, tcph_offset:4;

 // unsigned char tcph_flags;

  unsigned int

       tcp_res1:4,      /*little-endian*/

       tcph_hlen:4,     /*length of tcp header in 32-bit words*/

       tcph_fin:1,      /*Finish flag "fin"*/

       tcph_syn:1,      /*Synchronize sequence numbers to start a connection*/

       tcph_rst:1,      /*Reset flag */

       tcph_psh:1,      /*Push, sends data to the application*/

       tcph_ack:1,      /*acknowledge*/

       tcph_urg:1,      /*urgent pointer*/

       tcph_res2:2;

 unsigned short int tcph_win;

 unsigned short int tcph_chksum;

 unsigned short int tcph_urgptr;

};

 

// Simple checksum function, may use others such as Cyclic Redundancy Check, CRC

unsigned short csum(unsigned short *buf, int len)

{

        unsigned long sum;

        for(sum=0; len>0; len--)

                sum += *buf++;

        sum = (sum >> 16) + (sum &0xffff);

        sum += (sum >> 16);

        return (unsigned short)(~sum);

}

 

int main(int argc, char *argv[])

{

int sd;

// No data, just datagram

char buffer[PCKT_LEN];

// The size of the headers

struct ipheader *ip = (struct ipheader *) buffer;

struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof(struct ipheader));

struct sockaddr_in sin, din;

int one = 1;

const int *val = &one;

 

memset(buffer, 0, PCKT_LEN);

 

if(argc != 5)

{

printf("- Invalid parameters!!!\n");

printf("- Usage: %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);

exit(-1);

}

 

sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);

if(sd < 0)

{

   perror("socket() error");

   exit(-1);

}

else

printf("socket()-SOCK_RAW and tcp protocol is OK.\n");

 

// The source is redundant, may be used later if needed

// Address family

sin.sin_family = AF_INET;

din.sin_family = AF_INET;

// Source port, can be any, modify as needed

sin.sin_port = htons(atoi(argv[2]));

din.sin_port = htons(atoi(argv[4]));

// Source IP, can be any, modify as needed

sin.sin_addr.s_addr = inet_addr(argv[1]);

din.sin_addr.s_addr = inet_addr(argv[3]);

// IP structure

ip->iph_ihl = 5;

ip->iph_ver = 4;

ip->iph_tos = 16;

ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);

ip->iph_ident = htons(54321);

ip->iph_offset = 0;

ip->iph_ttl = 64;

ip->iph_protocol = 6;
// TCP

ip->iph_chksum = 0;
// Done by kernel

 

// Source IP, modify as needed, spoofed, we accept through command line argument

ip->iph_sourceip = inet_addr(argv[1]);

// Destination IP, modify as needed, but here we accept through command line argument

ip->iph_destip = inet_addr(argv[3]);

 

// The TCP structure. The source port, spoofed, we accept through the command line

tcp->tcph_srcport = htons(atoi(argv[2]));

// The destination port, we accept through command line

tcp->tcph_destport = htons(atoi(argv[4]));

tcp->tcph_seqnum = htonl(1);

tcp->tcph_acknum = 0;

tcp->tcph_offset = 5;

tcp->tcph_syn = 1;

tcp->tcph_ack = 0;

tcp->tcph_win = htons(32767);

tcp->tcph_chksum = 0;
// Done by kernel

tcp->tcph_urgptr = 0;

// IP checksum calculation

ip->iph_chksum = csum((unsigned short *) buffer, (sizeof(struct ipheader) + sizeof(struct tcpheader)));

 

// Inform the kernel do not fill up the headers' structure, we fabricated our own

if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)

{

    perror("setsockopt() error");

    exit(-1);

}

else

   printf("setsockopt() is OK\n");

 

printf("Using:::::Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));

 

// sendto() loop, send every 2 second for 50 counts

unsigned int count;

for(count = 0; count < 20; count++)

{

if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)

// Verify

{

   perror("sendto() error");

   exit(-1);

}

else

   printf("Count #%u - sendto() is OK\n", count);

sleep(2);

}

close(sd);

return 0;

}

 

[root@bakawali testraw]#gcc rawtcp.c -o rawtcp

[root@bakawali testraw]#./rawtcp

- Invalid parameters!!!

- Usage: ./rawtcp <source hostname/IP> <source port> <target hostname/IP> <target port>

[root@bakawali testraw]# ./rawtcp 10.10.10.100 23 203.106.93.88 8008

socket()-SOCK_RAW and tcp protocol is OK.

setsockopt() is OK

Using:::::Source IP: 10.10.10.100 port: 23, Target IP: 203.106.93.88 port: 8008.

Count #0 - sendto() is OK

Count #1 - sendto() is OK

Count #2 - sendto() is OK

Count #3 - sendto() is OK

Count #4 - sendto() is OK

...

 

抱歉!评论已关闭.