what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

mothra-v1.c

mothra-v1.c
Posted Mar 6, 2002
Authored by Dmuz | Site sec.angrypacket.com

Mothra is a monstrous yet graceful banner grabber for OpenBSD, NetBSD, Freebsd, and Linux.

tags | tool, scanner
systems | linux, netbsd, unix, freebsd, openbsd
SHA-256 | cb9644237c77b9f90cc59dd7d8b65622f9da08315a11d006df88293cb519808d

mothra-v1.c

Change Mirror Download
/* $Id: mothra.c,v 1.190 2002/03/04 20:50:38 dmuz Exp $ */

/* AngryPacket Security - https://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 - dmuz@angrypacket.com */
/* 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 write_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);
bzero(range, 4);
/* 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) {
write_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 https://sec.angrypacket.com for security tools and info\n");
return EX_OK;
}
Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    8 Files
  • 9
    Nov 9th
    3 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    14 Files
  • 12
    Nov 12th
    20 Files
  • 13
    Nov 13th
    63 Files
  • 14
    Nov 14th
    18 Files
  • 15
    Nov 15th
    8 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    18 Files
  • 19
    Nov 19th
    7 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close