Greetings PEN-TESTers!
AngryPacket Security is proud to announce the release of mothra-v1. mothra is a banner grabber that has some nice features including various protocol negotiations (ie: telnet, ntp...), file logging, highly configurable port ranges and lists, host range scanning (up to a class C) and c0l0rized output. :) Hopefully some will find it useful. Please feel free to send comments, suggestions or patches. Cheers, -- Josha Bronson [EMAIL PROTECTED] AngryPacket Security
/* $Id: mothra.c,v 1.189 2002/02/27 23:58:40 dmuz Exp $ */ /* AngryPacket Security - http://sec.angrypacket.com */ /* mothra - a monstrous yet graceful banner graber */ /* this is mothra version 1 */ /* feel free to send any bugfixes, patches, comments, suggestions, etc */ /* o o xo__ \__/ __ox \_ \ (__) / _/ \_-[xxxx]-_/ \ - - / _/ - -- - \_ _/ { AP } \_ /----/\{ }/\----\ \/ */ /* by dmuz - [EMAIL PROTECTED] */ /* with massive amounts of leet code from methodic */ /* also some "pointers" by freek... heh */ /* mothra was developed on OpenBSD for *BSD. It's been tested on OpenBSD, * NetBSD and FreeBSD. It should work on most Linux distributions too. */ /* Add -DDEBUG for debug mode (not recommened) */ #include <stdio.h> #include <ctype.h> #include <errno.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <sysexits.h> #include <sys/types.h> #include <sys/time.h> #include <sys/fcntl.h> #include <unistd.h> #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h> #define IPSIZE 17 /* enough to hold 12 digits, 4 dots, and a NULL */ #define MAX_BANNER_SIZE 512 #define MAX_PORTS 65535 #define FTP 21 #define TELNET 23 #define SMTP 25 #define TIME 37 #define HTTP 80 #define POP3PW 106 #define POP3 110 #define IDENT 113 #define IMAP4 143 #define RED "\E[1;31;40m" #define YELLOW "\E[1;33;40m" #define WHITE "\E[0;38;40m" #define ANGRYPACKET_OWNZ_YOU 1 /* global buffer to store data */ char buf[MAX_BANNER_SIZE+1]; /* keep track of connect state */ int state=0; /* recv() timeout variable, default is 15 seconds */ int u_timeout=15; /* verbose output variable */ int verbose=0; extern int errno; /* usage */ //XXX add EX: or example usages here void usage(void) { fprintf(stderr,"\nUSAGE: mothra -H <host_range> -h <host> -p <ports> -r <ports>" " -t <timeout> -f <logfile> -cv\n"); fprintf(stderr,"\t-H\t\thost IP range to scan\n"); fprintf(stderr,"\t-h\t\tsingle hostname to scan\n"); fprintf(stderr,"\t-p\t\tcomma seperated ports to grab\n"); fprintf(stderr,"\t-r\t\trange of ports (ex. 1-10)\n"); fprintf(stderr,"\t-t\t\ttimeout in seconds for a connection to a port\n"); fprintf(stderr,"\t-f\t\tlogfile to record banners in\n"); fprintf(stderr,"\t-c\t\tprint banners in color\n"); fprintf(stderr,"\t-v\t\tverbose output\n\n"); exit(0); } /* omg... ph33r!!! */ void ph33r(int color_out) { if(color_out) { fprintf(stderr, RED "\nmothra by dmuz and methodic - AngryPacket Security\n\n" WHITE ); } else { fprintf(stderr,"\nmothra by dmuz and methodic - AngryPacket Security\n\n"); } }; /* timer signal function */ void catchsignal() { state = 1; if(verbose) printf("timed out.\n"); } int parse_banner(char *banner, const char *delim) { int len; char *buf_p, *banner_p, *p; len = strlen(delim); banner_p = (char *)malloc(strlen(banner)+1); bzero(banner_p, strlen(banner)+1); for(buf_p = strtok(banner, "\n"); buf_p != NULL;) { p = strstr(buf_p, delim); if(p) { memmove(banner_p, (p+len), strlen(buf_p)-len); } buf_p = strtok(NULL, "\n"); } if(banner_p) { strncpy(banner, banner_p, MAX_BANNER_SIZE); } else { strncpy(banner, "no banner available", MAX_BANNER_SIZE); } free(banner_p); return(0); } int do_port_hook(int port, int sock) { char *http_s = "HEAD / HTTP/1.0\n\n"; char *identd_s = "VERSION\n"; if(port == HTTP) { send(sock, http_s, strlen(http_s), 0); } if(port == IDENT) { send(sock, identd_s, strlen(identd_s), 0); } return(0); } /* preprocess data to port if we have a hook */ int process_port(int port, int sock) { int x, i=0, j=0, result=0; unsigned int y; unsigned long epoch = 2208988800ul; unsigned char tmpbuf[MAX_BANNER_SIZE+1], *p=NULL, obuf[4]; time_t timedate; struct timeval timeout; fd_set fds; /* set timeout values for recv() */ timeout.tv_sec = u_timeout; timeout.tv_usec = 0; FD_ZERO(&fds); FD_SET(sock, &fds); fcntl(sock, F_SETFL, O_NONBLOCK); select(sock+1, &fds, NULL, NULL, &timeout); if(port == FTP) { /* loop to strip out ftp "messages" */ do { bzero(tmpbuf, MAX_BANNER_SIZE+1); result = recv(sock, tmpbuf, MAX_BANNER_SIZE, 0); if( result == -1 ) { if(verbose) printf(" * recv timed out for port %d, skipping\n", port); return(result); } }while(strstr(tmpbuf, "220-")); strncpy(buf, tmpbuf, MAX_BANNER_SIZE); } if(port == TELNET) { do { sleep(1); /* i cant fscking believe we need this */ bzero(tmpbuf, MAX_BANNER_SIZE+1); result = recv(sock, tmpbuf, MAX_BANNER_SIZE, 0); if( result == -1 ) { if(verbose) printf(" * recv timed out for port %d, skipping\n", port); return(result); } for(i = 0; i < result; i++) { /* we need to check every 3rd response, ie 0, 3, 9, 12, etc */ if((i % 3) == 0 && i > 0) { #if DEBUG printf("recv(%3u, %3u, %3u) [num=%2d] [seq=%2d]\n", tmpbuf[i-3], tmpbuf[i-2], tmpbuf[i-1], ++j, i); #endif if(tmpbuf[i-3] != 255) { /* not a telnet IAC */ bzero(buf, MAX_BANNER_SIZE+1); i=0; for(j = 0; j < result; j++) { #if DEBUG printf("%u,", tmpbuf[j]); #endif /* skip any telnet commands we still may have in * the buffer */ if(tmpbuf[j] == 255) { j++; j++; } else if(tmpbuf[j] != 0 && tmpbuf[j] != 13) { buf[i] = tmpbuf[j]; i++; } } buf[i] = '\0'; return(strlen(buf)); } } } /* if we recieved a telnet command, respond to it */ /* most of code ripped from netcat */ p = tmpbuf; x = strlen(tmpbuf); while(x > 0) { obuf[0] = 255; p++; x--; if( (*p == 251) || (*p == 252)) y = 254; if( (*p == 253) || (*p == 254)) y = 252; if(y) { obuf[1] = y; p++; x--; obuf[2] = *p; send(sock, obuf, 3, 0); y = 0; } p++; x--; } }while(p != NULL); #if DEBUG printf("telnet timed out.. cleaning up\n"); #endif } if(port == TIME) { bzero(tmpbuf, MAX_BANNER_SIZE+1); result = recv(sock, &timedate, sizeof(timedate), 0); if( result == -1 ) { if(verbose) printf(" * recv timed out for port %d, skipping\n", port); return(result); } timedate = ntohl((u_long)timedate) - epoch; snprintf(buf, MAX_BANNER_SIZE, "%s", ctime(&timedate)); } if(result == 0) { bzero(buf, MAX_BANNER_SIZE+1); result = recv(sock, buf, MAX_BANNER_SIZE, 0); if( result == -1 ) { if(verbose) printf(" * recv timed out for port %d, skipping\n", port); } } return result; } /* post process a banner if we want */ int post_process(int port, char *banner) { int i=1; char *banner_p; banner_p = (char *)malloc(strlen(banner)+1); bzero(banner_p, strlen(banner)+1); if(port == FTP) { if(strstr(banner, "220 ")) parse_banner(banner, "220 "); } if(port == SMTP) { parse_banner(banner, "220 "); } if(port == HTTP) { parse_banner(banner, "Server: "); } if(port == POP3PW) { parse_banner(banner, "200 "); } if(port == POP3) { parse_banner(banner, "+OK "); } if(port == IMAP4) { parse_banner(banner, "* OK "); } /* chop off any newline chars */ i = (strlen(banner)) - 1 ; while(banner[i] == '\r' || banner[i] == '\n') { banner[i] = '\0'; i--; } free(banner_p); return 0; } /* record open port banners to a file */ void log(int port, char *logfile, char *banner) { FILE *log_p; if ((log_p = fopen(logfile, "a+")) == NULL) { fprintf(stderr,"\ncould not open log file %s\n", logfile); } else { fprintf(log_p, "port %i: %s\n", port, banner); fclose(log_p); } } /* like, get some banners brah! most excellent! */ int main(int argc, char *argv[]) { /* network vars */ int sock; char *hostname=NULL, tmphost[IPSIZE]; char *host_r[5]; int start_addr=0, end_addr=0; int num_hosts=0; struct sockaddr_in s; /* inet socket address structure */ struct hostent *host_ent; /* host info structure */ /* var args */ int ch; char *ap; int start_port=0; int ports[MAX_PORTS+1]; int range[3]; int i=0, nports =0; /* extra variables */ int color_out=0; int result=0; /* connect() timeout struct */ struct itimerval itv; /* signal structure */ struct sigaction sig; /* file shit */ FILE *log_p; char *logfile = NULL; bzero(ports, MAX_PORTS+1); /* args */ while ((ch = getopt(argc, argv, "h:H:p:r:t:f:cv")) != -1) { switch (ch) { case 'H': /* split the dotted quad */ ap = strtok(optarg, "."); for(i = 0; i != 4; i++) { if(ap == NULL) { fprintf(stderr,"\nSyntax error in host range argument.\n"); usage(); } host_r[i] = ap; ap = strtok(NULL, "."); } /* split the range argument */ ap = strtok(host_r[3], "-"); for(i = 0; i != 2; i++) { host_r[4] = ap; if(ap == NULL) { fprintf(stderr,"\nSyntax error in host range argument.\n"); usage(); } ap = strtok(NULL, "-"); } /* test each of member the dotted quad for correctness */ for(i = 0; i != 5; i++) { if (atoi(host_r[3]) >= atoi(host_r[4])) { fprintf(stderr,"\nSyntax error in host range argument.\n"); usage(); } if (host_r[i] == NULL || atoi(host_r[i]) > 255 || atoi(host_r[i]) < 0) { fprintf(stderr,"\nSyntax error in host range argument.\n"); usage(); } } start_addr = atoi(host_r[3]); end_addr = atoi(host_r[4]); num_hosts = end_addr - start_addr; break; case 'h': hostname = optarg; break; case 'p': ap = strtok(optarg, ","); for(i = 0; ap; i++) { ports[i] = atoi(ap); if((ports[i] == 0) || (ports[i] > 65535) || (ports[i] < 0)) { fprintf(stderr,"\nSyntax error in port(s) list argument.\n"); usage(); } ap = strtok(NULL, ","); } nports = i; /* number of ports to check */ break; case 'r': ap = strtok(optarg, "-"); for(i = 0; i != 2; i++) { if(ap == NULL) { fprintf(stderr,"\nSyntax error in port range argument.\n"); usage(); } range[i] = atoi(ap); if(range[i] == 0) { fprintf(stderr,"\nSyntax error in port range argument.\n"); usage(); } ap = strtok(NULL, "-"); } if(range[0] >= range[1]) { fprintf(stderr,"\nSyntax error in port range argument.\n"); usage(); } start_port=range[0]; break; case 't': u_timeout = atoi(optarg); break; case 'f': logfile = optarg; break; case 'c': color_out = 1; break; case 'v': verbose = 1; break; default: usage(); } } argc -= optind; argv += optind; /* -p and -r can't both be specified */ if(range[0] && nports) { printf("\n-p and -r are mutually exclusive dude\n"); usage(); } /* build our ports[] array if we are using a range */ if(range[0]) { for(i = range[0]; i < range[1]+1; i++) { ports[i] = i; } nports = i; start_port = range[0]; } else { start_port = 0; } // if(!hostname || !nports) { if(!nports) { usage(); } /* print out our mad greetz */ ph33r(color_out); num_hosts++; while(num_hosts > 0) { if(start_addr && end_addr) { /* build our hostname */ snprintf(tmphost, IPSIZE, "%s.%s.%s.%d", host_r[0], host_r[1], host_r[2], start_addr); hostname = (char *)malloc(IPSIZE); strncpy(hostname, tmphost, IPSIZE); start_addr++; } /* attempt to open the logfile */ if(logfile) { if((log_p = fopen(logfile, "a+")) == NULL) { fprintf(stderr, "could not open log file %s\n", logfile); } else { fprintf(log_p, "-- - banner scan for [%s] - --\n", hostname); fclose(log_p); } } printf("-> starting banner scan for %s\n", hostname); /* zero socket structure */ bzero(&s, sizeof(s)); if((host_ent = gethostbyname(hostname)) == NULL) { fprintf(stderr, " * unknown host: %s\n", hostname); break; } else { memcpy((char*)&s.sin_addr, host_ent->h_addr, host_ent->h_length); } if(start_port) { i = start_port; } else { i = 0; } for(; i < nports; i++) { /* protocol and port information */ s.sin_family = AF_INET; s.sin_port = htons(ports[i]); /* setup the socket */ sock = socket(AF_INET, SOCK_STREAM, 0); /* create timeout values for connect() */ itv.it_value.tv_sec = u_timeout; itv.it_value.tv_usec = 0; itv.it_interval = itv.it_value; setitimer(ITIMER_REAL, &itv, NULL); sig.sa_handler = catchsignal; sigemptyset(&sig.sa_mask); sig.sa_flags = 0; sigaction(SIGALRM, &sig, 0); if(verbose) printf("-> connecting to port [%d] on %s.. ", ports[i], hostname); fflush(stdout); if(connect(sock, (struct sockaddr*)&s, sizeof(s)) == 0) { itv.it_value.tv_sec=0; itv.it_value.tv_usec=0; itv.it_interval=itv.it_value; setitimer(ITIMER_REAL,&itv,NULL); if(verbose) printf("connected!\n"); do_port_hook(ports[i], sock); if((result = process_port(ports[i], sock)) > 0){ post_process(ports[i], buf); if(logfile) { log(ports[i], logfile, buf); } else { if(color_out) { printf(YELLOW "port %d: %s\n" WHITE, ports[i], buf); } else { printf("port %d: %s\n", ports[i], buf); } } } } else if (state == 1) { /* timed out */ state=0; } else { /* couldn't connect */ if(verbose) { printf("connect failed.\n"); #if DEBUG printf("DEBUG ERROR: %d\n", errno); #endif } } close(sock); } if(logfile) { if((log_p = fopen(logfile, "a+")) == NULL) { fprintf(stderr, "could not open log file %s\n", logfile); } else { fprintf(log_p, "\n"); fclose(log_p); } } printf("-> finished banner scan for %s\n", hostname); num_hosts--; if(start_addr && end_addr) { free(hostname); } } printf("-> visit http://sec.angrypacket.com for security tools and info\n"); return EX_OK; }
---------------------------------------------------------------------------- This list is provided by the SecurityFocus Security Intelligence Alert (SIA) Service. For more information on SecurityFocus' SIA service which automatically alerts you to the latest security vulnerabilities please see: https://alerts.securityfocus.com/
