/*
######################################################################
# #
# Simple Sniffer with Filter #
# #
# Copyright (C) 2007 Matrix86 #
# #
# This program is free software; you can redistribute it and/or #
# modify it under the terms of the GNU General Public License #
# as published by the Free Software Foundation; either version 2 #
# of the License, or (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# http://www.gnu.org/copyleft/gpl.html #
# #
######################################################################
*/
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <ctype.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <netinet/igmp.h>
#include <regex.h>
FILE * out = NULL;
void usage(char *p){
fprintf(stdout,"\n--------- Sniffer Filter ---------\n");
fprintf(stdout,"Simple sniffer by Matrix86\nThx to Evilsocket\n");
fprintf(stdout,"Usage: %s [opzioni] -i [dispositivo]\n\n",p);
fprintf(stdout,"\tOpzioni disponibili:\n\t\t-f <espressione> : filtro pcap\n");
fprintf(stdout,"\t\t-r <espressione> : regex sul payload\n");
fprintf(stdout,"\t\t-o <file> : file di salvataggio\n");
fprintf(stdout,"\t\t-h : mostra questo help\n");
fprintf(stdout,"Esempio:\n\t%s -f \"port 6667\" -i eth0\n",p);
fprintf(stdout,"\t%s -f \"port 6667\" -o dump.txt -i eth0\n\n");
return;
}
void die(char * error){
fprintf(out,"[ERROR] %s\n",error);
exit(1);
}
char *get_protocols(struct iphdr *ip){
char *ret;
switch(ip->protocol){
case IPPROTO_TCP :
ret = strdup("TCP");
break;
case IPPROTO_UDP :
ret = strdup("UDP");
break;
case IPPROTO_IPIP :
ret = strdup("IP");
break;
case IPPROTO_IGMP :
ret = strdup("IGMP");
break;
case IPPROTO_ICMP :
ret = strdup("ICMP");
break;
}
return ret;
}
int matchreg(const char *string, char *pattern) {
int status;
regex_t re;
if(!regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE|REG_NEWLINE)) {
if(regexec(&re, string, (size_t)0, NULL, 0) == 0) status = 1;
else status = 0;
}
else die("Regex incorretta!");
regfree(&re);
return status;
}
void show_pkt(u_char * pkt,int size,char *ptn_reg){
struct iphdr * ip; // IP Header
struct in_addr addr;
char addr_str[16];
char *payload, *n;
int dataoffset,
i;
u_char *pointer = NULL;
ip = (struct iphdr *) pkt;
switch(ip->protocol){
case IPPROTO_TCP :
dataoffset = sizeof(struct iphdr) + (((struct tcphdr *)(pkt + sizeof(struct iphdr)))->doff * 4);
break;
case IPPROTO_UDP :
dataoffset = sizeof(struct iphdr) + sizeof(struct udphdr);
break;
case IPPROTO_IPIP :
dataoffset = sizeof(struct iphdr) * 2;
break;
case IPPROTO_IGMP :
dataoffset = sizeof(struct iphdr) + sizeof(struct igmp);
break;
case IPPROTO_ICMP :
dataoffset = sizeof(struct iphdr) + sizeof(struct icmphdr);
break;
default :
fprintf(out,"Protocollo sconosciuto");
return;
}
pointer = pkt + dataoffset;
n = payload = calloc(size - dataoffset,1);
for(i = 0; i < (size - dataoffset); i++,n++,pointer++){
if(isprint(*pointer)) *n = *pointer;
}
if(ptn_reg == NULL || matchreg(payload,ptn_reg)){
fprintf(out,"-------------------------------------------------------------\n");
fprintf(out,"Protocollo:\t%s\n",get_protocols(ip));
addr.s_addr = ip->saddr;
inet_ntop(AF_INET,&addr,addr_str,sizeof(addr_str));
fprintf(out,"Sorgente:\t%s\n",addr_str);
addr.s_addr = ip->daddr;
inet_ntop(AF_INET,&addr,addr_str,sizeof(addr_str));
fprintf(out,"Destinatario:\t%s\n",addr_str);
fprintf(out,"Payload:\n%s",payload);
fprintf(out,"\n-------------------------------------------------------------\n\n");
fflush(out);
}
return;
}
int main(int argc,char *argv[]){
char *device=NULL,
*pattern = NULL,
c,
strnetaddr[INET_ADDRSTRLEN],
strnetmask[INET_ADDRSTRLEN],
errbuf[PCAP_ERRBUF_SIZE],
*filtro = NULL;
int datalink,offset;
pcap_t *fd;
u_char *pcap_pkt; // Pachetto attuale
struct pcap_pkthdr pcap_hdr; // Pcap Header Packet
struct bpf_program filter;
bpf_u_int32 netmask,netaddr; // Netmask e Ip del dispositivo di sniffing
if (getuid()){
fprintf(stdout,"Bisogna essere root!\n");
exit(0);
}
if(argc < 2) {
usage(argv[0]);
exit(0);
}
while ((c = getopt (argc, argv, "i:f:r:o:")) != -1){
if(!optarg && c != 'h') c = 'h';
switch (c){
case 'i':
device = strdup(optarg);
break;
case 'f':
filtro= strdup(optarg);
break;
case 'r':
pattern = strdup(optarg);
break;
case 'o':
out=fopen(optarg,"a");
if(out == NULL)
die("Impossibile aprire il file\n");
break;
case 'h':
usage(argv[0]);
exit(0);
break;
default:
usage(argv[0]);
exit(0);
break;
}
}
if(out == NULL) out = stdout;
if(!device) exit(0);
fprintf(out,"Seleziono il device: %s\n",device);
if(pcap_lookupnet(device,&netaddr,&netmask,errbuf) == -1) {
fprintf(out,"Nessun indirizzo assegnato al device %s\n",device);
exit(0);
}
inet_ntop(AF_INET, (void *) &netaddr, strnetaddr, sizeof(strnetaddr));
inet_ntop(AF_INET, (void *) &netmask, strnetmask, sizeof(strnetmask));
fprintf(out,"Netmask: %s\nIndirizzo di rete: %s\n",strnetmask,strnetaddr);
if( (fd = pcap_open_live(device,65535,1,0,errbuf)) <= 0)
die(errbuf);
fprintf(out,"Dispositivo %s inizializzato e settato in Monitor Mode\n",device);
// int pcap_compile(pcap_t * p, struct bpf_ program *fp, char * str,int optimize, bpf_u_int32 netmask);
if(pcap_compile(fd,&filter,filtro,1,netaddr) == -1)
die(pcap_geterr(fd));
if(pcap_setfilter(fd,&filter) == -1)
die(pcap_geterr(fd));
if((datalink = pcap_datalink(fd)) < 0)
die(errbuf);
// Cerchiamo l'offset dell'ip nel pacchetto rispetto il tipo di dispositivo (Thx Evilsocket ;))
switch( datalink )
{
case DLT_RAW : offset = 0; break;
case DLT_PPP :
case DLT_LOOP :
case DLT_NULL : offset = 4; break;
case DLT_PPP_ETHER : offset = 8; break;
case DLT_EN10MB :
case DLT_EN3MB : offset = 14; break;
case DLT_LINUX_SLL :
case DLT_SLIP : offset = 16; break;
case DLT_SLIP_BSDOS :
case DLT_PPP_BSDOS :
case DLT_IEEE802_11 : offset = 24; break;
case DLT_PFLOG : offset = 48; break;
default :
die("Dispositivo non riconosciuto!");
}
fprintf(out,"Inizio sniffing...\n");
// u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);
while((pcap_pkt = pcap_next(fd, &pcap_hdr))){
show_pkt(pcap_pkt + offset, pcap_hdr.len + offset,pattern);
}
free(device);
pcap_close(fd);
exit(0);
}