

/*-------------------------------------------------------------------*
* SyncDet v4.0 (c) Jason Hamilton            Created:      01.20.98 *
*                                            Last updated: 10.20.98 *
*-------------------------------------------------------------------*
* This little program scans for any type of
* DoS that eats up tcp connections, or vhost/clones
* The format for netstat is based on the output from BSD/OS,
* but I belive it runs on freebsd as well. Linux I know has
* a slightly diff format, so may need some tweaking for that OS.
*
* Syntax: ./syncdet <number-to-find>

SAMPLE OUTPUT:

    Listing c-blocks with greater-than 6 connections.


---  208.204.44 -> 9  matches ------------
             x7    voyager.provalue.net (6667)
                   stillwater.webstreetonline.com (6667)
                   cruzzin.webstreetonline.com (6661)
--- 207.207.201 -> 19 matches ------------
             x19   linus.innovex-das.com (6667)
---    216.46.2 -> 12 matches ------------
             x11   shell.optima-dialup.com (6667)
                   216.46.2.241 (6661)
---  204.57.118 -> 8  matches ------------
             x2    alamo.satexas.com (6663)
             x5    userservice.org (6663)
                   satexas.com (6668)
---   209.58.49 -> 9  matches ------------
                   209.58.49.95 (6666)
                   209.58.49.92 (6662)
                   209.58.49.167 (6662)
                   209.58.49.210 (6662)
                   209.58.49.211 (6666)
                   209.58.49.73 (6667)
                   209.58.49.202 (6669)
                   209.58.49.152 (6667)
                   209.58.49.140 (6664)
--- 208.165.179 -> 8  matches ------------
                   loves.eggdrops.net (6666)
                   screwed.chelsea.clint0n.cx (6660)
                   flunked.my.final.ex.am (6660)
                   is.a.chatass.com (6667)
                   very.eleet.com (6660)
                   eye.am (6662)
                   d139.gw-fr2.kirenet.net (6669)
                   microsoft.linux.am (6661)
--- 208.165.180 -> 7  matches ------------
                   wanted.by.the.feds.org (6667)
                   back.to.school.ex.am (6667)
                   i.not.as.drnk.as.u.thnk.eye.am (6664)
                   v-usr117.bos.kirenet.net (6667)
                   my.bot.owns.the.feds.org (6667)
                   sold.47bottles.of.viagra.to.clint0n.cx (6667)
                   guessed.y0ur.cc (6667)


Total netblocks listed: 46
Total clones found    : 115
Total resolved users  : 315
Total unresolved users: 59
Total listed users    : 374


Processed             : 3989 connections... 

</SAMPLE>

*-------------------------------------------------------------------*
*/


#define NETSTAT_PATH "/usr/bin/netstat"


#include <netdb.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <stdlib.h>
#include <netinet/in.h>


void            process_log(), write_all(char *ip),
                add_ip(char *i, char *target);
long            process_ip(), check_ip(char *ip);


struct ip_list {
    char            ip[25];
    char            ip2[25];
    char            target[30];
    long            num;
    long            clone;
    long            done;
    struct ip_list *nx;
}              *iphead = NULL;


long            CONN;


main(int argc, char **argv)
{
    struct timeval  timeout;
    char            ptr[300];
    fd_set          fdvar;


    if (argv[1] == NULL) {
       printf("\n\nSyntax: %s <num_con>\n", argv[0]);
       printf("        Where num_con is the number of connections to alert at.\n\n");
       exit(0);
    }
    CONN = atoi(argv[1]);


    /* sprintf(ptr, "%s -an | grep tcp > netstat.log", NETSTAT_PATH); */
    sprintf(ptr, "%s -an -f inet | grep tcp > netstat.log", NETSTAT_PATH);
    system(ptr);
    sleep(2);
    process_log();
    unlink("netstat.log");
}


long
process_ip()
{
    struct ip_list *c;
    char            s[300], tmp[25];
    long            x = 0;
    c = iphead;


    printf("--- Possible Clone/VHOST Detection Results > %d per c-class\n\n",
           CONN);


    while (c != NULL) {
       if (c->num > CONN && c->done == 0) {
         x++;
         printf("--- %11s -> %-2d matches ------------\n",
                c->ip2, c->num);
         write_all(c->ip2);
       }
       c = c->nx;
    }
    printf("\n");
    return x;
}


