Thread: Question on ICMP echo request

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    4

    Question Question on ICMP echo request

    The below program was posted long time ago in this forum. However, it just can modify the IP and ICMP headers. I would like to ask what should I do if I want to edit the Ethernet header also.

    Any help will be highly appreciated!

    Code:
    /*
    * pinger.c
    * This is a ping imitation program
    * It will send an ICMP ECHO packet to the server of
    * your choice and listen for an ICMP REPLY packet
    * Have fun!
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <linux/ip.h>
    #include <linux/icmp.h>
    #include <string.h>
    #include <unistd.h>
    
    
    char dst_addr[15];
    char src_addr[15];
    
    unsigned short in_cksum(unsigned short *, int);
    void parse_argvs(char**, char*, char* );
    void usage();
    char* getip();
    
    int main(int argc, char* argv[])
    {
    struct iphdr* ip;
    struct iphdr* ip_reply;
    struct icmphdr* icmp;
    struct sockaddr_in connection;
    char* packet;
    char* buffer;
    int sockfd;
    int optval;
    int addrlen;
    
    if (getuid() != 0)
    {
    fprintf(stderr, "%s: root privelidges needed\n", *(argv + 0));
    exit(EXIT_FAILURE);
    }
    
    parse_argvs(argv, dst_addr, src_addr);
    printf("Source address: %s\n", src_addr);
    printf("Destination address: %s\n", dst_addr);
    
    /*
    * allocate all necessary memory
    */
    ip = malloc(sizeof(struct iphdr));
    ip_reply = malloc(sizeof(struct iphdr));
    icmp = malloc(sizeof(struct icmphdr));
    packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
    buffer = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
    /****************************************************************/
    
    ip = (struct iphdr*) packet;
    icmp = (struct icmphdr*) (packet + sizeof(struct iphdr));
    
    /*
    * here the ip packet is set up except checksum
    */
    ip->ihl = 5;
    ip->version = 4;
    ip->tos = 0;
    ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr);
    ip->id = htons(random());
    ip->ttl = 255;
    ip->protocol = IPPROTO_ICMP;
    ip->saddr = inet_addr(src_addr);
    ip->daddr = inet_addr(dst_addr);
    
    
    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
    {
    perror("socket");
    exit(EXIT_FAILURE);
    }
    
    /*
    * IP_HDRINCL must be set on the socket so that
    * the kernel does not attempt to automatically add
    * a default ip header to the packet
    */
    
    setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int));
    
    /*
    * here the icmp packet is created
    * also the ip checksum is generated
    */
    icmp->type = ICMP_ECHO;
    icmp->code = 0;
    icmp->un.echo.id = 0;
    icmp->un.echo.sequence = 0;
    icmp->checksum = 0;
    icmp-> checksum = in_cksum((unsigned short *)icmp, sizeof(struct icmphdr));
    
    ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));
    
    connection.sin_family = AF_INET;
    connection.sin_addr.s_addr = inet_addr(dst_addr);
    
    /*
    * now the packet is sent
    */
    
    sendto(sockfd, packet, ip->tot_len, 0, (struct sockaddr *)&connection, sizeof(struct sockaddr));
    printf("Sent %d byte packet to %s\n", sizeof(packet), dst_addr);
    
    /*
    * now we listen for responses
    */
    addrlen = sizeof(connection);
    if (recvfrom(sockfd, buffer, sizeof(struct iphdr) + sizeof(struct icmphdr), 0, (struct sockaddr *)&connection, &addrlen) == -1)
    {
    perror("recv");
    }
    else
    {
    printf("Received %d byte reply from %s:\n", sizeof(buffer), dst_addr);
    ip_reply = (struct iphdr*) buffer;
    printf("ID: %d\n", ntohs(ip_reply->id));
    printf("TTL: %d\n", ip_reply->ttl);
    }
    close(sockfd);
    return 0;
    }
    
    void parse_argvs(char** argv, char* dst, char* src)
    {
    int i;
    if(!(*(argv + 1)))
    {
    /* there are no options on the command line */
    usage();
    exit(EXIT_FAILURE);
    }
    if (*(argv + 1) && (!(*(argv + 2))))
    {
    /*
    * only one argument provided
    * assume it is the destination server
    * source address is local host
    */
    strncpy(dst, *(argv + 1), 15);
    strncpy(src, getip(), 15);
    return;
    }
    else if ((*(argv + 1) && (*(argv + 2))))
    {
    /*
    * both the destination and source address are defined
    * for now only implemented is a source address and
    * destination address
    */
    strncpy(dst, *(argv + 1), 15);
    i = 2;
    while(*(argv + i + 1))
    {
    if (strncmp(*(argv + i), "-s", 2) == 0)
    {
    strncpy(src, *(argv + i + 1), 15);
    break;
    }
    i++;
    }
    
    }
    }
    
    void usage()
    {
    fprintf(stderr, "\nUsage: pinger [destination] <-s [source]>\n");
    fprintf(stderr, "Destination must be provided\n");
    fprintf(stderr, "Source is optional\n\n");
    }
    
    char* getip()
    {
    char buffer[256];
    struct hostent* h;
    
    gethostname(buffer, 256);
    h = gethostbyname(buffer);
    
    return inet_ntoa(*(struct in_addr *)h->h_addr);
    
    }
    /*
    * in_cksum --
    * Checksum routine for Internet Protocol
    * family headers (C Version)
    */
    unsigned short in_cksum(unsigned short *addr, int len)
    {
    register int sum = 0;
    u_short answer = 0;
    register u_short *w = addr;
    register int nleft = len;
    /*
    * Our algorithm is simple, using a 32 bit accumulator (sum), we add
    * sequential 16 bit words to it, and at the end, fold back all the
    * carry bits from the top 16 bits into the lower 16 bits.
    */
    while (nleft > 1)
    {
    sum += *w++;
    nleft -= 2;
    }
    /* mop up an odd byte, if necessary */
    if (nleft == 1)
    {
    *(u_char *) (&answer) = *(u_char *) w;
    sum += answer;
    }
    /* add back carry outs from top 16 bits to low 16 bits */
    sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
    sum += (sum >> 16); /* add carry */
    answer = ~sum; /* truncate to 16 bits */
    return (answer);
    }

  2. #2
    Registered User
    Join Date
    Oct 2005
    Posts
    4

    Question Further Question

    As I want to detect if there is a sniffer(written by me) on the network(hub), i want to ping the suspected host with a mismatched MAC address.

    If a sniffer is on, the network card is in promiscuous mode and it will accept the ICMP echo request(ping) then reply regardless of the wrong MAC. If work, how can I change the MAC in the above program.

    Would my method work for the detection!!!

    Thx for any help!!!

  3. #3
    Unregistered User
    Join Date
    Sep 2005
    Location
    Antarctica
    Posts
    341
    you will need to use raw sockets, which aren't supported in windows.

  4. #4
    Bioport Productions
    Join Date
    Oct 2005
    Posts
    215
    look up ARP Spoofing
    -"What we wish, we readily believe, and what we ourselves think, we imagine others think also."
    PHP Code:
    sadf 

  5. #5
    Registered User
    Join Date
    Oct 2005
    Posts
    4

    I am using Linux

    I am using Linux(Redhat 9)2.22 kernel

  6. #6
    Unregistered User
    Join Date
    Sep 2005
    Location
    Antarctica
    Posts
    341
    well, then look into raw sockets, you should have no problem, they aren't that hard. You will also need to get very familiar with the structure of packets, so find a good tutorial on TCP/IP and ICMP.

  7. #7
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    Quote Originally Posted by rockytriton
    well, then look into raw sockets, you should have no problem, they aren't that hard. You will also need to get very familiar with the structure of packets, so find a good tutorial on TCP/IP and ICMP.
    Correct me if I'm wrong, but as far as I recall, raw sockets are from the Network layer up, you cannot edit the lower layer of the structure (Ethernet, for example). Yes you can write programs with spoofed IPs but not spoofed MACs.
    For changing the MAC, I think you will need to work with the NIC's driver.


    Quote Originally Posted by rockytriton
    you will need to use raw sockets, which aren't supported in windows.
    I don't agree. only windows XP patched with SP2, and other windows machines that didn't want the SP2 on their system were illegally patched by microsoft without the users knowledge.

    And even then, the raw sockets WERE NOT DISABLED! But nearly reduced. So yes, there is no more spoofing on patched windows machines but the raw sockets are still there.

    And as for windows 2003, I think they have a full raw socket support. Security reasons my ass.
    Last edited by Devil Panther; 10-31-2005 at 02:26 AM.
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  8. #8
    Unregistered User
    Join Date
    Sep 2005
    Location
    Antarctica
    Posts
    341
    You may be right about changing the MAC address, it probably is just the IP you can change, it's been a while since I had to do that kind of stuff. You are also right about the raw sockets, they ARE there but you can barely do anything useful with them. You can't send raw SYN or ACK messages or anything good like that, hell I don't know what you actually can do that's useful in the windows limited raw sockets.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. IPv6 ping in windows...problem..lots of ode:(
    By Neill KElly in forum C Programming
    Replies: 3
    Last Post: 04-27-2009, 11:50 PM
  2. another do while question
    By kbpsu in forum C++ Programming
    Replies: 3
    Last Post: 03-23-2009, 12:14 PM
  3. bcopy() question
    By failure_to in forum C Programming
    Replies: 6
    Last Post: 06-04-2004, 04:23 PM
  4. firewall question
    By *ClownPimp* in forum Tech Board
    Replies: 6
    Last Post: 11-04-2003, 08:02 AM
  5. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 09:47 PM