void
write_all(char *ip)
{
    struct ip_list *c;
    char            addr[5], *ptr;
    long            toggle = 0;
    struct hostent *h;


    char            s[300];
    c = iphead;


    while (c) {
       if (strcmp(ip, c->ip2) == 0) {
         c->done = 666;
         sscanf(c->ip, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]);
         h = gethostbyaddr(addr, 4, AF_INET);
         if (h == NULL) {
          toggle = 0;
         } else
          toggle = 1;
         if (c->clone > 1) {
          printf("             x%-4d %-15s -> %s [%s]\n",
                 c->clone, c->ip, c->target,
              toggle == 0 ? "unresolved" : h->h_name);
         } else
          printf("                   %-15s -> %s [%s]\n",
                 c->ip, c->target, toggle == 0 ? "unresolved" : h->h_name);
       }
       c = c->nx;
    }
}


void
add_ip(char *ip, char *target)
{
    char           *ptr, host[100], host2[100], temp[100];
    struct ip_list *n, *c;
    n = (struct ip_list *) malloc(sizeof(struct ip_list));


    ptr = strtok(ip, ".");
    sprintf(host, "%s", ptr);
    ptr = strtok(NULL, ".");
    sprintf(temp, "%s.%s", host, ptr);
    ptr = strtok(NULL, ".");
    sprintf(host, "%s.%s", temp, ptr);
    strcpy(host2, host);
    ptr = strtok(NULL, ".");
    sprintf(temp, "%s.%s", host, ptr);
    strcpy(host, temp);
    ptr = strtok(NULL, "");


    if (n != NULL) {
       strcpy(n->ip, host);
       strcpy(n->ip2, host2);
       strcpy(n->target, target);
       n->num = 1;
       n->clone = 1;
       n->done = 0;
       if (iphead == NULL) {
         iphead = n;
       } else {
         c = iphead;
         while (c->nx != NULL)
          c = c->nx;
         c->nx = n;
       }
    }
}


long
check_ip(char *ip)
{
    char           *ptr, host[100], temp[100];
    long            clone_count = 0;
    struct ip_list *c;
    c = iphead;


    ptr = strtok(ip, ".");
    strcpy(host, ptr);
    ptr = strtok(NULL, ".");
    sprintf(temp, "%s.%s", host, ptr);
    ptr = strtok(NULL, ".");
    sprintf(host, "%s.%s", temp, ptr);
    ptr = strtok(NULL, ".");
    sprintf(temp, "%s.%s", host, ptr);
    ptr = strtok(NULL, "");


    while (c != NULL) {
       if (strcmp(c->ip2, host) == 0)
         c->num++;
       if (strcmp(c->ip, temp) == 0) {
         c->clone++;
         clone_count = c->clone;
       }
       c = c->nx;
    }
    return clone_count;
}


void
process_log()
{
    FILE           *fp;
    long            i = 0;
    char            b[1000], *dat, s[300], s2[300], *target;


    if ((fp = fopen("netstat.log", "r")) == NULL) {
       printf("ERROR: Unable to open \"netstat.log\"\n");
       exit(0);
    }
    while (fgets(b, 1000, fp)) {
       i++;
       dat = strtok(b, " ");
       dat = strtok(NULL, " ");  /* recvq */
       dat = strtok(NULL, " ");  /* sendq */
       target = strtok(NULL, " ");
       dat = strtok(NULL, " ");
       strcpy(s, dat);
       strcpy(s2, dat);
       dat = strtok(target, ".");
       dat = strtok(NULL, ".");
       dat = strtok(NULL, ".");
       dat = strtok(NULL, ".");
       target = strtok(NULL, ".");   /* connected port */
       if (strcmp(s2, "*.*") != 0) {
         if (check_ip(s) < 2)
          add_ip(s2, target);
       }
    }


    if (process_ip() > 0) {
       printf("\nProcessed %d connections...\n", i);
    }
}
